Android 在操作栏中实现 SearchView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21585326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing SearchView in action bar
提问by Matteo
I need to create SearchView
from my arrayList<String>
and show the suggestions in the drop-down list same this
我需要SearchView
从我的创建arrayList<String>
并在下拉列表中显示与此相同的建议
I look for tutorials that explain step by step how to build a SearchView
in a action bar.
我寻找逐步解释如何SearchView
在操作栏中构建一个的教程。
I have read the documentationand following the example google but it was not useful to me.
我已经阅读了文档并遵循了 google 示例,但它对我没有用。
I have created the search
我已经创建了搜索
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_search"
android:title="Search"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="always"
android:actionViewClass="android.widget.SearchView" />
</menu>`
But I do not know how to set the parameters of the array of strings. I tried to retrieve the result in a different Activity but not work.
但是我不知道如何设置字符串数组的参数。我试图在不同的 Activity 中检索结果但不起作用。
回答by tpbapp
It took a while to put together a solution for this, but have found this is the easiest way to get it to work in the way that you describe. There could be better ways to do this, but since you haven't posted your activity code I will have to improvise and assume you have a list like this at the start of your activity:
花了一段时间才为此找到一个解决方案,但发现这是让它按照您描述的方式工作的最简单方法。可能有更好的方法来做到这一点,但由于您还没有发布您的活动代码,我将不得不即兴发挥并假设您在活动开始时有一个这样的列表:
private List<String> items = db.getItems();
ExampleActivity.java
示例Activity.java
private List<String> items;
private Menu menu;
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.example, menu);
this.menu = menu;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();
search.setSearchableInfo(manager.getSearchableInfo(getComponentName()));
search.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextChange(String query) {
loadHistory(query);
return true;
}
});
}
return true;
}
// History
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void loadHistory(String query) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// Cursor
String[] columns = new String[] { "_id", "text" };
Object[] temp = new Object[] { 0, "default" };
MatrixCursor cursor = new MatrixCursor(columns);
for(int i = 0; i < items.size(); i++) {
temp[0] = i;
temp[1] = items.get(i);
cursor.addRow(temp);
}
// SearchView
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final SearchView search = (SearchView) menu.findItem(R.id.search).getActionView();
search.setSuggestionsAdapter(new ExampleAdapter(this, cursor, items));
}
}
Now you need to create an adapter extended from CursorAdapter
:
现在您需要创建一个从CursorAdapter
以下扩展的适配器:
ExampleAdapter.java
示例适配器.java
public class ExampleAdapter extends CursorAdapter {
private List<String> items;
private TextView text;
public ExampleAdapter(Context context, Cursor cursor, List<String> items) {
super(context, cursor, false);
this.items = items;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
text.setText(items.get(cursor.getPosition()));
}
@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;
}
}
A better way to do this is if your list data is from a database, you can pass the Cursor
returned by database functions directly to ExampleAdapter
and use the relevant column selector to display the column text in the TextView
referenced in the adapter.
一个更好的方法是,如果您的列表数据来自数据库,您可以将Cursor
数据库函数返回的数据直接传递给ExampleAdapter
并使用相关的列选择器来显示TextView
适配器中引用的列文本。
Please note: when you import CursorAdapter
don't import the Android support version, import the standard android.widget.CursorAdapter
instead.
请注意:导入时CursorAdapter
不要导入 Android 支持版本,android.widget.CursorAdapter
而是导入标准。
The adapter will also require a custom layout:
适配器还需要自定义布局:
res/layout/item.xml
res/layout/item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
You can now customize list items by adding additional text or image views to the layout and populating them with data in the adapter.
您现在可以通过向布局添加额外的文本或图像视图并使用适配器中的数据填充它们来自定义列表项。
This should be all, but if you haven't done this already you need a SearchView menu item:
这应该是全部,但如果您还没有这样做,您需要一个 SearchView 菜单项:
res/menu/example.xml
资源/菜单/example.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/search"
android:title="@string/search"
android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView" />
</menu>
Then create a searchable configuration:
然后创建一个可搜索的配置:
res/xml/searchable.xml
res/xml/searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search"
android:hint="@string/search" >
</searchable>
Finally add this inside the relevant activity tag in the manifest file:
最后将其添加到清单文件的相关活动标签中:
AndroidManifest.xml
AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.default_searchable"
android:value="com.example.ExampleActivity" />
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
Please note: The @string/search
string used in the examples should be defined in values/strings.xml, also don't forget to update the reference to com.example
for your project.
请注意:@string/search
示例中使用的字符串应在values/strings.xml 中定义,也不要忘记更新com.example
项目的引用。
回答by Grease
If anyone else is having a nullptr on the searchview variable, I found out that the item setup is a tiny bit different:
如果其他人在 searchview 变量上有 nullptr,我发现项目设置有点不同:
old:
老的:
android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView"
new:
新的:
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"
pre-android x:
前安卓x:
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"
For more information, it's updated documentation is located here.
有关更多信息,它的更新文档位于此处。
回答by Rohit Singh
SearchDialog or SearchWidget ?
SearchDialog 或 SearchWidget ?
When it comes to implement a search functionality there are two suggested approachby official Android Developer Documentation.
You can either use a SearchDialogor a SearchWidget.
I am going to explain the implementation of Search functionality using SearchWidget.
在实现搜索功能时,官方 Android 开发人员文档有两种建议的方法。
您可以使用SearchDialog或SearchWidget。
我将解释使用 SearchWidget 实现搜索功能。
How to do it with Search widget ?
如何使用搜索小部件做到这一点?
I will explain search functionality in a RecyclerView using SearchWidget. It's pretty straightforward.
我将使用 SearchWidget 在 RecyclerView 中解释搜索功能。这很简单。
Just follow these 5 Simple steps
只需遵循以下 5 个简单步骤
1) Add searchView item in the menu
1)在菜单中添加searchView项
You can add SearchView
can be added as actionView
in menu using
您可以添加SearchView
可以actionView
在菜单中使用
app:useActionClass = "android.support.v7.widget.SearchView" .
app:useActionClass = "android.support.v7.widget.SearchView" 。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="rohksin.com.searchviewdemo.MainActivity">
<item
android:id="@+id/searchBar"
app:showAsAction="always"
app:actionViewClass="android.support.v7.widget.SearchView"
/>
</menu>
2) Set up SerchView Hint text, listener etc
2) 设置 SerchView 提示文本、监听器等
You should initialize SearchView in the onCreateOptionsMenu(Menu menu)
method.
您应该在onCreateOptionsMenu(Menu menu)
方法中初始化 SearchView 。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.searchBar);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setQueryHint("Search People");
searchView.setOnQueryTextListener(this);
searchView.setIconified(false);
return true;
}
3) Implement SearchView.OnQueryTextListener in your Activity
3) 在你的 Activity 中实现 SearchView.OnQueryTextListener
OnQueryTextListener
has two abstract methods
OnQueryTextListener
有两个抽象方法
onQueryTextSubmit(String query)
onQueryTextChange(String newText
onQueryTextSubmit(String query)
onQueryTextChange(String newText
So your Activity skeleton would look like this
所以你的 Activity 骨架看起来像这样
YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{
public boolean onQueryTextSubmit(String query)
public boolean onQueryTextChange(String newText)
}
4) Implement SearchView.OnQueryTextListener
4) 实现 SearchView.OnQueryTextListener
You can provide the implementation for the abstract methods like this
您可以为这样的抽象方法提供实现
public boolean onQueryTextSubmit(String query) {
// This method can be used when a query is submitted eg. creating search history using SQLite DB
Toast.makeText(this, "Query Inserted", Toast.LENGTH_SHORT).show();
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.filter(newText);
return true;
}
5) Write a filter method in your RecyclerView Adapter.
5) 在 RecyclerView Adapter 中编写过滤器方法。
Most important part. You can write your own logic to perform search.
Here is mine. This snippet shows the list of Name which contains the text typed in the SearchView
最重要的部分。您可以编写自己的逻辑来执行搜索。
这是我的。此代码段显示 Name 列表,其中包含在SearchView
public void filter(String queryText)
{
list.clear();
if(queryText.isEmpty())
{
list.addAll(copyList);
}
else
{
for(String name: copyList)
{
if(name.toLowerCase().contains(queryText.toLowerCase()))
{
list.add(name);
}
}
}
notifyDataSetChanged();
}
Relevant link:
相关链接:
Full working code on SearchView with an SQLite database in this Music App
此音乐应用程序中带有 SQLite 数据库的 SearchView 上的完整工作代码
回答by Neeraj Gupta
For Searchview
use these code
对于Searchview
使用这些代码
For XML
<android.support.v7.widget.SearchView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/searchView"> </android.support.v7.widget.SearchView>
In your Fragment or Activity
package com.example.user.salaryin; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.example.user.salaryin.Adapter.BusinessModuleAdapter; import com.example.user.salaryin.Network.ApiClient; import com.example.user.salaryin.POJO.ProductDetailPojo; import com.example.user.salaryin.Service.ServiceAPI; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class OneFragment extends Fragment implements SearchView.OnQueryTextListener { RecyclerView recyclerView; RecyclerView.LayoutManager layoutManager; ArrayList<ProductDetailPojo> arrayList; BusinessModuleAdapter adapter; private ProgressDialog pDialog; GridLayoutManager gridLayoutManager; SearchView searchView; public OneFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.one_fragment,container,false); pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Please wait..."); searchView=(SearchView)rootView.findViewById(R.id.searchView); searchView.setQueryHint("Search BY Brand"); searchView.setOnQueryTextListener(this); recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView); layoutManager = new LinearLayoutManager(this.getActivity()); recyclerView.setLayoutManager(layoutManager); gridLayoutManager = new GridLayoutManager(this.getActivity().getApplicationContext(), 2); recyclerView.setLayoutManager(gridLayoutManager); recyclerView.setHasFixedSize(true); getImageData(); // Inflate the layout for this fragment //return inflater.inflate(R.layout.one_fragment, container, false); return rootView; } private void getImageData() { pDialog.show(); ServiceAPI service = ApiClient.getRetrofit().create(ServiceAPI.class); Call<List<ProductDetailPojo>> call = service.getBusinessImage(); call.enqueue(new Callback<List<ProductDetailPojo>>() { @Override public void onResponse(Call<List<ProductDetailPojo>> call, Response<List<ProductDetailPojo>> response) { if (response.isSuccessful()) { arrayList = (ArrayList<ProductDetailPojo>) response.body(); adapter = new BusinessModuleAdapter(arrayList, getActivity()); recyclerView.setAdapter(adapter); pDialog.dismiss(); } else if (response.code() == 401) { pDialog.dismiss(); Toast.makeText(getActivity(), "Data is not found", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<List<ProductDetailPojo>> call, Throwable t) { Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show(); pDialog.dismiss(); } }); } /* @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { getActivity().getMenuInflater().inflate(R.menu.menu_search, menu); MenuItem menuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem); searchView.setQueryHint("Search Product"); searchView.setOnQueryTextListener(this); }*/ @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { newText = newText.toLowerCase(); ArrayList<ProductDetailPojo> newList = new ArrayList<>(); for (ProductDetailPojo productDetailPojo : arrayList) { String name = productDetailPojo.getDetails().toLowerCase(); if (name.contains(newText) ) newList.add(productDetailPojo); } adapter.setFilter(newList); return true; } }
In adapter class
public void setFilter(List<ProductDetailPojo> newList){ arrayList=new ArrayList<>(); arrayList.addAll(newList); notifyDataSetChanged(); }
对于 XML
<android.support.v7.widget.SearchView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/searchView"> </android.support.v7.widget.SearchView>
在您的片段或活动中
package com.example.user.salaryin; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.example.user.salaryin.Adapter.BusinessModuleAdapter; import com.example.user.salaryin.Network.ApiClient; import com.example.user.salaryin.POJO.ProductDetailPojo; import com.example.user.salaryin.Service.ServiceAPI; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class OneFragment extends Fragment implements SearchView.OnQueryTextListener { RecyclerView recyclerView; RecyclerView.LayoutManager layoutManager; ArrayList<ProductDetailPojo> arrayList; BusinessModuleAdapter adapter; private ProgressDialog pDialog; GridLayoutManager gridLayoutManager; SearchView searchView; public OneFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.one_fragment,container,false); pDialog = new ProgressDialog(getActivity()); pDialog.setMessage("Please wait..."); searchView=(SearchView)rootView.findViewById(R.id.searchView); searchView.setQueryHint("Search BY Brand"); searchView.setOnQueryTextListener(this); recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView); layoutManager = new LinearLayoutManager(this.getActivity()); recyclerView.setLayoutManager(layoutManager); gridLayoutManager = new GridLayoutManager(this.getActivity().getApplicationContext(), 2); recyclerView.setLayoutManager(gridLayoutManager); recyclerView.setHasFixedSize(true); getImageData(); // Inflate the layout for this fragment //return inflater.inflate(R.layout.one_fragment, container, false); return rootView; } private void getImageData() { pDialog.show(); ServiceAPI service = ApiClient.getRetrofit().create(ServiceAPI.class); Call<List<ProductDetailPojo>> call = service.getBusinessImage(); call.enqueue(new Callback<List<ProductDetailPojo>>() { @Override public void onResponse(Call<List<ProductDetailPojo>> call, Response<List<ProductDetailPojo>> response) { if (response.isSuccessful()) { arrayList = (ArrayList<ProductDetailPojo>) response.body(); adapter = new BusinessModuleAdapter(arrayList, getActivity()); recyclerView.setAdapter(adapter); pDialog.dismiss(); } else if (response.code() == 401) { pDialog.dismiss(); Toast.makeText(getActivity(), "Data is not found", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<List<ProductDetailPojo>> call, Throwable t) { Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show(); pDialog.dismiss(); } }); } /* @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { getActivity().getMenuInflater().inflate(R.menu.menu_search, menu); MenuItem menuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(menuItem); searchView.setQueryHint("Search Product"); searchView.setOnQueryTextListener(this); }*/ @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { newText = newText.toLowerCase(); ArrayList<ProductDetailPojo> newList = new ArrayList<>(); for (ProductDetailPojo productDetailPojo : arrayList) { String name = productDetailPojo.getDetails().toLowerCase(); if (name.contains(newText) ) newList.add(productDetailPojo); } adapter.setFilter(newList); return true; } }
在适配器类中
public void setFilter(List<ProductDetailPojo> newList){ arrayList=new ArrayList<>(); arrayList.addAll(newList); notifyDataSetChanged(); }