java - 两个 fragment 之间带有(共享?)android.widget.SearchView 的 Android FragmentActivity?

标签 java android android-fragments searchview

我有一个带有两个 fragment 的 FragmentActivity (support-v4)。 两者都包含一个带有 ActionBar 的 SearchView 的菜单。

播放列表 fragment :

@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 的方法。

如您所见,调用最后一个 searchInPlaylist(max) 时使用的参数与之前我在 FilterlistFragment SearchView 中键入的参数相同。 为什么这个搜索参数在两个不同的 SearchView 之间传递? 我怎样才能将它重置为默认的空字符串?

是否需要在 FilterlistFragment 的 onDestroyView 中进行一些特殊处理以取消当前的 SearchView?

附言

我找到原因但没有解决办法: 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'})

打电话。

关于新 fragment 的方法

com.android.internal.view.menu.MenuBuilder#restoreActionViewStates

在 onPrepareOptionsMenu 之后调用以恢复旧的 View 状态。 因此,我的 ActionBar/SearchView/TextView 使用 query=max 从这个 Bundle 中恢复了一个(错误的)状态。 这会触发来自 SearchView 的 onTextChange,因此会在我的新 fragment 中触发对“max”的 sql 搜索,如您所见的最后一行日志。

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

最佳答案

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

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

关于java - 两个 fragment 之间带有(共享?)android.widget.SearchView 的 Android FragmentActivity?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31657717/

相关文章:

java - 尝试部署到 tomcat 时,由 : java. lang.NoSuchFieldError: NULL 引起

带有背景提示的 Android Searchview

android - 集成 Quickblox Android SDK 以进行聊天

java - 在 Android Activity 之间共享 View 的正确方法?

android - 持续配置更改的 DialogFragment 监听器

java - 在 Wildfly 中使用多个数据源

java - “mvnw”不被识别为内部或外部命令

java - Eclipse Java JTable 与表

android - 测试GPS数据是否被删除

android - 如何获取对最后一个 backstack 弹出 fragment 的引用?