Android - Prevent text truncation in SearchView suggestions?

三世轮回 提交于 2019-12-17 19:49:21

问题


The suggestions that appear in the default ListView beneath my SearchView contain text that is truncated. I would like the text to be displayed in its entirety (on multiple lines if necessary).

I have come up with two possible ways to solve this but, with no examples to be found on the net, I was hoping someone on here may be able to help...

Approach #1 / Q1: How can I directly access and modify the appearance of the TextViews that hold the SUGGEST_COLUMN_TEXT_1 and SUGGEST_COLUMN_TEXT_1 text?

Approach #2 / Q2: Alternatively, SearchView has a setSuggestionsAdapter(CursorAdapter adapter) method which looks like it may be (more?) suitable than approach #1. Although I have read up on CursorAdapters and have one already implemented in my app, I'm not sure how I would configure one for the SearchView (esp. in terms of accessing the cursor), so could anyone help me out with some general guidance or a skeleton example?

Here is the existing code from my SearchViewFragment class:

public class SearchViewFragment extends Fragment {

public SearchViewFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {

    // Inflate the layout for this fragment
    View fragmentView =  inflater.inflate(R.layout.fragment_search_view, container, false);

    // Use the Search Manager to find the SearchableInfo related to this Activity
    SearchManager searchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
    SearchableInfo searchableInfo = searchManager.getSearchableInfo(getActivity().getComponentName());

    // Bind the Activity's SearchableInfo to the Search View
    SearchView searchView = (SearchView)fragmentView.findViewById(R.id.searchView);
    searchView.setSearchableInfo(searchableInfo);
    searchView.setIconifiedByDefault(false);
    searchView.setSubmitButtonEnabled(true);
    //searchView.setQueryRefinementEnabled(true);

    return fragmentView;
}

}

Update: SOLVED!

Thanks to the accepted answer, I have created this code which is pretty clean and does the job well...

public class SearchViewFragment extends Fragment {

    private static final String LOG_TAG = SearchViewFragment.class.getSimpleName();

    public SearchViewFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setRetainInstance(true); //todo - not working - Remember search term
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View fragmentView =  inflater.inflate(R.layout.fragment_search_view, container, false);

        // Use the Search Manager to find the SearchableInfo related to this Activity
        SearchManager searchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
        SearchableInfo searchableInfo = searchManager.getSearchableInfo(getActivity().getComponentName());

        // Bind the Activity's SearchableInfo to the Search View
        final SearchView searchView = (SearchView)fragmentView.findViewById(R.id.searchView);
        searchView.setSearchableInfo(searchableInfo);
        searchView.setIconifiedByDefault(false);
        searchView.setSubmitButtonEnabled(true);
        //searchView.setQueryRefinementEnabled(true);

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
               //DO whatever you want here on text submit in the search View
                Log.d(LOG_TAG, "onQueryTextSubmit(" + s + ")");

                return true;
            }
            @Override
            public boolean onQueryTextChange(String textChange) {

                Log.d(LOG_TAG, "onQueryTextChange(" + textChange + ")");

                ContentResolver cr = getActivity().getContentResolver();

                Uri uri = DbContentProvider.CONTENT_URI_REAL_PRODUCTS;
                String[] projection = DbContentProvider.getProjectionIn(DbContentProvider.REAL_PRODUCTS_SUGGEST);
                String selection = DbContentProvider.getSelection(false);
                String[] selectionArgs = {Utilities.formatQueryString(textChange)};
                String sortOrder = null;
                Cursor cursor = cr.query(uri, projection, selection, selectionArgs, sortOrder);
                Log.d(LOG_TAG, "Setting setSuggestionsAdapter. cursor: " + cursor);
                searchView.setSuggestionsAdapter(new SearchSuggestionsAdapter(getActivity(), cursor));

                return true;

            }
        });

        return fragmentView;
    }

    private static class SearchSuggestionsAdapter extends SimpleCursorAdapter {

        private static final String[] mVisible = {SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2};
        private static final int[] mViewIds = {R.id.product_name, R.id.product_shelf};

        public SearchSuggestionsAdapter(Context context, Cursor cursor) {

            super(context, R.layout.search_view_suggestions, cursor, mVisible, mViewIds, 0);

        }
        /*
        @Override
        public void bindView(View view, Context context, Cursor cursor) {

            Log.d(LOG_TAG, "bindView(" + view + ", " + context + ", " + cursor + ")");
            super.bindView(view, context, cursor);

        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {

            Log.d(LOG_TAG, "newView(" + context + ", " + cursor + ", " + parent + ")");
            return super.newView(context, cursor, parent);

        }
        */

    }

}

And here is my search_view_suggestions.xml...

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin" >

    <TextView
        android:id="@+id/product_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Product Name placeholder"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/product_shelf"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Product Shelf placeholder" />

</LinearLayout>

...the result is no text truncation. :-)


回答1:


It seems like you want a custom layout for your search view results. I will try to outline some clear steps below:

To make the search view to work we need to have a searchable.xml in the res/xml folder and a content provider at all times.

searchable.xml example:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:searchSuggestAuthority="com.example.searchProvider" ></searchable>

The label and searchSuggestAuthority are required. The searchSuggestAuthority should point to the location of the content provider

Add the intent-filter meta-data to the activity in the manifest. Example:

  <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>

In the activity/fragment, get your searchView object and pass it the custom adapter for displaying the custom layout.

searchView.setSearchableInfo(manager.getSearchableInfo(getActivity().getComponentName()));
        final SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
               //DO whatever you want here on text submit in the search View

                return true;
            }
 @Override
            public boolean onQueryTextChange(String textChange) {


                searchView.setSuggestionsAdapter(new ExampleAdapter(context,yourData));

            }
        };

Make sure the custom adapter extends the cursorAdapter.

public class ExampleAdapter extends CursorAdapter {

    private Cursor cursor;

    private TextView text;

    public ExampleAdapter(Context context, Cursor cursor) {

        super(context, cursor);

        this.cursor= cursor;

    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        text.setText((cursor.getString(cursor.getColumnIndex(YOUR_STRING_KEY));));

    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = inflater.inflate(R.layout.item, parent, false);

        text = (TextView) view.findViewById(R.id.text);

        return view;

    }

}

In the above code R.layout.item refers to your custom xml file that you can use to inflate in the searchview results.

Make sure you are using a content provider though. The searchView doesn't work without one. It doesn't matter even if you are only caching the data on a temporary basis.

Hope this helps!




回答2:


user2511882's answer is perfect, but that constructor is deprecated.

Deprecated :
public ExampleAdapter(Context context, Cursor cursor) {
    super(context, cursor);
    this.cursor= cursor;
}

you can use the below one instead of that.

public ExampleAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
}

and then call it like this.

searchView.setSuggestionsAdapter(new ExampleAdapter(context,YOUR_DATA,CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));

https://developer.android.com/reference/android/widget/CursorAdapter.html




回答3:


I think you will need to create a CustomAdapter that access your own layout to do this. It is surprising this hasn't been made easier to modify. SuggestionsAdapter isn't public so you can't extend it. It's not pretty but the easiest solution will be to copy SuggestionsAdapter.java into your own project and point it to a layout in your own res/layouts. I would again copy the version from the Android source code and modify it to your needs.

The Android 5 version is even worse for modifying so this is the KitKat version: http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/widget/SuggestionsAdapter.java/?v=source

Change this line to point to your layout file:

super(context,
        com.android.internal.R.layout.search_dropdown_item_icons_2line, // make it you layout xml (see below)
        null,   // no initial cursor
        true);  // auto-requery

http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/frameworks/base/core/res/res/layout/search_dropdown_item_icons_2line.xml/?v=source

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingStart="@dimen/dropdownitem_text_padding_left"
    android:paddingEnd="4dip"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" > <!-- changed -->

Also in the layout file:

<TextView android:id="@android:id/text2"
    style="?android:attr/dropDownItemStyle"
    android:textAppearance="?android:attr/textAppearanceSearchResultSubtitle"
    <!-- android:singleLine="true" --> <!-- remove this line -->
    android:layout_width="match_parent"
    android:layout_height="wrap_content" <!-- changed -->

user2511882's answer is probably better than this quick hack.



来源:https://stackoverflow.com/questions/27671954/android-prevent-text-truncation-in-searchview-suggestions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!