如何在Android工具栏中使用搜索视图(SearchView)

133

我正在处理的代码使用一个工具栏并填充一个菜单

下面是这段代码:

private Toolbar mToolbar;
mToolbar.inflateMenu(R.menu.chat_screen_menu);
setupMenu ();
private void setupMenu ()
   {
   mMenu = mToolbar.getMenu();
   if (mMenu != null)
      {
       if (mChatPager != null && mChatPager.getCurrentItem() > 0)
          {
          mMenu.setGroupVisible(R.id.menu_group_chats, true);
          mMenu.setGroupVisible(R.id.menu_group_contacts, false);
          }
       else
          {
           mMenu.setGroupVisible(R.id.menu_group_chats, false);
           mMenu.setGroupVisible(R.id.menu_group_contacts, true);
           mMenu.setGroupVisible(R.id.menu_group_otr_verified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_unverified,false);
           mMenu.setGroupVisible(R.id.menu_group_otr_off,false);
          }
    }
    mToolbar.setOnMenuItemClickListener(new OnMenuItemClickListener ()
    {
    ..........
    }
}

但现在他们需要在工具栏中添加一个名为Search的按钮。我已经成功地将其添加进去了,我遵循了这里的指导。 当我尝试输入内容进行搜索时,我预先设置的用于测试listener的toast从未显示出来,这表明listener没有起作用。

@Override
    public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.chat_screen_menu, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_menu_search));
    final Toast toast = new Toast(mApp);

    if (mSearchView != null )
    {
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener()
        {
            public boolean onQueryTextChange(String newText)
            {
                mSearchString = newText;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test1", Toast.LENGTH_LONG).show();
                return true;
            }

            public boolean onQueryTextSubmit(String query)
            {
                mSearchString = query;
                //doFilterAsync(mSearchString);
                toast.makeText(getApplicationContext(), "Test2", Toast.LENGTH_LONG).show();

                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);
    }

    return true;

}
6个回答

218
你需要使用 Appcompat 库来实现这个功能。你可以像下面这样使用它:

dashboard.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="always|collapseActionView"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        android:title="Search"/>
</menu>

活动文件(Java中):

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.dashboard, menu);

     MenuItem searchItem = menu.findItem(R.id.action_search);

    SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);

    SearchView searchView = null;
    if (searchItem != null) {
        searchView = (SearchView) searchItem.getActionView();
    }
    if (searchView != null) {
        searchView.setSearchableInfo(searchManager.getSearchableInfo(MainActivity.this.getComponentName()));
    }
        return super.onCreateOptionsMenu(menu);
}

活动文件(Kotlin语言):

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_search, menu)

    val searchItem: MenuItem? = menu?.findItem(R.id.action_search)
    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView: SearchView? = searchItem?.actionView as SearchView

    searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))
    return super.onCreateOptionsMenu(menu)
}

清单文件:

<meta-data 
      android:name="android.app.default_searchable" 
      android:value="com.apkgetter.SearchResultsActivity" /> 

        <activity
            android:name="com.apkgetter.SearchResultsActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
            </intent-filter>

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

可搜索的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name" />

最后,您的SearchResultsActivity类代码。用于显示您搜索的结果。


18
请注意,现在您应该导入android.support.v7.widget.SearchView - Joaquin Iurchuk
谢谢,有什么想法如何处理“Go”点击吗?这会有所帮助。 - Bala Vishnu
2
我将仅提供官方文档的链接,您可以在其中找到如何响应查询的信息。 https://developer.android.com/training/search/setup.html - koesclem
2
请注意使用 app:actionViewClass 而不是 android:actionViewClass。 - DragonT
2
如果您已经迁移到androidX,请使用:androidx.appcompat.widget.SearchView - Daniil
显示剩余3条评论

183

如果您想在Fragment内设置搜索功能,请添加以下几行代码:

步骤1 - 将搜索字段添加到您的toolbar中:

<item
    android:id="@+id/action_search"
    android:icon="@android:drawable/ic_menu_search"
    app:showAsAction="always|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView"
    android:title="Search"/>

步骤 2 - 在你的 onCreateOptionsMenu() 中添加逻辑。

import android.support.v7.widget.SearchView; // not the default !

@Override
public boolean onCreateOptionsMenu( Menu menu) {
    getMenuInflater().inflate( R.menu.main, menu);

    MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
    searchView = (SearchView) myActionMenuItem.getActionView();
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            // Toast like print
            UserFeedback.show( "SearchOnQueryTextSubmit: " + query);
            if( ! searchView.isIconified()) {
                searchView.setIconified(true);
            }
            myActionMenuItem.collapseActionView();
            return false;
        }
        @Override
        public boolean onQueryTextChange(String s) {
            // UserFeedback.show( "SearchOnQueryTextChanged: " + s);
            return false;
        }
    });
    return true;
}

34
如果你不想在用户提交搜索查询时创建/移动到新的活动,那么这个答案会更加有帮助。这将允许您停留在同一活动/片段中,只需根据用户的输入更新一个视图。非常棒的内容。 - Nick.D
3
用户反馈是类似于我的Toast方法的方式。 - tm1701
搜索视图中无法输入键盘。 - Saravanan
R.menu.main是什么? - Alston
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { } 在这里您可以直接调用此方法,您可以自己填充菜单,并直接从片段中处理它,而无需使用活动。非常感谢。 - Amar Singh

42

如果你想直接将它添加到工具栏中。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <SearchView
            android:id="@+id/searchView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:iconifiedByDefault="false"
            android:queryHint="Search"
            android:layout_centerHorizontal="true" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>


2
如果您正在使用支持SearchView,请不要忘记在XML中将其声明为android.support.v7.widget.SearchView - Abandoned Cart
不要忘记在Gradle中添加以下代码:implementation 'com.android.support:design:$latest_version' - Ali
什么是“iconified”? - IgorGanapolsky
如果您希望搜索字段始终可见,则调用 setIconifiedByDefault(false)。——来自文档 - noe

22

将SearchView与RecyclerView集成

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)在你的Activity中实现SearchView.OnQueryTextListener

SearchView.OnQueryTextListener有两个抽象方法。因此,在实现SearchView文本监听器后,您的Activity框架将如下所示。

YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{

   public boolean onQueryTextSubmit(String query)

   public boolean onQueryTextChange(String newText) 

}

3)设置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;
}

4) 实现SearchView.OnQueryTextListener

这是如何实现监听器抽象方法的过程。

@Override
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)在您的RecyclerView适配器中编写过滤器方法。

您可以根据自己的需求想出自己的逻辑。以下是示例代码片段,用于显示包含在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代码。


为什么菜单是必要的? - IgorGanapolsky

4

通过按钮实现搜索视图,而无需使用menu.xml文件

在您的Activity中,我们需要使用onCreateOptionsMenu方法的方式,在其中编程动态载入SearchView

private MenuItem searchMenu;
private String mSearchString="";

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        SearchManager searchManager = (SearchManager) StoreActivity.this.getSystemService(Context.SEARCH_SERVICE);


        SearchView mSearchView = new SearchView(getSupportActionBar().getThemedContext());
        mSearchView.setQueryHint(getString(R.string.prompt_search)); /// YOUR HINT MESSAGE
        mSearchView.setMaxWidth(Integer.MAX_VALUE);

        searchMenu = menu.add("searchMenu").setVisible(false).setActionView(mSearchView);
        searchMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);


        assert searchManager != null;
        mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        mSearchView.setIconifiedByDefault(false);

        SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            public boolean onQueryTextChange(String newText) {
                mSearchString = newText;

                return true;
            }

            public boolean onQueryTextSubmit(String query) {
                mSearchString = query;

                searchMenu.collapseActionView();


                return true;
            }
        };

        mSearchView.setOnQueryTextListener(queryTextListener);


        return true;
    }

在您的Activity类中,您可以像下面这样在工具栏上的任何按钮单击时打开SearchView

YOUR_BUTTON.setOnClickListener(view -> {

            searchMenu.expandActionView();

        });

-1

我搜索并实现了很多代码,但都没有对我起作用。 然后我将自定义工具栏实现到我的XML文件中,然后在工具栏标签内使用searchview标签。 希望它对你有用。


1
您的答案可以通过添加额外的支持信息来改善。请编辑以添加更多细节,如引用或文档,以便他人确认您的答案是否正确。您可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接