【问题标题】:Is there a better way to restore SearchView state?有没有更好的方法来恢复 SearchView 状态?
【发布时间】:2014-04-25 06:06:02
【问题描述】:

我的ActionBar 中有一个可折叠的SearchView。执行搜索后,关联的ListView 将被过滤以仅显示匹配项。在该状态下,SearchView 仍处于展开状态并显示搜索字符串。如果用户关闭SearchView,我删除过滤器。

我想恢复搜索状态,例如在配置更改或当我从另一个活动返回时活动被破坏。

我在onRestoreInstanceState() 中恢复查询字符串,如果在onCreateOptionsMenu() 中找到查询字符串,我调用

searchView.setQuery(query, true); 

以便再次执行查询。事实证明,这比立即应用查询过滤器onRestoreInstanceState() 更好。对于后者,列表很快就会显示为未经过滤的,然后才会再次应用查询。 setQuery() 不会发生这种情况。

问题:执行查询并过滤列表,但搜索视图仍处于折叠状态。因此,用户不能使用搜索视图来删除过滤器或应用另一个查询。

onCreateOptionsMenu()中我可以确定搜索项和搜索视图存在,因此我可以调用searchItem.expandActionView()。奇怪的是,只有这样才能真正扩展ActionView - 调用setIconified(false) 不会扩展视图,即使连续调用两次也不会。

如果我在调用setQuery() 之前使用expandActionView(),则SearchView 会打开并显示文本(否则expandActionView() 会清空SearchView)。

不幸的是,expandActionView() 有一个副作用:建议列表也会显示并且键盘会打开。

我可以使用searchView.clearFocus() 隐藏键盘。所以剩下的问题是建议列表。如何关闭包含文本的 SearchView 上的打开建议列表?

不知道有没有更好的方法来恢复操作栏中的搜索视图,并且没有那么多副作用。

【问题讨论】:

  • this可能对你有帮助
  • 这种情况不同,搜索视图在 onRestoreInstanceState 中可用。在我的情况下,搜索视图在操作栏中,在 onRestoreInstanceState 中不可用。
  • expandActionView 似乎由于某种原因导致当前查询字符串被重置为空。如果我首先展开操作视图,然后调用 setQuery,查询将打开并显示文本。现在剩下的问题是建议列表显示并且键盘是打开的。
  • 试试this
  • 感谢您的指点。我不确定你所说的“这个”到底是什么意思。它确认 expandActionView 清除了查询字符串,并且答案包含一个自定义 searchView,其文本在折叠/展开时保留。就我而言,问题是在配置更改后恢复扩展的 searchView。

标签: android searchview


【解决方案1】:

以我的拙见。当你想恢复 searchView 状态时,我们应该使用onSaveInstanceState(Bundle outState)。调用以在被杀死之前从 Activity 中检索每个实例的状态,以便可以在 onCreate(Bundle) 或 onRestoreInstanceState(Bundle) 中恢复状态(此方法填充的 Bundle 将传递给两者)。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // if you saved something on outState you can recover them here
    if (savedInstanceState != null) {
             mSearchString = savedInstanceState.getString(SEARCH_KEY);
    }
}

// This is called before the activity is destroyed
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mSearchString = mSearchView.getQuery().toString();
    outState.putString(SEARCH_KEY, mSearchString);
}

这个方法在一个activity可能被杀死之前被调用,这样当它在未来某个时间回来时它可以恢复它的状态。现在当用户改变方向时,可以通过 onCreate(Bundle) 或 onRestoreInstanceState(Bundle) 恢复用户界面的状态。

现在我们应该使用onCreateOptionsMenu(Menu menu),因为我们需要关注我们的SearchView。

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

    MenuItem searchMenuItem = menu.findItem(R.id.menu_main_action_search);

    mSearchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);

    //focus the SearchView
    if (mSearchString != null && !mSearchString.isEmpty()) {
        searchMenuItem.expandActionView();
        mSearchView.setQuery(mSearchString, true);
        mSearchView.clearFocus();
    }

    return super.onCreateOptionsMenu(menu);
}

您也可以查看this link 的完整代码。

【讨论】:

  • 您可以使用outState.putCharSequence(SEARCH_KEY, mSearchView.getQuery()); 而不是转换为字符串。
  • 另外,对于mSearchString != null && !mSearchString.isEmpty(),还有!TextUtils.isEmpty(mSearchString)
【解决方案2】:

我找到了解决方法。它非常丑陋,但它确实有效。

这就是我如何在配置更改后恢复搜索框实例状态。

首先在onRestoreInstanceState中恢复查询字符串

currentQuery = state.getString(KEY_SAVED_FILTER_CONSTRAINT);

在 onCreateOptionsMenu 中设置搜索视图,如果有 currentQuery,展开搜索项并再次提交查询。清除焦点以隐藏键盘。

    MenuItem searchItem = menu.findItem(R.id.action_search);
    searchView = (SearchView) searchItem.getActionView();
    searchView.setSearchableInfo(searchManager
            .getSearchableInfo(getComponentName()));

    if (!TextUtils.isEmpty(currentQuery)) {
        searchItem.expandActionView();
        searchView.setQuery(currentQuery, true);
        searchView.clearFocus();
    }

最后我们需要关闭建议列表。以下是如何从搜索视图中获取查询文本视图:

private AutoCompleteTextView findQueryTextView(ViewGroup viewGroup) {
    AutoCompleteTextView queryTextView = null;
    if (viewGroup != null) {
        int childCount = viewGroup.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = viewGroup.getChildAt(i);
            if (child instanceof AutoCompleteTextView) {
                queryTextView = (AutoCompleteTextView) child;
                break;
            } else if (child instanceof ViewGroup) {
                queryTextView = findQueryTextView((ViewGroup) child);
                if (queryTextView != null) {
                    break;
                }
            }
        }
    }
    return queryTextView;
} 

然后您可以关闭建议列表:

    AutoCompleteTextView queryTextView = findQueryTextView(searchView);
    if (queryTextView != null) {
        queryTextView.dismissDropDown();
    }

但这在 onCreateOptionsMenu 中不起作用。我必须将dismissDropDown 的调用移到我的活动的onNewIntent 方法中才能使其工作。

使这变得如此难看的原因是恢复步骤分散在生命周期的各个阶段,并且需要递归视图搜索才能获得建议列表。

【讨论】:

  • 不幸的是,searchItem.expandActionView(); 在 API 级别 14 之前不可用。看起来如果您使用支持 SearchView,那么您很不走运。
  • 不,有支持库你应该使用 MenuItemCompat.expandActionView()。
  • 订单很重要! item.expandActionView(); searchView.setQuery(_eventSearchQuery.query, true);
  • 如果expandActionView() 不起作用,请添加searchView.setIconified(false);
  • 真的很讨厌 android 框架来解决这些类型的变通办法。
猜你喜欢
  • 2011-11-08
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
  • 2011-05-05
  • 1970-01-01
相关资源
最近更新 更多