【问题标题】:Android Actionbar Search widget implementation In ListFragmentListFragment 中的 Android Actionbar Search 小部件实现
【发布时间】:2012-03-04 16:48:07
【问题描述】:

我目前的应用程序在左侧设置了 ListFragment,在右侧设置了 DetailsFragment(类似于下面平板电脑上的布局)。

在操作栏上,我有一个搜索小部件,当提交搜索词时,它应该更新列表的内容(在 ListFragment 中)。 我一直在关注 android dev (http://developer.android.com/guide/topics/search/search-dialog.html) 上的搜索指南,但在同一活动中更新列表时遇到问题。

我已经设法通过在提交搜索词时调用新活动来实现某种形式的实现,但这会使后退按钮的行为异常(即,您按下后退并转到上一个活动,但搜索小部件仍显示搜索词)。

我已将意图行添加到清单中,如下所示

<intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data android:name="android.app.searchable"
               android:resource="@xml/searchable"/>

是否可以让搜索小部件更新当前活动的列表?

【问题讨论】:

    标签: android android-3.0-honeycomb android-actionbar android-4.0-ice-cream-sandwich android-searchmanager


    【解决方案1】:

    是的,事实上,这是“正常”用例。您必须记住的是,使用搜索操作栏小部件的片段通常应该是注册它的部分,因为小部件将与该片段一起被销毁。

    以下是正确捆绑的方法:

    在您的ListFragment 中告知您有选项菜单项...

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        ..
        setHasOptionsMenu(true);
        ..
    }
    

    然后在同一个ListFragment 中通过覆盖回调创建您的选项菜单,一旦您拥有 SearchView 小部件引用,注册一个 QueryTextListener 回调:

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.grid_default, menu); 
        SearchView searchView = (SearchView)menu.findItem(R.id.grid_default_search).getActionView();
        searchView.setOnQueryTextListener(queryListener);
    }
    

    通过编程方式 (Java) 或声明方式 (XML) 创建您的搜索小部件,这里是 XML(命名为 grid_default.xml,来自上面):

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item     
            android:id="@+id/grid_default_search"
            android:icon="@android:drawable/ic_menu_search"
            android:title="search"
            android:showAsAction="always"
            android:actionViewClass="android.widget.SearchView" 
        />
    
        <!-- other items or whatever  -->
    
    </menu>
    

    现在回到您的ListFragment,您需要创建我们在上面注册的queryListener

    private String grid_currentQuery = null; // holds the current query...
    
    final private OnQueryTextListener queryListener = new OnQueryTextListener() {       
    
        @Override
        public boolean onQueryTextChange(String newText) {
            if (TextUtils.isEmpty(newText)) {
                getActivity().getActionBar().setSubtitle("List");               
                grid_currentQuery = null;
            } else {
                getActivity().getActionBar().setSubtitle("List - Searching for: " + newText);
                grid_currentQuery = newText;
    
            }   
            getLoaderManager().restartLoader(0, null, MyListFragment.this); 
            return false;
        }
    
        @Override
        public boolean onQueryTextSubmit(String query) {            
            Toast.makeText(getActivity(), "Searching for: " + query + "...", Toast.LENGTH_SHORT).show();
            return false;
        }
    };
    

    现在您知道查询何时更改或提交,在我的示例中,我会在每次按下某个键时重新查询,因为我的数据库很小且结果很快,您可能需要更改此设置.. 但您会注意到我如何使用小部件将ListFragment 中的私有类字段设置为搜索小部件的当前文本(grid_currentQuery),然后我只是调用getLoaderManager().restartLoader(0, null, MyListFragment.this); 在我的onCreateLoader 里面我只是在更新我这样使用的查询:

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bargs) {
    
        String sort = "SortColumn ASC";
        String[] grid_columns = new String[] { "ColumnA", "ColumnB", "Etc..." };
        String grid_whereClause = "ColumnToSearchBy LIKE ?"
    
        if (!TextUtils.isEmpty(grid_currentQuery)) {            
            return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, grid_whereClause, new String[] { grid_currentQuery + "%" }, sort);
        }       
    
        return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, null, null, sort);
    }
    

    这就是你真正需要做的,我意识到这有点被切碎了,但就是这样,因为还有更多的事情需要发生,设置适配器,首先使用 getLoaderManager().initLoader(0, null, this); 启动加载器和需要处理的所有其余加载程序回调...但是如果您遵循 android 人员提出的最佳实践,(在您的 ListActivitys 和 ListFragmentss 中使用 LoaderManagers 它应该是对你来说很容易......

    如果您需要 -ck,我希望这有助于随时在 cmets 中要求澄清

    【讨论】:

    • 非常感谢您的详细解释。我将在接下来的几天内尝试实施它,如果我有任何问题,请告诉您。
    • 谢谢我已经设法让它工作非常有用的答案。我想知道的一件事。默认情况下,在应用程序中我有 3 个选项卡,每个选项卡在搜索时代表一个类别,我想删除这些选项卡。这不是问题,我遇到的问题是我如何知道用户何时完成搜索(返回)以重新添加选项卡。
    • @bencallis 您最想在 SearchView 上使用 setOnCloseListener(SearchView.OnCloseListener listener)...
    • 我只是在处理这个问题,但我遇到了问题。 searchView.setOnCloseListener(new OnCloseListener() { @Override public boolean onClose() { Toast.makeText(DealPadActivity.this, "Closed", Toast.LENGTH_SHORT).show(); Log.d("Search", "search closed" ); 它似乎没有被调用。
    • 只有在单击“x”以“关闭”搜索时才会调用它,这对我来说很好用:searchView.setOnCloseListener(new OnCloseListener() { @Override public boolean onClose() { / * 这完美你的问题在别处*/ return false; } });
    猜你喜欢
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    相关资源
    最近更新 更多