Android - Предотвратить усечение текста в предложениях SearchView?

Предложения, которые появляются по умолчанию ListView под моим SearchView содержит текст, который усечен. Я хотел бы, чтобы текст отображался полностью (в несколько строк, если это необходимо).

Я придумала два возможных способа решения этой проблемы, но без примеров в сети, я надеялась, что кто-то здесь сможет помочь...

Подход № 1 / Q1: Как я могу напрямую получить доступ и изменить внешний вид TextViews, которые содержат SUGGEST_COLUMN_TEXT_1 а также SUGGEST_COLUMN_TEXT_1 текст?

Подход № 2 / Q2: в качестве альтернативы, SearchView имеет setSuggestionsAdapter(CursorAdapter adapter) метод, который выглядит так, как будто он (больше?) подходит, чем подход № 1. Хотя я прочитал CursorAdapters и уже внедрил его в свое приложение, я не уверен, как бы настроить его для SearchView (особенно с точки зрения доступа к курсору), поэтому кто-нибудь может мне помочь с некоторыми общими рекомендациями или пример скелета?

Вот существующий код из моего класса SearchViewFragment:

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;
}

}

Обновление: решено!

Благодаря принятому ответу, я создал этот код, который довольно чистый и хорошо выполняет свою работу...

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);

        }
        */

    }

}

А вот и мой 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>

... результат - отсутствие усечения текста.:-)

3 ответа

Решение

Похоже, что вы хотите пользовательский макет для результатов поиска. Я постараюсь изложить некоторые четкие шаги ниже:

Чтобы заставить работать представление поиска, нам нужно иметь searchable.xml в res/xml folder и content provider всегда.

пример searchable.xml:

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

label а также searchSuggestAuthority являются обязательными. searchSuggestAuthority должен указывать на местоположение поставщика контента

Добавьте метаданные фильтра намерений к действию в манифесте. Пример:

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

В упражнении / фрагменте получите ваш объект searchView и передайте ему пользовательский адаптер для отображения пользовательского макета.

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));

            }
        };

Убедитесь, что пользовательский адаптер расширяет курсор Adapter.

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;

    }

}

В приведенном выше коде R.layout.item относится к вашему обычаю xml файл, который вы можете использовать для раздувания в результатах поиска.

Убедитесь, что вы используете content provider хоть. searchView не работает без него. Это не имеет значения, даже если вы кэшируете данные только на временной основе.

Надеюсь это поможет!

user2511882 идеален, но этот конструктор устарел.

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

Вы можете использовать ниже, вместо этого.

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

и затем назовите это так

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

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

Я думаю, что вам нужно будет создать CustomAdapter, который обращается к вашему собственному макету, чтобы сделать это. Удивительно, но это не так легко изменить. SuggestionsAdapter не является общедоступным, поэтому вы не можете его расширить. Это не красиво, но самое простое решение - скопировать SuggestionsAdapter.java в ваш собственный проект и указать его на макете в ваших собственных res / layouts. Я бы снова скопировал версию из исходного кода Android и изменил ее в соответствии с вашими потребностями.

Версия Android 5 еще хуже для модификации, так что это версия KitKat: http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/widget/SuggestionsAdapter.java/?v=source

Измените эту строку, чтобы она указала на ваш файл макета:

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 -->

Также в файле макета:

<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, вероятно, лучше, чем этот быстрый взлом.

Другие вопросы по тегам