Skip to content
<style> .vp-card { max-width: 800px; margin: 20px auto; padding: 30px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); } .code-block { position: relative; } .copy-btn { position: absolute; top: 10px; right: 10px; background: rgba(255,255,255,0.8); border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; } </style>

Android 15+ ステータスバー色変更

Android status bar

Android 15(APIレベル35)以降でステータスバーの色を変更する方法について解説します。従来のwindow.statusBarColorメソッドは非推奨となったため、WindowInsets APIを使用した新しいアプローチが必要です。

重要

従来のwindow.statusBarColor = Color.RED はAndroid 15以降で非推奨となり効果がありません

ステータスバー色変更の実装方法

方法1: WindowInsetsを使用した推奨手法(Android 15+)

kotlin
fun setStatusBarColor(window: Window, color: Int) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
        window.decorView.setOnApplyWindowInsetsListener { view, insets ->
            val statusBarInsets = insets.getInsets(WindowInsets.Type.statusBars())
            view.setBackgroundColor(color) // 背景色設定
            view.setPadding(0, statusBarInsets.top, 0, 0) // パディング調整
            insets
        }
    } else {
        // 従来手法 (Android 14以前)
        window.statusBarColor = color
    }
}

使用方法

アクティビティで次のように呼び出します:

kotlin
setStatusBarColor(window, Color.RED)

方法2: 一時的なオプトアウト(非推奨)

xml
<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
    <item name="android:statusBarColor">@color/primary_color</item>
</style>

WARNING

windowOptOutEdgeToEdgeEnforcement 属性は将来的に削除されます。一時的な対策としてのみ使用してください。

Jetpack Composeでの実装方法

kotlin
Box(Modifier.fillMaxSize()) {
    // メインコンテンツ
    Content()
    
    // ステータスバー背景色用スペーサー
    Spacer(
        Modifier
            .windowInsetsTopHeight(WindowInsets.statusBars)
            .fillMaxWidth()
            .background(Color.Red)
    )
}
アクティビティ全体コード
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    setContent {
        Box(Modifier.fillMaxSize()) {
            // アプリメインコンテンツ
            Content()
            
            // ステータスバー背景設定
            Spacer(
                Modifier
                    .windowInsetsTopHeight(WindowInsets.statusBars)
                    .fillMaxWidth()
                    .align(Alignment.TopCenter)
                    .background(Color.Red)
            )
        }
    }
}

多バージョン対応ユーティリティ

kotlin
object StatusBarUtils {
    private const val TAG_STATUS_BAR = "STATUS_BAR_TAG"

    fun setStatusBarColor(activity: Activity, color: Int) {
        val window = activity.window
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
            // Android 15以上の処理
            applyModernStatusBarColor(window, color)
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // Android 5~14の処理
            window.statusBarColor = color
        }
    }

    private fun applyModernStatusBarColor(window: Window, color: Int) {
        ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { v, insets ->
            val statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars())
            v.setPadding(0, statusBarInsets.top, 0, 0)
            v.setBackgroundColor(color)
            WindowInsetsCompat.CONSUMED
        }
    }
}

ベストプラクティス

  1. エッジツーエンドデザインを採用

    kotlin
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge() // 必須
        // ...
    }
  2. ステータスバーの高さを自動取得

    kotlin
    val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top
  3. ライト/ダークモード対応

    kotlin
    WindowCompat.getInsetsController(window, window.decorView).run {
        isAppearanceLightStatusBars = !isDarkModeEnabled
    }
  4. 下位互換性の考慮

    kotlin
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
        // Android 15+ 専用処理
    } else {
        // 従来の処理
    }

トラブルシューティング

一般的な問題と解決策

症状解決方法
色が変わらないenableEdgeToEdge()setContent()より前に呼び出す
コンテンツと重なるsetPadding()でステータスバー高さ分の上パディングを追加
一時的な色変更WindowCompat.getInsetsControllerで動的変更

参考リソース

<script> document.querySelector('.code-block button.copy-btn').addEventListener('click', function(e) { const block = this.parentElement; const code = block.querySelector('code').innerText; navigator.clipboard.writeText(code); this.textContent = 'コピー完了!'; setTimeout(() => this.textContent = 'コピー', 2000); }); </script>