Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Prevent text truncation in SearchView suggestions?

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. :-)

like image 221
ban-geoengineering Avatar asked Dec 27 '14 22:12

ban-geoengineering


People also ask

How to set SearchView in ToolBar in Android?

To add a SearchView widget to the app bar, create a file named res/menu/options_menu. xml in your project and add the following code to the file. This code defines how to create the search item, such as the icon to use and the title of the item.

How to use SearchView in Android?

SearchView widget can be implemented over ToolBar/ActionBar or inside a layout. SearchView is by default collapsible and set to be iconified using setIconifiedByDefault(true) method of SearchView class. For making search field visible, SearchView uses setIconifiedByDefault(false) method.


1 Answers

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!

like image 102
user2511882 Avatar answered Oct 02 '22 17:10

user2511882