Android FragmentActivity与两个片段之间的(共享?)android.widget.SearchView?

时间:2015-07-27 15:53:34

标签: java android android-fragments searchview

我有一个带有两个片段的FragmentActivity(support-v4)。 两者都包含一个菜单,其中包含ActionBar的SearchView。

PlaylistFragment:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    Log.d(LOGTAG, String.format("onCreateOptionsMenu(%s,%s)", this, menu));
    inflater.inflate(R.menu.playlist_ab_menu, menu);
    buildLocalSearchView(menu.findItem(R.id.menu_playlist_search));
    super.onCreateOptionsMenu(menu, inflater);
}
private void buildLocalSearchView(MenuItem item) {
    SearchView searchView = (SearchView) item.getActionView();
    searchView.setSubmitButtonEnabled(false);
    searchView.setIconifiedByDefault(true);
    searchView.setIconified(true);
    //don't work because a bug in android, @see https://code.google.com/p/android/issues/detail?id=25758
    searchView.setOnCloseListener(this);
    //workaround for the above
    MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            return true;
        }

        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            return true;
        }
    });
    searchView.setOnQueryTextListener(adapter);
}

和FilterlistFragment类似:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    Log.d(LOGTAG, String.format("onCreateOptionsMenu(%s,%s)", this, menu));
    inflater.inflate(R.menu.filterlist_ab_menu, menu);
    // Get the SearchView and set the searchable configuration
    buildLocalSearchView(menu.findItem(R.id.menu_filterlist_search));
    super.onCreateOptionsMenu(menu, inflater);
}

但是如果我现在在FilterlistFragment中开始搜索并且关闭SearchView但切换到PlaylistFragment,则查询字符串从FilterlistFragment转移到PlaylistFragment。但是ActionBar-SearchView在PlaylistFragment中就像关闭一样可见。

切换到PlaylistFragment后,我可以在我的日志中看到:

07-25 05:09:29.277    3315-3315/de.NullZero.ManiDroid D/de.NullZero.ManiDroid.presentation.fragments.FilterListFragment﹕ onDestroyView(FilterListFragment{b12b8090 #2 id=0x7f0a0085 FILTER_2})
07-25 05:09:29.277    3315-3315/de.NullZero.ManiDroid D/PlaylistFragment﹕ onCreate(PlaylistFragment{b13dcc58 #3 id=0x7f0a0085 PLAYLIST},null)
07-25 05:09:29.277    3315-3315/de.NullZero.ManiDroid D/PlaylistFragment﹕ onViewCreated(PlaylistFragment{b13dcc58 #3 id=0x7f0a0085 PLAYLIST},null)
07-25 05:09:29.277    3315-3315/de.NullZero.ManiDroid D/de.NullZero.ManiDroid.presentation.ManiDroidAppActivity﹕ onBackStackChanged() Fragment:PlaylistFragment{b13dcc58 #3 id=0x7f0a0085 PLAYLIST}
07-25 05:09:29.287    3315-3360/de.NullZero.ManiDroid D/DEBUG﹕ searchInPlaylist() = 2 ms
07-25 05:09:29.307    3315-3315/de.NullZero.ManiDroid D/PlaylistFragment﹕ onCreateOptionsMenu(PlaylistFragment{b13dcc58 #3 id=0x7f0a0085 PLAYLIST},com.android.internal.view.menu.MenuBuilder@b106ad90)
07-25 05:09:29.317    3315-3315/de.NullZero.ManiDroid D/PlaylistFragment﹕ onPrepareOptionsMenu(PlaylistFragment{b13dcc58 #3 id=0x7f0a0085 PLAYLIST},com.android.internal.view.menu.MenuBuilder@b106ad90)
07-25 05:09:29.477    3315-3364/de.NullZero.ManiDroid D/DEBUG﹕ searchInFilter(, ManitobaFilter{filterName='Zuletzt gehört'}) = 178 ms
07-25 05:09:29.477    3315-3364/de.NullZero.ManiDroid D/DEBUG﹕ searchInPlaylist(max) = 1 ms

searchInPlaylist()方法是PlaylistFragment的SearchView(适配器)方法,searchInFilter(...)方法是FilterlistFragment的方法。

正如您所看到的那样,使用与我在FilterlistFragment SearchView中输入之前相同的参数调用最后一个searchInPlaylist(max)。 为什么在两个不同的SearchView之间传输此搜索参数? 如何将其重置为默认的空字符串?

在FilterlistFragment中onDestroyView需要一些特殊的处理来取消当前的SearchView吗?

P.S。

我找到原因但没有解决方案:        com.android.internal.widget.ActionBarView.ExpandedActionViewMenuPresenter#collapseItemActionView

来电

    // Do this before detaching the actionview from the hierarchy, in case
    // it needs to dismiss the soft keyboard, etc.
    if (mExpandedActionView instanceof CollapsibleActionView) {
        ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
    }

由于我的setOnQueryTextListener,这将触发setQuery(“”),因此会触发sql-search。在上面的日志中,这是

07-25 05:09:29.477    3315-3364/de.NullZero.ManiDroid D/DEBUG﹕searchInFilter(, ManitobaFilter{filterName='Zuletzt gehört'})

呼叫。

在新片段上方法

com.android.internal.view.menu.MenuBuilder#restoreActionViewStates
在onPrepareOptionsMenu之后调用

来恢复旧的视图状态。 因此,我的ActionBar / SearchView / TextView使用query = max从此Bundle恢复(错误)状态。 这会触发来自SearchView的onTextChange,因此在我的新片段中搜索“max”,因为您可以看到最后一个日志行。

如何禁用ActionBar / SearchView / TextView的保存和恢复?

1 个答案:

答案 0 :(得分:1)

@Override
public void onDestroyView() {
    super.onDestroyView();
    Log.d(LOGTAG, String.format("onDestroyView(%s)", this));
    searchView.setOnQueryTextListener(null);
    searchView.setQuery("", true);
}

这样就可以了。 真的很难看,因为它们都具有相同的TextView,因此不可能使用多个SearchView,因此可以从同一个Bundle-Key保存/恢复。