如何正确隐藏ActionBar?切换Fragment时出现灰色残留问题
我有一个包含多个Fragment的AppCompatActivity,要求ActionBar始终可见,仅在打开MyTestFragment时隐藏它。
在Activity的onCreate方法中调用supportActionBar?.hide()可以正常隐藏ActionBar,但在Fragment的onActivityCreated中通过(activity as AppCompatActivity).supportActionBar!!.hide()调用时,ActionBar并未完全消失,顶部会出现一条灰色痕迹。
测试代码显示:在onCreate中立即隐藏(标记1)正常,延迟后显示(标记2)正常,但再次延迟隐藏(标记3)就会出现灰色痕迹,说明只有在初始化阶段隐藏ActionBar才正常,后续操作会出现问题。
布局使用了DrawerLayout嵌套CoordinatorLayout,其中包含自定义的BondToolbarLayout,滚动视图设置了appbar_scrolling_view_behavior。
- 仅调用
supportActionBar.hide()只会隐藏ActionBar的内容,但自定义的BondToolbarLayout(作为ActionBar的载体)可能仍处于可见状态或残留背景,导致顶部出现痕迹。 - 使用
CoordinatorLayout和appbar_scrolling_view_behavior时,当ActionBar已经显示过再隐藏,滚动视图的布局位置未自动更新,导致顶部留下空白/灰色区域。 - DrawerLayout中的
navigation_view_container设置了固定的marginTop="?android:attr/actionBarSize",即使ActionBar隐藏,该边距仍会保留,可能加剧顶部痕迹问题。
方案1:同时控制ToolbarLayout的可见性
不要只调用supportActionBar.hide(),同时将自定义ToolbarLayout设置为GONE,彻底隐藏其布局空间:
在Fragment中:
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) val activity = requireActivity() as AppCompatActivity // 隐藏ActionBar内容 activity.supportActionBar?.hide() // 彻底隐藏Toolbar布局 activity.findViewById<BondToolbarLayout>(R.id.toolbar_layout).visibility = View.GONE // 强制CoordinatorLayout重新布局,确保滚动视图位置更新 activity.findViewById<CoordinatorLayout>(R.id.coordinator_layout).requestLayout() }
恢复显示时同理:
override fun onDestroyView() { super.onDestroyView() val activity = requireActivity() as AppCompatActivity activity.supportActionBar?.show() activity.findViewById<BondToolbarLayout>(R.id.toolbar_layout).visibility = View.VISIBLE activity.findViewById<CoordinatorLayout>(R.id.coordinator_layout).requestLayout() }
(注意:需要给布局中的CoordinatorLayout添加idcoordinator_layout)
方案2:动态调整DrawerLayout侧边栏的边距
针对navigation_view_container的固定边距问题,在隐藏ActionBar时动态将其marginTop设为0:
val navContainer = activity.findViewById<FrameLayout>(R.id.navigation_view_container) val layoutParams = navContainer.layoutParams as DrawerLayout.LayoutParams layoutParams.topMargin = if (isActionBarHidden) 0 else resources.getDimensionPixelSize(android.R.attr.actionBarSize) navContainer.layoutParams = layoutParams
方案3:封装Activity中的ActionBar控制方法
在MainActivity中封装显示/隐藏方法,统一处理ActionBar和ToolbarLayout的状态,避免Fragment中重复代码:
class MainActivity : AppCompatActivity() { private lateinit var toolbarLayout: BondToolbarLayout private lateinit var coordinatorLayout: CoordinatorLayout private lateinit var navContainer: FrameLayout override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) toolbarLayout = findViewById(R.id.toolbar_layout) coordinatorLayout = findViewById(R.id.coordinator_layout) navContainer = findViewById(R.id.navigation_view_container) setSupportActionBar(toolbarLayout) } fun hideActionBar() { supportActionBar?.hide() toolbarLayout.visibility = View.GONE // 调整侧边栏边距 val layoutParams = navContainer.layoutParams as DrawerLayout.LayoutParams layoutParams.topMargin = 0 navContainer.layoutParams = layoutParams coordinatorLayout.requestLayout() } fun showActionBar() { supportActionBar?.show() toolbarLayout.visibility = View.VISIBLE val layoutParams = navContainer.layoutParams as DrawerLayout.LayoutParams layoutParams.topMargin = resources.getDimensionPixelSize(android.R.attr.actionBarSize) navContainer.layoutParams = layoutParams coordinatorLayout.requestLayout() } }
然后在Fragment中直接调用:
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) (activity as MainActivity).hideActionBar() } override fun onDestroyView() { super.onDestroyView() (activity as MainActivity).showActionBar() }
修改测试代码,加入ToolbarLayout的可见性控制:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_activity) val toolbarLayout = findViewById<BondToolbarLayout>(R.id.toolbar_layout) val coordinatorLayout = findViewById<CoordinatorLayout>(R.id.coordinator_layout) Thread { Thread.sleep(8000) mainExecutor.execute { supportActionBar?.show() toolbarLayout.visibility = View.VISIBLE coordinatorLayout.requestLayout() } }.start() Thread { Thread.sleep(12000) mainExecutor.execute { supportActionBar?.hide() toolbarLayout.visibility = View.GONE coordinatorLayout.requestLayout() } }.start() supportActionBar?.hide() toolbarLayout.visibility = View.GONE coordinatorLayout.requestLayout() }
此时标记3的隐藏操作应该不会再出现灰色痕迹。
内容的提问来源于stack exchange,提问作者Sirop4ik

