片段替换触发searchView上的onQueryTextChange

时间:2014-05-08 14:15:44

标签: android android-fragments save state searchview

这是我浏览应用的方式:

  • 用列表
  • 打开片段
  • 按照在searchview中输入的文字过滤列表
  • 点击listitem(列表片段被细节片段替换)
  • 向后导航(详细信息片段被列表片段替换)

当我从list-detail-fragment导航时,我希望将searchview的当前过滤器保存在字符串变量中。我在执行onQueryTextChange时存储searchview的值。

问题: 我无法存储实际的过滤器值,因为当我从列表导航到详细信息时会调用onQueryTextChange,因为有些东西会清除搜索视图的文本。

// ...
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            searchReceived(s);
            return true;
        }
    });
// ...

public void searchReceived(String searchQuery)
{
    this.stateHolder.searchQuery = searchQuery;
    // more code...
}

当我想在导航回来时恢复过滤器时,它只是使用空字符串过滤,因为错误的值存储在this.stateHolder.searchQuery中。

Stack:

onQueryTextChange():139, EmployeeListFragment$1 {com.example.exampleapp.fragment}
onTextChanged():1153, SearchView {android.widget}
access$2000():92, SearchView {android.widget}
onTextChanged():1638, SearchView$11 {android.widget}
sendOnTextChanged():7408, TextView {android.widget}
setText():3816, TextView {android.widget}
setText():3671, TextView {android.widget}
setText():80, EditText {android.widget}
setText():3646, TextView {android.widget}
setQuery():511, SearchView {android.widget}
onActionViewCollapsed():1250, SearchView {android.widget}
collapseItemActionView():1662, ActionBarView$ExpandedActionViewMenuPresenter {com.android.internal.widget}
collapseItemActionView():1258, MenuBuilder {com.android.internal.view.menu}
clear():521, MenuBuilder {com.android.internal.view.menu}
doInvalidatePanelMenu():789, PhoneWindow {com.android.internal.policy.impl}
run():221, PhoneWindow$1 {com.android.internal.policy.impl}

如何在导航时阻止系统清除搜索视图?

感谢。

8 个答案:

答案 0 :(得分:5)

经过两天的谷歌搜索后,我得到的解决方案肯定能帮到你。

我只有cut and pasted代码从onCreateOptionMenu()onPrepareOptionMenu()

我不知道为什么会发生这种情况,我认为searchView的倾听者不会以NULL的方式改变您的代码。

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    getSherlockActivity().getSupportMenuInflater().inflate(R.menu.menu_all_order, menu);

    searchView = (SearchView) menu.findItem(R.id.menu_all_order_search).getActionView();
    searchView.setInputType(InputType.TYPE_CLASS_NUMBER);
    searchView.setQueryHint("Enter Order No");
    searchView.setOnQueryTextListener(this);
}

并删除:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
}

谢谢:)

答案 1 :(得分:4)

问题是ActionBar(和子组件)在替换包含它的片段时会崩溃。发生这种情况时,将清除SearchView查询,如onActionViewCollapsed中所示。解决方法包括:

防止崩溃

从搜索视图的创建代码中删除setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);或从其xml代码中删除android:showAsAction="collapseActionView"

这将影响在尝试折叠视图时关闭/语音搜索按钮的方式/时间

还可以通过覆盖SearchView的onActionViewCollapsed()方法来防止崩溃,但不会做任何事情,但会完成同样的事情。

在适当时忽略查询更改

当片段无效(被替换)时,忽略查询更改,否则会导致片段更改其保存的查询文本或布局(如果片段实际上没有视图,更改布局会导致异常含量)。

public boolean onQueryTextChange(String newText) {
    if (!isVisible()) {
        // The fragment was replaced so ignore
        return true;
    }
    // Text was actually changed, perform search
    return true;
}

这将是更好的选择,因为它不会影响搜索视图的功能。

答案 2 :(得分:2)

我发现您还没有找到解决方案,我发布了problem here {/ 3>}

我发现调用invalidateOptionsMenu时也调用方法onQueryTextChange,因为在您清除搜索后,View启动dispatchRestoreInstanceState具有上一个值。你打电话给invalidateOptionsMenu吗?

也许, onQueryTextChange内,您可以检查应用程序对象的某些当前状态的布尔值,以了解是否应该执行方法内容。在我的情况下,我使用mDrawerLayout.isDrawerOpen(..)来允许搜索。

你也可以在你使用的每个类上,SearchView.OnQueryTextListener或主活动类上实现Fragment,在类的某个地方你可以设置一个你将在里面检查的布尔模块变量{ {1}}

答案 3 :(得分:1)

我将菜单项属性showAsActionandroid:showAsAction="always|collapseActionView"修改为android:showAsAction="always"。现在,searchview的外观和行为发生了一些变化,但是searchQuery没有被清除!

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
            android:id="@+id/actionSearch"
            android:icon="@android:drawable/ic_menu_search"
            android:actionViewClass="android.widget.SearchView"
            android:showAsAction="always"
            android:title="@android:string/search_go"
    />
</menu>

答案 4 :(得分:0)

这是我的解决方案:

ValueError: arrays must all be same length

答案 5 :(得分:0)

使用androidx.appcompat.widget.SearchView + LiveData + ViewModel

searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
    override fun onQueryTextSubmit(query: String?): Boolean {
        viewModel.setSearchQuery(query)
        return true
    }
    override fun onQueryTextChange(newText: String?): Boolean {
        if(searchView.isIconified || !isVisible) {
            // Don't call setSearchQuery when SearchView is collapsing/collapsed
            return true
        }
        viewModel.setSearchQuery(newText)
        return true
    }
})

答案 6 :(得分:0)

如果有人遇到同样的问题,则当当前扩展时,在菜单XML文件中使用以下操作替换Fragment时,将触发onQueryTextChange回调:

android:showAsAction="always|collapseActionView"

当您尝试在onQueryTextChange回调中使用 isVisible()(Java)或 isVisible (Kotlin)作为确定片段是否实际可见的方式时,返回的值将始终返回 true

这样做的原因是,当您尝试更改Fragment的SearchView时,onQueryTextChange回调将被触发。

在此阶段, collapseActionView 的默认操作是在更改Fragment时折叠

解决方案

只需在onQueryTextChange回调中调用SearchView !isIconified (Kotlin)方法,并且仅在返回 false (即SearchView当前被扩展)时设置逻辑。 。完整示例如下所述:

yourSearchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
    override fun onQueryTextSubmit(query: String?): Boolean {
        // Do search query here if you use a submit action
        return true
    }

    override fun onQueryTextChange(newText: String?): Boolean {
        if (!yourSearchView.isIconified) {
            // Don't execute your search query here when SearchView is 
            // currently open
            return true
        }
        // Do search query here
        return true
    }
})

答案 7 :(得分:0)

override fun onQueryTextChange(newText: String?): Boolean {
   // your codes
   if (!newText.isNullOrBlank()) {
      // when fragment change
      // this will not work
   }
   // your codes
   return true
}

当片段更改 searchView 触发时,我不知道为什么,但通过检查此 newText.isNullOrBlank() 我解决了我的问题,也许它可以帮助某人