进入上下文操作模式时如何修改Android状态栏背景与图标颜色
实现方案
你可以通过在ActionMode生命周期中添加和ActionMode动画同步的状态栏属性动画实现平滑过渡效果,同时适配状态栏图标颜色,具体修改如下:
第一步:调整ActionMode背景色(可选,如果你需要深灰色操作栏)
你当前配置的Widget.App.ActionMode中背景用的是grey_100(浅灰色),如果需要深灰色可以替换为对应的深灰颜色值,比如:
<style name="Widget.App.ActionMode" parent="Widget.AppCompat.ActionMode"> <item name="background">@color/grey_800</item> </style>
第二步:修改Fragment中的ActionMode回调逻辑
在回调的生命周期中,记录原始状态栏状态,通过属性动画同步修改状态栏颜色和图标样式,动画时长和系统默认的ActionMode动画时长保持一致,实现平滑过渡:
val callback = object: ActionMode.Callback { // 保存原始状态栏状态,退出时复原 private var originalStatusBarColor: Int = 0 private var originalSystemUiFlags: Int = 0 private var statusBarAnimator: ValueAnimator? = null override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { requireActivity().menuInflater.inflate(R.menu.contextual_action_bar, menu) val window = requireActivity().window // 保存原始状态 originalStatusBarColor = window.statusBarColor originalSystemUiFlags = window.decorView.systemUiVisibility // 目标状态栏颜色,和ActionMode背景色保持一致即可 val targetStatusBarColor = ContextCompat.getColor(requireContext(), R.color.grey_800) // 动画时长和系统短动画时长对齐,和ActionMode动画同步 val animDuration = resources.getInteger(android.R.integer.config_shortAnimTime) // 执行状态栏颜色过渡动画 statusBarAnimator = ValueAnimator.ofArgb(originalStatusBarColor, targetStatusBarColor).apply { duration = animDuration.toLong() addUpdateListener { animator -> window.statusBarColor = animator.animatedValue as Int } start() } // 修改状态栏图标颜色为亮色(适配深色状态栏背景) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { window.decorView.systemUiVisibility = originalSystemUiFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() } // 若需兼容Android 11+ 可使用下方写法替换以上系统UI修改逻辑 // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // window.insetsController?.setSystemBarsAppearance( // 0, // WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS // ) // } return true } override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { return false } override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return false } override fun onDestroyActionMode(mode: ActionMode?) { val window = requireActivity().window val animDuration = resources.getInteger(android.R.integer.config_shortAnimTime) // 执行退出时的状态栏颜色复原动画 statusBarAnimator?.cancel() ValueAnimator.ofArgb(window.statusBarColor, originalStatusBarColor).apply { duration = animDuration.toLong() addUpdateListener { animator -> window.statusBarColor = animator.animatedValue as Int } start() } // 复原状态栏图标颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { window.decorView.systemUiVisibility = originalSystemUiFlags } // 若需兼容Android 11+ 可使用下方写法替换以上系统UI复原逻辑 // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // window.insetsController?.setSystemBarsAppearance( // originalSystemUiFlags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, // WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS // ) // } } } val actionMode = requireActivity().startActionMode(callback) actionMode?.title = "1 selected"
说明
这个方案的动画和系统ActionMode的出现/消失动画完全同步,不会出现生硬的跳转效果,和Google Files等官方应用的实现逻辑一致,适配Android 5.0及以上系统,低版本系统会自动降级不处理状态栏修改。
内容的提问来源于stack exchange,提问作者Tushar Kathuria
相关产品推荐
相关产品推荐

