我的SearchView
中有一个可折叠的ActionBar
。执行搜索后,将过滤关联的ListView
以仅显示匹配的项目。在此状态期间,SearchView
仍会展开并显示搜索字符串。如果用户关闭SearchView
,我会删除过滤器。
我想恢复搜索状态,例如关于配置更改或当我从另一个活动返回活动时活动被销毁。
我在onRestoreInstanceState()
中恢复查询字符串,如果在onCreateOptionsMenu()
中找到查询字符串,则调用
searchView.setQuery(query, true);
以便再次执行查询。事实证明,这比立即应用查询过滤器onRestoreInstanceState()
更好。对于后者,列表很快显示为未过滤,然后再次应用查询。使用setQuery()
时,这不会发生。
问题:执行查询并过滤列表,但搜索视图仍然处于折叠状态。因此,用户无法使用搜索视图删除过滤器或应用其他查询。
在onCreateOptionsMenu()
我可以确定搜索项和搜索视图存在,因此我可以调用searchItem.expandActionView()
。奇怪的是,只有这会真正扩展ActionView
- 调用setIconified(false)
不会扩展视图,即使连续两次调用它也不会。
如果我在致电expandActionView()
之前使用setQuery()
,则会打开SearchView
并显示文字(否则expandActionView()
清空SearchView
)。
不幸的是,expandActionView()
有副作用:还会显示建议列表并打开键盘。
我可以使用searchView.clearFocus()
隐藏键盘。所以剩下的问题是建议清单。如何关闭包含文字的SearchView
上的公开建议列表?
我想知道是否有更好的方法可以在操作栏中恢复没有太多副作用的搜索视图。
答案 0 :(得分:12)
我找到了一个解决方法。它非常难看,但它确实有效。
所以这是我在配置更改后能够恢复搜索框实例状态的方法。
首先,恢复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方法中,以使其工作。
这使得丑陋的原因是恢复步骤分散在生命周期的各个阶段,并且需要递归视图搜索才能到达建议列表。
答案 1 :(得分:7)
以我的拙见。如果要恢复searchView状态,我们应该使用onSaveInstanceState(Bundle outState)。被调用以在被杀死之前从活动中检索每个实例状态,以便可以在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);
}
在活动可能被杀死之前调用此方法,以便在将来某个时间返回时可以恢复其状态。现在,当用户更改方向时,可以通过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。