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