PAYATHON 2026

Android 支付 SDK 结束后如何恢复 status bar color

支付小周

结论

colorPrimaryDark 资源无法在运行时被“覆盖”。应用构建完成后,资源值不会因为支付 SDK 启动而被永久修改。

状态栏一直显示红色,通常是因为支付 SDK 修改了当前 Window 的 statusBarColor 或系统栏标志,而应用页面恢复时没有重新设置。可以在支付结束或页面重新获得焦点后,主动恢复状态栏颜色。通常把这段逻辑放在宿主 Activity 的 onResume() 中,也可以在支付结果回调中执行。

推荐做法

从支付页面返回后,重新设置当前 Activity 的状态栏颜色:

class PaymentActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        restoreStatusBar()
    }

    private fun restoreStatusBar() {
        window.statusBarColor = ContextCompat.getColor(
            this,
            R.color.status_bar_blue
        )

        WindowCompat.getInsetsController(window, window.decorView)
            .isAppearanceLightStatusBars = false
    }
}

对应的颜色资源:

<!-- res/values/colors.xml -->
<color name="status_bar_blue">#1565C0</color>

isAppearanceLightStatusBars = false 表示使用浅色状态栏图标,适合较深的蓝色背景。状态栏背景较浅时,应将其设置为 true,改用深色图标。

在支付结果回调中恢复

如果 SDK 通过 Activity Result 返回结果,可以在回调中恢复状态栏:

private val paymentLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        restoreStatusBar()

        if (result.resultCode == Activity.RESULT_OK) {
            // 处理支付成功结果
        } else {
            // 处理取消或失败结果
        }
    }

private fun startPayment(intent: Intent) {
    paymentLauncher.launch(intent)
}

private fun restoreStatusBar() {
    window.statusBarColor = ContextCompat.getColor(
        this,
        R.color.status_bar_blue
    )

    WindowCompat.getInsetsController(window, window.decorView)
        .isAppearanceLightStatusBars = false
}

即使回调中已经恢复了状态栏,也建议保留 onResume() 中的设置。部分 SDK 可能通过内部 Activity、回调或窗口标志改变系统栏外观,实际执行顺序不一定相同。

Java 写法

@Override
protected void onResume() {
    super.onResume();

    getWindow().setStatusBarColor(
        ContextCompat.getColor(this, R.color.status_bar_blue)
    );

    WindowInsetsControllerCompat controller =
        WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());

    controller.setAppearanceLightStatusBars(false);
}

为什么修改主题没有生效

主题配置主要在创建 Activity 时用于初始化窗口,例如:

<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="colorPrimaryDark">@color/status_bar_blue</item>
    <item name="android:statusBarColor">@color/status_bar_blue</item>
    <item name="android:windowLightStatusBar">false</item>
</style>

如果 SDK 在运行期间调用了类似代码:

window.statusBarColor = Color.RED

这个运行时设置会覆盖主题初始化的颜色。返回原来的 Activity 时,该 Activity 通常不会重新创建,主题自然也不会再次应用。因此,需要在生命周期回调中主动恢复状态栏。

另外,colorPrimaryDark 只是主题属性,并不是可以在运行时修改的全局状态。SDK 更可能修改自己的窗口或宿主窗口,而不是资源文件中的值。

如果仍然无法恢复

检查 SDK 是否直接在宿主 Activity 中展示支付界面,例如使用 Dialog、Fragment 或透明页面。如果 SDK 修改了窗口标志,可以先清除相关设置,再恢复颜色:

private fun restoreStatusBar() {
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)

    window.statusBarColor = ContextCompat.getColor(
        this,
        R.color.status_bar_blue
    )

    WindowCompat.getInsetsController(window, window.decorView)
        .isAppearanceLightStatusBars = false
}

还要确认应用是否启用了 edge-to-edge。启用后,状态栏可能是透明的,用户看到的颜色实际上来自状态栏下方的页面背景,而不是 statusBarColor。此时需要同时设置顶部容器的背景和 Window Insets,仅修改 colorPrimaryDark 并不能解决问题。

注意事项

  • 不要尝试在运行时修改 R.color 或 colorPrimaryDark,编译后的资源不是可变配置。
  • 新代码不推荐使用 onActivityResult(),应优先使用 Activity Result API。
  • 如果 SDK 提供“关闭”“支付完成”或“页面销毁”回调,可以在回调中恢复状态栏,但 onResume() 通常更稳妥。
  • 如果应用支持浅色和深色主题,应分别提供颜色资源,例如放在 values/colors.xml 和 values-night/colors.xml 中。
  • Android 15 及后续版本对 edge-to-edge 的处理可能影响系统栏的最终效果,具体表现取决于应用的 target SDK、主题和布局方式。

备注:内容仅供参考。