SearchView
に折りたたみ可能なActionBar
があります。検索が実行された後、関連するListView
がフィルタリングされ、一致するアイテムのみが表示されます。その状態の間、SearchView
は展開されたままで、検索文字列が表示されます。ユーザーがSearchView
を閉じると、フィルターを削除します。
検索状態を復元したい、例えば構成の変更時、または別のアクティビティから戻ったときにアクティビティが破棄された場合。
onRestoreInstanceState()
でクエリ文字列を復元し、onCreateOptionsMenu()
でクエリ文字列を見つけた場合は
searchView.setQuery(query, true);
クエリを再度実行するため。これは、クエリフィルターをすぐに適用するよりも優れていることがわかりましたonRestoreInstanceState()
。後者の場合、リストはすぐにフィルタリングされずに表示され、クエリが再度適用されます。 setQuery()
では、これは起こりません。
問題:クエリが実行され、リストがフィルタリングされますが、検索ビューは折りたたまれたままです。したがって、ユーザーは検索ビューを使用してフィルターを削除したり、別のクエリを適用したりすることはできません。
onCreateOptionsMenu()
では、検索アイテムと検索ビューが存在することを確認できるため、searchItem.expandActionView()
を呼び出すことができます。不思議なことに、これだけが実際にActionView
を展開します。setIconified(false)
を呼び出しても、2回続けて呼び出された場合でも、ビューは展開されません。
expandActionView()
を呼び出す前にsetQuery()
を使用すると、SearchView
が開き、テキストが表示されます(それ以外の場合、expandActionView()
はSearchView
を空にします)。
残念ながら、expandActionView()
には副作用があります。提案リストも表示され、キーボードが開きます。
searchView.clearFocus()
を使用してキーボードを非表示にできます。したがって、残りの問題は提案リストです。テキストのあるSearchView
で開いている提案リストを閉じるにはどうすればよいですか?
それほど多くの副作用がないアクションバーの検索ビューを復元するためのより良い方法があるのだろうか。
回避策を見つけました。それは非常に醜いですが、それは機能します。
これが、構成の変更後に検索ボックスインスタンスの状態を復元する方法です。
まず、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メソッドに移動する必要がありました。
これを非常に醜いものにしているのは、復元手順がライフサイクルのさまざまなフェーズに分散していることと、提案リストに到達するために再帰的なビュー検索が必要であるという事実です。
私の愚見で。 searchViewの状態を復元する場合は、 onSaveInstanceState(Bundle outState) を使用する必要があります。 onCreate(Bundle)または onRestoreInstanceState(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)を介してユーザーインターフェイスの状態を復元できます。
SearchViewにフォーカスする必要があるため、 onCreateOptionsMenu(Menu menu) を使用する必要があります。
@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);
}
また、完全なコードで このリンク を確認することもできます。