Jetpack Navigation按返回键先关闭SearchView无法直接返回上一页
问题产生原因
- 根本原因是你给SearchView对应的菜单项加了
app:showAsAction="collapseActionView|ifRoom"配置,这是系统ActionBar菜单的默认行为规则:只要绑定的ActionView(这里就是SearchView)处于展开状态,返回事件(不管是点Toolbar左上角的返回按钮,还是按系统返回键)都会优先被ActionView拦截消费,第一次按返回只会把SearchView折成图标,根本不会传到Navigation Component的返回栈逻辑里。 - 你在代码里主动调用了
searchItem.expandActionView()和isIconified = false,页面一进来SearchView就是全展开的状态,所以第一次返回必然先触发SearchView自己的收起逻辑,等SearchView收起来了,第二次返回事件才能传到Navigation组件执行页面返回,这就是要按两次返回的原因,和Navigation组件本身逻辑无关。
修改方案
不需要修改menu布局文件,只要在Fragment里补充两段逻辑即可:
- 拦截菜单项的折叠事件,屏蔽默认收起SearchView的行为,触发折叠时直接执行导航返回
在onCreateOptionsMenu方法中获取到searchItem后,添加折叠状态监听:
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { override fun onMenuItemActionExpand(item: MenuItem): Boolean { // 允许SearchView正常展开 return true } override fun onMenuItemActionCollapse(item: MenuItem): Boolean { // 拦截默认折叠动作,直接返回上一页面 findNavController().navigateUp() // 返回false告知系统不执行SearchView收起的默认逻辑 return false } })
- 接管系统返回键事件,避免按压系统返回键时仍然先收起SearchView
在Fragment的onViewCreated方法中添加返回键回调,优先处理导航返回:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 回调和Fragment视图生命周期绑定,不会造成内存泄漏 requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { findNavController().navigateUp() } }
修改完成后,无论是点击SearchView左侧的返回箭头,还是按压系统返回键,都会直接触发导航返回上一页面,不会先执行SearchView收起操作。
内容的提问来源于stack exchange,提问作者Abdullah Celik
相关产品推荐
相关产品推荐

