본문 바로가기
안드로이드 코틀린

[Kotlin][Android] Jetpack Compose로 system bar 색 변경하기

by teamnova 2022. 9. 27.

안녕하세요.

오늘은 XML 파일을 수정하지 않고 Compose를 사용하여 상태 표시줄과 탐색 표시줄 색상을 변경하는 방법을 알아보겠습니다. 

 

Jetpack Compose 이전에는 system bar색상을 지정하기 위해 일반적으로 다음 themes.xml과 같이 파일을 수정했습니다.

 

<resources>
    <style name="Theme.BarColors" parent="android:Theme.Material.Light.NoActionBar">
        <item name="android:statusBarColor">@color/purple_700</item>
        <item name="android:navigationBarColor">@color/purple_700</item>
    </style>
</resources>

 android:statusBarColor및 android:navigationBarColor속성은 각각 상태 표시줄 색상과 탐색 표시줄 색상에 영향을 줍니다.

 

android:windowLightStatusBar (상태 표시줄의 아이콘을 어둡게 만들기 위해) 또는 android:windowLightNavigationBar(탐색 표시줄과 유사하게 ) 지정할 수 있습니다. (후자는 API 레벨 27이 필요 합니다.)

폴더 themes.xml아래의 다른 파일에서 이 속성을 재정의해야 합니다. values-27이와 같은 속성이 많을 때 매우 지저분한 구조로 이어질 수 있습니다. 어두운 테마를 지원하려면 더욱 복잡해질 수 있습니다. 

 

Compose에는 이를 수행하는 다른 방법이 있습니다.

 

먼저 구현을 위해 Compose를 사용하여 중앙에 텍스트를 표시하는 간단한 화면을 만들어보겠습니다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
		
        setContent {
            BarColorsTheme {
                Surface {
                    Text(
                        modifier = Modifier
                            .fillMaxSize()
                            .wrapContentHeight(),
                        textAlign = TextAlign.Center,
                        style = MaterialTheme.typography.h3,
                        text = "Hello Android!",
                    )
                }
            }
        }
    }
}

 

프로젝트를 새로 만들때 Empty Compose Activity를 선택하면 위에서 사용되는 함수를 사용할 수 있습니다. 

 

private val DarkColorPalette = darkColors(
    primary = Purple200,
    primaryVariant = Purple700,
    secondary = Teal200
)

private val LightColorPalette = lightColors(
    primary = Purple500,
    primaryVariant = Purple700,
    secondary = Teal200
)

@Composable
fun BarColorsTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}

위 코드는 프로젝트 전체에 대한 적절한 색상 팔레트(어두운 테마 활성화 여부에 따라), 타이포그래피 및 모양을 지정하는 루트 컴포저블 역할을 합니다.

 

@Composable  
fun BarColorsTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {  
	// ...
    val view = LocalView.current  
    if (!view.isInEditMode) {  
        SideEffect {  
            val window = (view.context as Activity).window  
            window.statusBarColor = colors.primary.toArgb()  
            window.navigationBarColor = colors.primary.toArgb()  
  
            WindowCompat.getInsetsController(window, view)  
                .isAppearanceLightStatusBars = darkTheme  
            WindowCompat.getInsetsController(window, view)  
                .isAppearanceLightNavigationBars = darkTheme  
        }  
    }  
	// ...
}

 

변수 WindowCompat값에 따라 상태 표시줄과 탐색 표시줄 아이콘을 밝게 또는 어둡게 만드는 데 사용합니다. 

darkTheme사용의 좋은 이점은 WindowCompat해당 메서드를 실행하기 전에 API 수준을 확인할 필요가 없다는 것입니다. 뒤에서 지원되지 않는 API에는 영향을 미치지 않습니다.

이러한 변경을 수행하고 앱을 실행하면 원하는 효과를 얻을 수 있습니다.

 

Compose로 변경된 시스템 표시줄 색상

 

현재 테마에 맞는 시스템 표시줄 색상