You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

进入上下文操作模式时如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 12:48:01