【问题标题】:Fragment replacement triggers onQueryTextChange on searchview片段替换在 searchview 上触发 onQueryTextChange
【发布时间】:2014-06-25 23:59:16
【问题描述】:

这就是我浏览我的应用程序的方式:

  • 用列表打开片段
  • 按在搜索视图中输入的文本过滤列表
  • 点击列表项(列表片段被详细片段替换)
  • 向后导航(详细片段被列表片段替换)

当我从列表导航到细节片段时,我想将搜索视图的当前过滤器保留在字符串变量中。我在执行 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 中。

堆栈:

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}

导航时如何防止搜索视图被系统清除?

谢谢。

【问题讨论】:

标签: android android-fragments save state searchview


【解决方案1】:
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() 我解决了我的问题,也许它可以帮助某人

【讨论】:

  • 请添加解释以提高洞察力并为 OP 提供更多信息
【解决方案2】:

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

android:showAsAction="always|collapseActionView"

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

这样做的原因是,当您尝试更改 Fragment 时,当前展开 SearchView 时会触发 onQueryTextChange 回调。

collapseActionView在这个阶段的默认动作是collapse改变Fragment时的SearchView。

解决方案

只需在 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
    }
})

【讨论】:

    【解决方案3】:

    使用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
        }
    })
    

    【讨论】:

      【解决方案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;
      }
      

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

      【讨论】:

      • 检查 !isVisible() 简单有效。
      【解决方案5】:

      这是我的解决方案:

       @Override
              public boolean onQueryTextChange(final String newText) {
      
                  if (searchTF.isIconified())
                      return false;
      
                  // put the "real" onQueryTextChange actions here
      
      
                  return true;
      
      
              }
      

      【讨论】:

        【解决方案6】:

        经过 2 天的谷歌搜索,我得到了绝对可以帮助您的解决方案。

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

        我不知道为什么会这样,我认为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);
        }
        

        谢谢:)

        【讨论】:

        • 我已经尝试了很多方法,但 onQueryTextChange 并没有在我的应用程序的每个片段中被调用。
        【解决方案7】:

        我看到你还没有找到解决方案,我有同样的problem 发布here

        我发现,当invalidateOptionsMenu 被调用时,onQueryTextChange 方法也被调用,因为在您清除搜索示例后,View 会使用先前的值启动 dispatchRestoreInstanceState。你会打电话给invalidateOptionsMenu 吗?

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

        您还可以在您使用的每个类、Fragment 或 Main Activity 类上实现 SearchView.OnQueryTextListener,您可以在类中的某个位置设置一个布尔模块变量,您将在 onQueryTextChange. 中检查该变量

        p>

        【讨论】:

        • 我已经发布了我的解决方案,可能会对您的问题有所帮助。
        【解决方案8】:

        我将菜单项属性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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-12
          • 2012-04-21
          相关资源
          最近更新 更多