【问题标题】:How to use SearchView in Toolbar Android如何在工具栏 Android 中使用 SearchView
【发布时间】:2015-02-07 08:20:11
【问题描述】:

我正在处理的代码是使用Toolbar 并膨胀menu

这里是代码

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 ()
    {
    ..........
    }
}

但现在,他们需要在 tool_bar 中添加一个 Search 按钮。 我设法把它说出来,我跟着一个指南here 当我尝试写一些东西来搜索时,我用来测试listener 的吐司从未出现过。 这表明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;

}

【问题讨论】:

    标签: android android-actionbar searchview android-toolbar


    【解决方案1】:

    为此,您必须使用 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 课程代码。用于显示您的搜索结果。

    【讨论】:

    • 注意现在你应该import android.support.v7.widget.SearchView
    • 谢谢,您知道如何处理“开始”点击吗?这会有所帮助
    • 我将只链接官方文档,您还可以在其中找到如何响应查询developer.android.com/training/search/setup.html
    • 注意 app:actionViewClass 而不是 android:actionViewClass
    • 如果您已迁移到 androidX,请使用:androidx.appcompat.widget.SearchView
    【解决方案2】:

    如果您想在 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;
    }
    

    【讨论】:

    • 如果您不想在用户提交搜索查询时创建/移动到新活动,此答案会更有帮助。这将允许您停留在相同的活动/片段上,并且只需根据用户输入更新视图。很棒的东西。
    • UserFeedback ... 是我的 Toast-alike 方法。
    • 搜索视图中未采用键盘输入
    • R.menu.main 是什么?
    • public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { } 你可以在这里直接调用这个方法你可以infilate自己的菜单,并且直接从fragment处理这个而不使用activity。很好,谢谢
    【解决方案3】:

    如果你想直接在工具栏中添加。

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

    【讨论】:

    • 如果您使用支持 SearchView,请不要忘记在 XML 中也将其声明为android.support.v7.widget.SearchView
    • 别忘了在gradle中添加implementation 'com.android.support:design:$latest_version'
    • 什么是图标化
    • ¨如果您希望搜索字段始终可见,请从文档中调用 setIconifiedByDefault(false)¨
    【解决方案4】:

    将 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 文本侦听器之后,您的活动框架现在看起来像这样。

    YourActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{
    
       public boolean onQueryTextSubmit(String query)
    
       public boolean onQueryTextChange(String newText) 
    
    }
    

    3) 设置 SerchView 提示文本、监听器等

    @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 Adapter 中编写一个过滤器方法。

    您可以根据自己的要求提出自己的逻辑。这是示例代码 sn-p 显示名称列表,其中包含在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();
    }
    

    可以找到完整的工作代码示例>HERE
    您还可以在 Music App 中使用 SQLite 数据库查看 SearchView 上的代码

    【讨论】:

    • 为什么需要菜单?
    【解决方案5】:

    在不使用menu.xml文件的情况下实现SearchView并通过按钮打开

    在您的Activity 中,我们需要使用onCreateOptionsMenumethod 的方法,我们将以编程方式对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();
    
            });
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center