Compose의 머티리얼 테마 설정

Jetpack Compose는 디지털 인터페이스를 만들기 위한 포괄적인 디자인 시스템인 머티리얼 디자인 구현을 제공합니다. 머티리얼 디자인 구성요소(버튼, 카드, 스위치 등)는 제품 브랜드를 효과적으로 반영하기 위해 머티리얼 디자인을 맞춤설정하는 체계적인 방법인 머티리얼 테마 설정을 기반으로 빌드됩니다. 머티리얼 테마에는 색상, 서체도형 속성이 포함되어 있습니다. 이러한 속성을 맞춤설정하면 앱을 빌드하는 데 사용되는 구성요소에 변경사항이 자동으로 반영됩니다.

Jetpack Compose는 MaterialTheme 컴포저블을 사용하여 다음 개념을 구현합니다.

MaterialTheme(
    colors = …,
    typography = …,
    shapes = …
) {
    // app content
}

MaterialTheme에 전달하는 매개변수를 구성하여 애플리케이션의 테마를 설정합니다.

두 개의 대조되는 스크린샷. 첫 번째는 기본 MaterialTheme 스타일 지정을 사용하고 두 번째 스크린샷은 수정된 스타일 지정을 사용합니다.

그림 1. 첫 번째 스크린샷은 MaterialTheme을 구성하지 않는 앱을 보여주며 기본 스타일 지정을 사용합니다. 두 번째 스크린샷은 MaterialTheme에 매개변수를 전달하여 스타일 지정을 맞춤설정하는 앱을 보여줍니다.

색상

색상은 Compose에서 간단한 데이터 보유 클래스인 Color 클래스로 모델링됩니다.

val Red = Color(0xffff0000)
val Blue = Color(red = 0f, green = 0f, blue = 1f)

원하는 대로 색상을 구성할 수 있지만(예: 싱글톤 내에서 또는 정의된 인라인으로 최상위 상수로 구성) 테마에 색상을 지정하고 거기에서 색상을 검색하는 것이 좋습니다. 이 접근 방식을 사용하면 어두운 테마 및 중첩 테마를 손쉽게 지원할 수 있습니다.

테마 색상 팔레트의 예

그림 2. 머티리얼 색상 시스템.

Compose는 Colors 클래스를 제공하여 머티리얼 색상 시스템을 모델링합니다. Colors는 다음과 같이 밝거나 어두운 색상 세트를 만드는 빌더 함수를 제공합니다.

private val Yellow200 = Color(0xffffeb46)
private val Blue200 = Color(0xff91a4fc)
// ...

private val DarkColors = darkColors(
    primary = Yellow200,
    secondary = Blue200,
    // ...
)
private val LightColors = lightColors(
    primary = Yellow500,
    primaryVariant = Yellow400,
    secondary = Blue700,
    // ...
)

Colors를 정의한 후에는 MaterialTheme에 전달할 수 있습니다.

MaterialTheme(
    colors = if (darkTheme) DarkColors else LightColors
) {
    // app content
}

테마 색상 사용

MaterialTheme.colors를 사용하여 MaterialTheme 컴포저블에 제공된 Colors를 검색할 수 있습니다.

Text(
    text = "Hello theming",
    color = MaterialTheme.colors.primary
)

표시 경로 및 콘텐츠 색상

많은 구성요소가 한 쌍의 색상 및 콘텐츠 색상을 허용합니다.

Surface(
    color: Color = MaterialTheme.colors.surface,
    contentColor: Color = contentColorFor(color),
    // ...

TopAppBar(
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor),
    // ...

이를 통해 컴포저블의 색상을 설정할 수 있을 뿐만 아니라 그 안에 포함된 컴포저블인 콘텐츠의 기본 색상을 제공할 수도 있습니다. 많은 컴포저블은 기본적으로 이 콘텐츠 색상을 사용합니다. 예를 들어 Text는 상위 요소의 콘텐츠 색상을 기반으로 색상을 설정하고 Icon은 이 색상을 사용하여 색조를 설정합니다.

색상이 다른 동일한 배너의 두 가지 예

그림 3. 배경 색상을 다르게 설정하면 서로 다른 텍스트 및 아이콘 색상이 생성됩니다.

contentColorFor() 메서드는 테마 색상에 적절한 '설정' 색상을 검색합니다. 예를 들어 Surfaceprimary 배경 색상을 설정하면 메서드는 이 함수를 사용하여 onPrimary를 콘텐츠 색상으로 설정합니다. 테마가 아닌 배경 색상을 설정하는 경우 적절한 콘텐츠 색상도 지정해야 합니다. 계층 구조에 지정된 위치에서 현재 배경에 선호되는 콘텐츠 색상을 검색하려면 LocalContentColor를 사용합니다.

콘텐츠 알파

콘텐츠를 강조하는 정도를 달리하여 중요도를 전달하고 시각적 계층 구조를 알려야 할 때가 많습니다. 머티리얼 디자인 텍스트 가독성 권장사항에서는 다양한 수준의 불투명도를 사용하여 서로 다른 중요도 수준을 전달하도록 권장합니다.

Jetpack Compose에서는 LocalContentAlpha를 사용해 이를 구현합니다. CompositionLocal 값을 제공하여 계층 구조의 콘텐츠 알파를 지정할 수 있습니다. 중첩된 컴포저블은 이 값을 사용하여 콘텐츠에 알파 처리를 적용할 수 있습니다. 예를 들어 TextIcon은 기본적으로 LocalContentAlpha를 사용하도록 조정된 LocalContentColor 조합을 사용합니다. 머티리얼에서는 ContentAlpha 객체에 의해 모델링된 일부 표준 알파 값(high, medium, disabled)을 지정합니다.

// By default, both Icon & Text use the combination of LocalContentColor &
// LocalContentAlpha. De-emphasize content by setting content alpha
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
    Text(/*...*/)
}
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) {
    Icon(/*...*/)
    Text(/*...*/)
}

CompositionLocal에 관한 자세한 내용은 CompositionLocal을 사용한 로컬 범위 지정 데이터 가이드를 참고하세요.

다양한 텍스트 강조 수준을 보여주는 문서 제목의 스크린샷

그림 4. 텍스트에 다양한 수준의 강조를 적용하여 정보 계층 구조를 시각적으로 전달할 수 있습니다. 텍스트의 첫 번째 줄은 제목입니다. 가장 중요한 정보를 포함하고 있으므로 ContentAlpha.high를 사용합니다. 두 번째 줄은 덜 중요한 메타데이터를 포함하고 있으므로 ContentAlpha.medium을 사용합니다.

어두운 테마

Compose에서 MaterialTheme 컴포저블에 다양한 Colors 세트를 제공하여 밝은 테마 및 어두운 테마를 구현합니다.

@Composable
fun MyTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    MaterialTheme(
        colors = if (darkTheme) DarkColors else LightColors,
        /*...*/
        content = content
    )
}

이 예에서 MaterialTheme은 어두운 테마를 사용할지 여부를 지정하는 매개변수를 받는 자체의 구성 가능한 함수로 래핑되어 있습니다. 이 경우 함수는 기기 테마 설정을 쿼리하여 darkTheme의 기본값을 가져옵니다.

다음과 같은 코드를 사용하여 현재 Colors가 밝은지 아니면 어두운지 확인할 수 있습니다.

val isLightTheme = MaterialTheme.colors.isLight
Icon(
    painterResource(
        id = if (isLightTheme) {
          R.drawable.ic_sun_24dp
        } else {
          R.drawable.ic_moon_24dp
        }
    ),
    contentDescription = "Theme"
)

고도 오버레이

머티리얼에서 고도가 높은 어두운 테마의 표시 경로는 배경을 밝게 하는 고도 오버레이를 수신합니다. 표시 경로의 고도가 높을수록(암시적 광원에 더 가깝게 상승) 표시 경로가 더 밝아집니다.

이러한 오버레이는 어두운 색상을 사용할 때 표시 경로를 사용하는 다른 머티리얼 컴포저블에 Surface 컴포저블을 통해 자동으로 적용됩니다.

Surface(
    elevation = 2.dp,
    color = MaterialTheme.colors.surface, // color will be adjusted for elevation
    /*...*/
) { /*...*/ }

고도 수준이 다양한 요소에 사용되는 미묘하게 다른 색상을 보여주는 앱의 스크린샷

그림 5. 카드와 하단 탐색은 모두 surface 색상을 배경으로 사용합니다. 카드와 하단 탐색은 배경에서 서로 다른 고도 수준에 있기 때문에 색상이 약간 다릅니다. 카드가 배경보다 더 밝고 하단 탐색이 카드보다 더 밝습니다.

Surface를 사용하지 않는 맞춤 시나리오에는 Surface 구성요소에 사용되는 ElevationOverlay가 포함된 CompositionLocalLocalElevationOverlay를 사용합니다.

// Elevation overlays
// Implemented in Surface (and any components that use it)
val color = MaterialTheme.colors.surface
val elevation = 4.dp
val overlaidColor = LocalElevationOverlay.current?.apply(
    color, elevation
)

고도 오버레이를 중지하려면 컴포저블 계층 구조의 원하는 지점에 null을 제공합니다.

MyTheme {
    CompositionLocalProvider(LocalElevationOverlay provides null) {
        // Content without elevation overlays
    }
}

제한된 강조 색상

머티리얼에서는 대부분의 경우 primary 색상보다 surface 색상을 사용하는 것을 선호하기 때문에 어두운 테마에 제한된 강조 색상을 적용할 것을 권장합니다. TopAppBar, BottomNavigation 같은 머티리얼 컴포저블에서는 기본적으로 이 동작을 구현합니다.

그림 6. 제한된 강조 색상과 함께 사용된 머티리얼 어두운 테마. 상단 앱 바는 밝은 테마에는 기본 색상을 사용하고, 어두운 테마에는 표면 경로 색상을 사용합니다.

맞춤 시나리오에는 primarySurface 확장 속성을 사용합니다.

Surface(
    // Switches between primary in light theme and surface in dark theme
    color = MaterialTheme.colors.primarySurface,
    /*...*/
) { /*...*/ }

서체

머티리얼은 유형 시스템을 정의하여 의미론적으로 이름이 지정된 소수의 스타일을 사용하도록 권장합니다.

다양한 스타일의 여러 가지 다른 서체의 예

그림 7. 머티리얼 유형 시스템.

Compose는 Typography, TextStyle글꼴 관련 클래스를 사용하여 유형 시스템을 구현합니다. Typography 생성자는 각 스타일의 기본값을 제공하므로 맞춤설정하지 않으려는 스타일은 생략할 수 있습니다.

val Rubik = FontFamily(
    Font(R.font.rubik_regular),
    Font(R.font.rubik_medium, FontWeight.W500),
    Font(R.font.rubik_bold, FontWeight.Bold)
)

val MyTypography = Typography(
    h1 = TextStyle(
        fontFamily = Rubik,
        fontWeight = FontWeight.W300,
        fontSize = 96.sp
    ),
    body1 = TextStyle(
        fontFamily = Rubik,
        fontWeight = FontWeight.W600,
        fontSize = 16.sp
    )
    /*...*/
)
MaterialTheme(typography = MyTypography, /*...*/)

전체적으로 동일한 서체를 사용하려면 다음과 같이 defaultFontFamily parameter를 지정하고 TextStyle 요소의 fontFamily를 생략합니다.

val typography = Typography(defaultFontFamily = Rubik)
MaterialTheme(typography = typography, /*...*/)

텍스트 스타일 사용

TextStyle에는 MaterialTheme.typography를 통해 액세스됩니다. 다음과 같이 TextStyle를 검색합니다.

Text(
    text = "Subtitle2 styled",
    style = MaterialTheme.typography.subtitle2
)

다양한 용도의 다양한 서체가 혼합된 것을 보여주는 스크린샷

그림 8. 다양한 서체와 스타일을 사용하여 브랜드를 표현할 수 있습니다.

도형

머티리얼은 도형 시스템을 정의합니다. 이 시스템을 통해 대형, 중형 및 소형 구성요소의 도형을 정의할 수 있습니다.

다양한 머티리얼 디자인 도형을 보여주는 예

그림 9. 머티리얼 도형 시스템.

Compose는 Shapes 클래스를 통해 도형 시스템을 구현합니다. 이 클래스를 사용하면 각 크기 카테고리의 CornerBasedShape를 지정할 수 있습니다.

val Shapes = Shapes(
    small = RoundedCornerShape(percent = 50),
    medium = RoundedCornerShape(0f),
    large = CutCornerShape(
        topStart = 16.dp,
        topEnd = 0.dp,
        bottomEnd = 0.dp,
        bottomStart = 16.dp
    )
)

MaterialTheme(shapes = Shapes, /*...*/)

많은 구성요소가 기본적으로 이러한 도형을 사용합니다. 예를 들어 Button, TextFieldFloatingActionButton은 기본적으로 소형으로, AlertDialog는 기본적으로 중형으로, ModalDrawer은 기본적으로 대형으로 설정됩니다. 전체 매핑은 도형 구성표 참조를 참고하세요.

도형 사용

Shape에는 MaterialTheme.shapes를 통해 액세스됩니다. 다음과 같은 코드를 사용하여 Shape를 검색합니다.

Surface(
    shape = MaterialTheme.shapes.medium, /*...*/
) {
    /*...*/
}

머티리얼 도형을 사용하여 요소의 상태를 전달하는 앱의 스크린샷

그림 10. 도형을 사용하여 브랜드 또는 상태를 표현할 수 있습니다.

기본 스타일

Compose에는 Android 보기의 기본 스타일에 상응하는 개념이 없습니다. 머티리얼 구성요소를 래핑하는 구성 가능한 '오버로드' 함수를 직접 생성하여 비슷한 기능을 제공할 수 있습니다. 예를 들어 버튼 스타일을 만들려면 고유의 구성 가능한 함수로 버튼을 래핑하고 변경하려는 매개변수를 직접 설정하며 포함하는 컴포저블에 매개변수로 다른 매개변수를 노출합니다.

@Composable
fun MyButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        colors = ButtonDefaults.buttonColors(
            backgroundColor = MaterialTheme.colors.secondary
        ),
        onClick = onClick,
        modifier = modifier,
        content = content
    )
}

테마 오버레이

MaterialTheme 컴포저블을 중첩하여, Compose의 Android 보기에서 테마 오버레이와 동일한 기능을 구현할 수 있습니다. MaterialTheme가 색상, 서체, 도형의 기본값을 현재 테마 값으로 설정하기 때문에, 테마에 이러한 매개변수 중 하나만 설정되는 경우 다른 매개변수는 기본값을 유지합니다.

더욱이 뷰 기반 화면을 Compose로 이전할 때 android:theme 속성을 사용하는 것에 유의하세요. Compose UI 트리의 관련 부분에 새로운 MaterialTheme가 필요할 수 있습니다.

Owl 샘플의 세부정보 화면에서는 대부분의 화면에는 PinkTheme를, 관련 섹션에는 BlueTheme를 사용합니다. 아래 스크린샷과 코드를 참고하세요.

그림 11. Owl 샘플의 중첩 테마.

@Composable
fun DetailsScreen(/* ... */) {
    PinkTheme {
        // other content
        RelatedSection()
    }
}

@Composable
fun RelatedSection(/* ... */) {
    BlueTheme {
        // content
    }
}

구성요소 상태

상호작용(클릭, 전환 등)할 수 있는 머티리얼 구성요소는 서로 다른 시각적 상태일 수 있습니다. 상태에는 사용 설정, 중지, 누름 상태 등이 있습니다.

종종 컴포저블에는 enabled 매개변수가 있습니다. 이 매개변수를 false로 설정하면 상호작용이 방지되고, 색상과 고도 같이 구성요소 상태를 시각적으로 전달하기 위한 속성이 변경됩니다.

그림 12. enabled = true(왼쪽) 및 enabled = false(오른쪽) 상태의 버튼.

대부분의 경우 색상과 고도 같은 값에는 기본값을 사용할 수 있습니다. 서로 다른 상태에 사용되는 값을 구성해야 하는 경우 클래스와 편의성 함수를 사용할 수 있습니다. 아래 버튼 예시를 참고하세요.

Button(
    onClick = { /* ... */ },
    enabled = true,
    // Custom colors for different states
    colors = ButtonDefaults.buttonColors(
        backgroundColor = MaterialTheme.colors.secondary,
        disabledBackgroundColor = MaterialTheme.colors.onBackground
            .copy(alpha = 0.2f)
            .compositeOver(MaterialTheme.colors.background)
        // Also contentColor and disabledContentColor
    ),
    // Custom elevation for different states
    elevation = ButtonDefaults.elevation(
        defaultElevation = 8.dp,
        disabledElevation = 2.dp,
        // Also pressedElevation
    )
) { /* ... */ }

그림 13. 색상과 고도 값이 조정된, enabled = true(왼쪽)와 enabled = false(오른쪽) 상태의 버튼.

물결

머티리얼 구성요소는 물결 효과를 사용하여 구성요소가 상호작용 중임을 나타냅니다. 계층 구조에서 MaterialTheme를 사용하는 경우 Ripple은 수정자 내에 clickable, indication 같은 기본 Indication으로 사용됩니다.

대부분의 경우 기본 Ripple을 사용할 수 있습니다. 모양을 구성하려면 RippleTheme을 사용하여 색상과 알파 같은 속성을 변경하면 됩니다.

RippleTheme를 확장하고 defaultRippleColordefaultRippleAlpha 유틸리티 함수를 사용할 수 있습니다. 그런 다음 LocalRippleTheme를 사용하여 계층 구조에서 맞춤 물결 테마를 제공할 수 있습니다.

@Composable
fun MyApp() {
  MaterialTheme {
    CompositionLocalProvider(
      LocalRippleTheme provides SecondaryRippleTheme
    ) {
      // App content
    }
  }
}

@Immutable
private object SecondaryRippleTheme : RippleTheme {
  @Composable
  override fun defaultColor() = RippleTheme.defaultRippleColor(
    contentColor = MaterialTheme.colors.secondary,
    lightTheme = MaterialTheme.colors.isLight
  )

  @Composable
  override fun rippleAlpha() = RippleTheme.defaultRippleAlpha(
    contentColor = MaterialTheme.colors.secondary,
    lightTheme = MaterialTheme.colors.isLight
  )
}

alt_text

그림 14. RippleTheme을 통해 제공된 서로 다른 물결 효과 값의 버튼

머티리얼 디자인 3 및 Material You

Jetpack Compose는 차세대 머티리얼 디자인인 머티리얼 디자인 3 구현을 제공합니다. 머티리얼 3는 업데이트된 테마 설정 및 구성요소, Material You 맞춤설정 기능(동적 색상 등)을 포함하며 새로운 Android 12의 시각적 스타일 및 시스템 UI와 일관되도록 설계되었습니다.

먼저 새 Compose Material 3 종속 항목을 build.gradle 파일에 추가합니다.

implementation "androidx.compose.material3:material3:material3_version"

M3 테마에는 색 구성표서체 값이 포함되어 있으며 도형 업데이트가 곧 제공될 예정입니다. 이러한 값을 맞춤설정하면 앱을 빌드하는 데 사용되는 M3 구성요소에 변경사항이 자동으로 반영됩니다.

Jetpack Compose는 새로운 M3 MaterialTheme 컴포저블을 사용하여 다음 개념을 구현합니다.

MaterialTheme(
    colorScheme = …,
    typography = …
    // Updates to shapes coming soon
) {
    // M3 app content
}

M3 MaterialTheme에 전달하는 매개변수를 구성하여 애플리케이션의 테마를 설정합니다.

그림 15. 처음 두 스크린샷은 M3 MaterialTheme을 구성하지 않아 기본 스타일 지정을 사용하는 앱을 보여줍니다. 두 번째 스크린샷은 MaterialTheme에 매개변수를 전달하여 스타일 지정을 맞춤설정하는 앱을 보여줍니다.

색 구성표

머티리얼 디자인 3는 이름이 지정된 색상 '슬롯'(예: '기본', '배경', '오류')으로 색상을 분리하며 이 슬롯은 머티리얼 3 구성요소에서 사용합니다. 이러한 슬롯이 함께 색 구성표를 형성합니다. 각 슬롯에서 사용하는 색상 값은 접근성 요구사항을 충족하도록 선택된 색조 팔레트 세트에서 가져옵니다. 예를 들어 '기본' 슬롯은 반드시 '기본(대비)' 슬롯과 대비됩니다. 색 구성표는 밝은 테마와 어두운 테마에 모두 새로운 기본 기준 색상을 제공합니다.

그림 16. 기준 색상 값이 있는 머티리얼 3 색조 팔레트와 색 구성표

Compose는 ColorScheme 클래스를 제공하여 머티리얼 3 색 구성표를 모델링합니다. ColorScheme밝은 색 구성표나 어두운 색 구성표를 만드는 빌더 함수를 제공합니다.

private val Blue40 = Color(0xff1e40ff​​)
private val DarkBlue40 = Color(0xff3e41f4)
private val Yellow40 = Color(0xff7d5700)
// Remaining colors from tonal palettes

private val LightColorScheme = lightColorScheme(
    primary = Blue40,
    secondary = DarkBlue40,
    tertiary = Yellow40,
    // error, primaryContainer, onSecondary, etc.
)
private val DarkColorScheme = darkColorScheme(
    primary = Blue80,
    secondary = DarkBlue80,
    tertiary = Yellow80,
    // error, primaryContainer, onSecondary, etc.
)

ColorScheme을 정의한 후에는 M3 MaterialTheme에 전달할 수 있습니다.

val darkTheme = isSystemInDarkTheme()
MaterialTheme(
    colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
) {
    // M3 app content
}

색 구성표 생성

맞춤 ColorScheme을 수동으로 만들 수도 있지만 브랜드의 소스 색상을 사용하여 생성하는 것이 더 쉬울 때가 많습니다. 머티리얼 테마 빌더 도구를 사용하면 이 작업을 실행할 수 있고 선택적으로 Compose 테마 설정 코드를 내보낼 수 있습니다.

그림 17. 머티리얼 테마 빌더 도구로 생성한 맞춤 색상 값이 있는 머티리얼 3 색조 팔레트와 색 구성표

동적 색 구성표

동적 색상은 Material You의 핵심 부분으로, 알고리즘이 사용자의 배경화면에서 맞춤 색상을 가져와 앱과 시스템 UI에 적용합니다. 이 색상 팔레트는 완전한 밝은 색 구성표나 어두운 색 구성표를 생성하는 시작점으로 사용됩니다.

동적 색상은 Android 12 이상에서 사용할 수 있습니다. 동적 색상을 사용할 수 있다면 동적 ColorScheme을 설정할 수 있습니다. 사용할 수 없으면 밝은 또는 어두운 맞춤 ColorScheme 사용으로 대체할 수 있습니다.

ColorScheme은 동적 밝은 색 구성표나 어두운 색 구성표를 만드는 빌더 함수를 제공합니다.

// Dynamic color is available on Android 12+
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colorScheme = when {
    dynamicColor && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
    dynamicColor && !darkTheme -> dynamicLightColorScheme(LocalContext.current)
    darkTheme -> DarkColorScheme
    else -> LightColorScheme
}

그림 18. 처음 두 스크린샷은 빨간색 배경화면에 기반한 동적 ColorScheme을 사용하는 앱을 보여줍니다. 두 번째 스크린샷은 파란색 배경화면에 기반한 동적 ColorScheme을 사용하는 앱을 보여줍니다.

색 구성표 색상 사용

MaterialTheme.colorScheme을 사용하여 M3 MaterialTheme 컴포저블에 제공된 ColorScheme을 검색할 수 있습니다.

Text(
    text = "Hello M3 theming",
    color = MaterialTheme.colorScheme.tertiary
)

서체

머티리얼 디자인 3는 머티리얼 디자인 2에서 조정된 텍스트 스타일을 비롯하여 유형 스케일을 정의합니다. 이름 지정과 그룹화는 표시, 헤드라인, 제목, 본문, 라벨로 간소화되었고 각각 대, 중, 소 크기가 있습니다.

그림 19. 머티리얼 3 유형 스케일과 머티리얼 2 유형 스케일 비교

Compose는 기존 TextStyle글꼴 관련 클래스와 함께 새로운 M3 Typography 클래스를 제공하여 머티리얼 3 유형 스케일을 모델링합니다.

val KarlaFontFamily = FontFamily(
    Font(R.font.karla_regular),
    Font(R.font.karla_bold, FontWeight.Bold)
)

val AppTypography = Typography(
    bodyLarge = TextStyle(
        fontFamily = KarlaFontFamily,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.15.sp
    ),
    // titleMedium, labelSmall, etc.
)

Typography를 정의한 후에는 M3 MaterialTheme에 전달할 수 있습니다.

MaterialTheme(
    typography = AppTypography
) {
    // M3 app content
}

텍스트 스타일 사용

MaterialTheme.typography를 사용하여 M3 MaterialTheme 컴포저블에 제공된 Typography를 검색할 수 있습니다.

Text(
    text = "Hello M3 theming",
    style = MaterialTheme.typography.bodyLarge
)

고도

머티리얼 3는 주로 색조 색상 오버레이를 사용하여 고도를 나타냅니다. 이는 컨테이너와 표면을 서로 구별하는 새로운 방법입니다. 색조 고도를 높이면 그림자 외에도 더 눈에 띄는 색조가 사용됩니다.

어두운 테마의 고도 오버레이도 머티리얼 3에서 색조 색상 오버레이로 변경되었습니다.

오버레이 색상은 기본 색상 슬롯에서 가져옵니다.

그림 20. 밝은 테마와 어두운 테마에서 머티리얼 3 고도와 머티리얼 2 고도 비교

대부분의 M3 구성요소를 뒷받침하는 지원 컴포저블인 M3 Surface에는 색조 고도 지원과 그림자 고도 지원이 모두 포함됩니다.

Surface(
    tonalElevation = 16.dp,
    shadowElevation = 16.dp
) {
    // Surface content
}

시스템 UI

Material You의 일부 측면은 새로운 Android 12 시각적 스타일과 시스템 UI에서 비롯됩니다. 변경사항이 있는 두 가지 주요 영역은 물결 효과와 오버스크롤입니다. 이러한 변경사항을 구현하려고 추가 작업을 하지 않아도 됩니다.

물결 효과

이제 물결 효과를 누르면 은은한 반짝임이 적용되어 표면이 밝아집니다. Compose 머티리얼 물결 효과내부적으로 Android의 RippleDrawable 플랫폼을 사용하므로 반짝임 물결 효과는 Android 12 이상에서 모든 머티리얼 구성요소에 사용할 수 있습니다.

그림 21. Android 12 물결 효과와 Android 12 전 물결 효과 비교

오버스크롤

이제 오버스크롤이 스크롤 컨테이너 가장자리에서 스트레치 효과를 사용합니다. 스트레치 오버스크롤은 API 수준과 상관없이 Compose Foundation 1.1.0 이상의 스크롤 컨테이너 컴포저블(예: LazyColumn, LazyRow, LazyVerticalGrid)에서 기본적으로 사용 설정되어 있습니다.

그림 22. 스트레치 오버스크롤

자세히 알아보기

Compose의 머티리얼 테마 설정에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.

Codelabs

동영상