在操作栏中实现 SearchView

我需要从我的 arrayList<String>中创建 SearchView,并在下拉列表中显示相同的建议

enter image description here

我寻找教程,逐步解释如何建立一个 SearchView在一个动作栏。

我已经阅读了 文件和下面的例子谷歌,但它对我没有用。

我创造了搜索

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

但是我不知道如何设置字符串数组的参数。 我试图在一个不同的活动中检索结果,但没有工作。

195833 次浏览

我们花了一些时间来整理出一个解决方案,但是我们发现这是按照您所描述的方式使其工作的最简单的方法。可能有更好的方法来做到这一点,但由于你还没有发布你的活动代码,我将不得不即兴发挥,假设你有一个像下面这样的列表在你的活动开始:

private List<String> items = db.getItems();

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


}


}

现在您需要创建一个从 CursorAdapter扩展的适配器:

ExampleAdapter.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;


}


}

更好的方法是,如果列表数据来自数据库,可以将数据库函数返回的 Cursor直接传递给 ExampleAdapter,并使用相关的列选择器显示适配器中引用的 TextView中的列文本。

请注意: 导入 CursorAdapter时不要导入 Android 支持版本,而是导入标准的 android.widget.CursorAdapter

适配器还需要一个自定义布局:

Res/layp/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>

现在可以通过向布局添加其他文本或图像视图并在适配器中用数据填充它们来自定义列表项。

这应该就是全部了,但是如果你还没有这样做,你需要一个 SearchView 菜单项:

Res/menu/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>

然后创建一个可搜索的配置:

Res/xml/searchable.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/search"
android:hint="@string/search" >
</searchable>

最后,在清单文件的相关活动标记中添加以下内容:

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

请注意: 示例中使用的 @string/search字符串应该在 Value/strings.xml中定义,也不要忘记为您的项目更新对 com.example的引用。

如果其他人在 searchview 变量上使用 nullptr,我会发现条目设置有一点点不同:

旧的:

android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView"

最新消息:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"

前机器人 X:

app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"

更多信息,它的更新文档是 位于这里


对于 Searchview,请使用以下代码

  1. 用于 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>
    

  2. 在你的片段或活动中

    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;
    }
    }
    
  3. In adapter class

     public void setFilter(List<ProductDetailPojo> newList){
    arrayList=new ArrayList<>();
    arrayList.addAll(newList);
    notifyDataSetChanged();
    }
    

SearchDialog 还是 SearchWidget? ?

在实现搜索功能方面,官方的 Android 开发者文档提供了 建议的两种方法
您可以使用 SearchDialogSearchWidget
我将解释如何使用 SearchWidget 实现搜索功能。

如何使用搜索小部件?

我将使用 SearchWidget 在回收视图中解释搜索功能。

只要遵循以下5个简单的步骤

1)在菜单中添加 searchView 项

可以添加 SearchView,可以在菜单中添加 actionView,使用

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)设置 SerchView 提示文本、监听器等

应该在 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)在活动中实现 SearchView.OnQueryTextListener

OnQueryTextListener有两个抽象方法

  1. onQueryTextSubmit(String query)
  2. onQueryTextChange(String newText

所以你的活动骨架应该是这样的

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{


public boolean onQueryTextSubmit(String query)


public boolean onQueryTextChange(String newText)


}

4)实现 SearchView.OnQueryTextListener

您可以为这样的抽象方法提供实现

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)在回收视图适配器中编写一个过滤器方法。

最重要的部分。您可以编写自己的逻辑来执行搜索。
这里是我的。这个代码片段显示的名称列表,其中包含在 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();
}

相关连结:

在此 音乐应用中使用 SQLite 数据库的 SearchView 上的完整工作代码