SearchView 过滤和设置建议
Posted
技术标签:
【中文标题】SearchView 过滤和设置建议【英文标题】:SearchView Filtering and Set Suggestions 【发布时间】:2015-01-03 08:32:01 【问题描述】:我对使用SearchView
很陌生。我需要一个有ActionBar
的功能,我有Search
。当我点击搜索时,Suggestions 应该会显示在 Search 字段下方的 List 中。
到目前为止我做了什么:
在 menu.xml 中添加了搜索,并在 onCreateOptionsMenu()
中编写了代码,我在其中初始化了 SearchView,setSuggestionsAdapter
也实现了 setOnQueryTextListener
。
结果:我进入应用程序,点击搜索图标,它会显示建议。我输入一个字母,它会整理出匹配的字母。我输入第二个字母它没有显示任何建议。另外我关闭搜索视图并再次打开它,键盘已打开,但未显示列表中的建议。
我需要什么:根据用户输入的字符进行过滤。哪怕不止一个角色。 始终显示包含所有列表项的默认建议或在用户键入时排序的建议。
我在 android 的 SearchView 类中看到,他们将文本设置为空并且还关闭了建议。但我不想要这个。
我被困在这里,不知道如何继续。请帮我。 这是我的适配器代码:
public class ExampleAdapter extends CursorAdapter implements Filterable
private ArrayList<String> items;
private ArrayList<String> orig;
public ExampleAdapter(Context context, Cursor cursor,
ArrayList<String> items)
super(context, cursor, false);
this.items = new ArrayList<String>();
this.items = items;
orig = new ArrayList<String>();
orig.addAll(items);
@Override
public int getCount()
return items.size();
@Override
public Filter getFilter()
return new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if (constraint != null
&& constraint.toString().length() > 0)
List<String> founded = new ArrayList<String>();
for (int i = 0, l = orig.size(); i < l; i++)
if (orig.get(i)
.toString()
.toLowerCase()
.startsWith(
constraint.toString().toLowerCase()))
founded.add(orig.get(i));
result.values = founded;
result.count = founded.size();
else
synchronized (this)
result.values = orig;
result.count = orig.size();
return result;
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
items.clear();
items = new ArrayList<String>();
items = (ArrayList<String>) results.values;
notifyDataSetChanged();
;
@Override
public void bindView(View view, Context context, Cursor cursor)
ViewHolder holder = (ViewHolder) view.getTag();
holder.textView.setText(items.get(cursor.getPosition()));
public class ViewHolder
public TextView textView;
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent)
ViewHolder holder = new ViewHolder();
View v = null;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.item, parent, false);
holder.textView = (TextView) v.findViewById(R.id.text);
v.setTag(holder);
return v;
我的 Activity 中的代码与我有 searchview 的菜单相关:
private String[] columns = new String[] "_id", "text" ;
private SearchView searchView;
private SearchManager manager;
private ExampleAdapter aptr;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
setSearchTextColour(searchView);
setSearchIcons(searchView);
searchView.setQueryHint(html.fromHtml("<font color = #ffffff>"
+ getResources().getString(R.string.search_store) + "</font>"));
searchView.setSearchableInfo(manager
.getSearchableInfo(getComponentName()));
Object[] temp = new Object[] 0, "default" ;
final MatrixCursor cursor = new MatrixCursor(columns);
for (int i = 0; i < alStoreNames.size(); i++)
temp[0] = i;
temp[1] = alStoreNames.get(i);
cursor.addRow(temp);
aptr = new ExampleAdapter(MainActivity.this, cursor, alStoreNames);
searchView.setSuggestionsAdapter(aptr);
searchView.setOnQueryTextListener(new OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String arg0)
if (!TextUtils.isEmpty(arg0))
aptr.getFilter().filter(arg0.toString());
return true;
@Override
public boolean onQueryTextChange(String arg0)
return false;
);
searchView.setOnSuggestionListener(new OnSuggestionListener()
@Override
public boolean onSuggestionSelect(int arg0)
return false;
@Override
public boolean onSuggestionClick(int position)
String suggestion = getSuggestion(position);
db.openDatabase();
String studentId = db.getStudentIdFromName(suggestion);
String studentImg = db.getStudentImgFromName(suggestion);
db.closeDatabase();
Log.e("Sp", " On Click name -> " + aptr.getItem(position).toString() + " : "
+ aptr.getCursor().getString(0) + " : " + suggestion);
Intent i = new Intent(MainActivity.this,
ExampleActivity.class);
i.putExtra("studentId", studentId);
i.putExtra("studentName", suggestion);
i.putExtra("studentImg", studentImg);
startActivity(i);
return true;
);
return true;
private String getSuggestion(int position)
Cursor cursor = (Cursor) searchView.getSuggestionsAdapter().getItem(
position);
String suggest1 = cursor.getString(cursor.getColumnIndex("text"));
return suggest1;
private void setSearchTextColour(SearchView searchView)
Field qTextField;
try
qTextField = SearchView.class.getDeclaredField("mQueryTextView");
qTextField.setAccessible(true);
SearchAutoComplete searchPlate = (SearchAutoComplete) qTextField
.get(searchView);
searchPlate.setTextColor(getResources().getColor(R.color.white));
catch (NoSuchFieldException e)
e.printStackTrace();
catch (IllegalArgumentException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
private void setSearchIcons(SearchView searchView)
try
Field searchField = SearchView.class
.getDeclaredField("mCloseButton");
searchField.setAccessible(true);
ImageView closeBtn = (ImageView) searchField.get(searchView);
closeBtn.setImageResource(R.drawable.close);
Field searchField1 = SearchView.class
.getDeclaredField("mSearchButton");
searchField1.setAccessible(true);
ImageView searchButton = (ImageView) searchField1.get(searchView);
searchButton.setImageResource(R.drawable.ic_action_search);
catch (NoSuchFieldException e)
Log.e("SearchView", e.getMessage(), e);
catch (IllegalAccessException e)
Log.e("SearchView", e.getMessage(), e);
【问题讨论】:
有什么变化?过滤没有问题..问题在于 onsuggestionclick 检查:***.com/questions/23422072/… 【参考方案1】:在我看来,部分问题在于缺少 getItem() 方法。
如果您查看游标适配器源代码,getItem() 将从游标获取数据,而不是从过滤列表中获取数据,您希望它从过滤列表中获取数据!
试试这个:
@Override
public Object getItem(int position)
if (position < items.size())
return items.get(position);
else
return null;
我忘记添加了,你也需要改一下:
private String getSuggestion(int position)
String suggest1 = (String) searchView.getSuggestionsAdapter().getItem(position);
return suggest1;
要关闭所有内容,首先将其添加到 createOptions 菜单:
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setIconifiedByDefault(true); //this line
...
然后将其添加到 onSuggestionClick:
@Override
public boolean onSuggestionClick(int position)
String suggestion = getSuggestion(position);
db.openDatabase();
String studentId = db.getStudentIdFromName(suggestion);
String studentImg = db.getStudentImgFromName(suggestion);
db.closeDatabase();
Log.e("Sp", " On Click name -> " + aptr.getItem(position).toString() + " : "
+ aptr.getCursor().getString(0) + " : " + suggestion);
searchView.setIconified(true);//this line
Intent i = new Intent(MainActivity.this,ExampleActivity.class);
i.putExtra("studentId", studentId);
i.putExtra("studentName", suggestion);
i.putExtra("studentImg", studentImg);
startActivity(i);
return true;
有点解释。当您调用 setIconified 时,它将清除您的 searchView 的文本或将其折叠,具体取决于默认状态。我们所做的是将默认状态设置为图标化,因此当我们调用 setIconified 方法时,它将清除文本并折叠视图!
【讨论】:
【参考方案2】:您好,我发现您的代码存在一些问题。
请尝试我的方式。
替换publishResults of ExampleAdapter
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
items.clear();
// items = new ArrayList<String>();
//items = (ArrayList<String>) results.values;
items.addAll((ArrayList<String>) results.values);
notifyDataSetChanged();
与
searchView.setOnQueryTextListener(new OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String arg0)
if (!TextUtils.isEmpty(arg0))
aptr.getFilter().filter(arg0.toString());
return true;
@Override
public boolean onQueryTextChange(String arg0)
if (!TextUtils.isEmpty(arg0))
aptr.getFilter().filter(arg0.toString());
return true;
return false;
);
【讨论】:
解决了建议列表问题。但是当我单击排序建议列表中的一项时,它指向该位置的旧字符串 将 cursoradapter 设为全局并尝试使用 adapter.getItem(position); 我有 onSuggestionClick,当我点击它时,它会给出点击的字符串名称 必须尝试将适配器设为全局?【参考方案3】:尝试将搜索值传递给过滤器,即使是空的:
@Override
public boolean onQueryTextSubmit(String arg0)
aptr.getFilter().filter(arg0.toString());
return true;
如果搜索不匹配或搜索值为空,则将默认列表设置为适配器:
@Override
public Filter getFilter()
return new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if (constraint != null && constraint.toString().length() > 0)
List<String> founded = new ArrayList<String>();
for (int i = 0, l = orig.size(); i < l; i++)
if (orig.get(i).toString().toLowerCase().startsWith(constraint.toString().toLowerCase()))
founded.add(orig.get(i));
if(founded.size()>0)
result.values = founded;
result.count = founded.size();
else
result.values = orig;
result.count = orig.size();
else
result.values = orig;
result.count = orig.size();
return result;
【讨论】:
以上是关于SearchView 过滤和设置建议的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SearchView 过滤 RecyclerView
使用 Room 和 RecyclerView 在 SearchView 中添加过滤器
如何使用 SearchView 过滤 FirestoreRecyclerAdapter
我的应用程序的Recycler View问题中的Android Studio SearchView过滤器
已解决:SearchView 不会在 TabLayout 的每个子选项卡中进行过滤
在使用存储在 JSON 上的 ID 进行 SearchView 过滤后,如何从 ListView 打开 Activity