와챠의 우당탕탕 코딩 일기장

[Compose] 2-1. Material Design 3으로 앱 테마 지정 / Material Theme Builder / Color, Type, Theme, Shape 설정 본문

코딩 일기장/Android(Kotlin)

[Compose] 2-1. Material Design 3으로 앱 테마 지정 / Material Theme Builder / Color, Type, Theme, Shape 설정

minWachya 2025. 4. 16. 21:30
반응형

이제 강의 2: 레이아웃, 테마 설정, 애니메이션을 공부해보자.

 

 

<목차>

  1. Material Theme Builder를 통해 AppTheme 생성
  2. Surface로 색조와 그림자 설정
  3. 색 변경을 통한 강조
  4. 서체 스타일 설정
  5. 도형(모서리) 설정

1. Material Theme Builder를 통해 AppTheme 생성

Material Theme Builder 사이트를 이용해 색 구성표를 쉽게 생성할 수 있다.

아래 사이트에서 Primary 컬러를 지정하거나, 원하는 분위기의 이미지를 넣으면 자동으로 주요 색상을 뽑아준다.

  • Primary: 기본 색상. 눈에 띄는 구성요소에 사용됨
  • Secondary: 눈에 덜 띄는 구성요소에 사용됨
  • Tertiary: 대비 강조를 위해 사용됨
  • Background, Surfece: 앱의 배경과 표면에 사용됨

이렇게 컬러를 적용한 컴포넌트들을 보여주기까지 한다!

 

라이트 모드 / 다크 모드 컬러들까지 뽑아준다~~

이런 모드들이 적용된 앱 화면까지 확인 할 수 있어서 앱을 어떻게 조화롭게 꾸밀지 고민할 필요가 없어졌다!!!

 

폰트까지 설정 가능하고, export하면 Color.kt, Theme.kt, Type.kt 파일을 모두 받을 수 있다.

이걸 Theme.kt의 MaterialTheme에서 다음과 같이 설정해준다.

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable() () -> Unit
) {
    // ...

  MaterialTheme(
    colorScheme = colorScheme,
    typography = typography,
    content = content
  )
}

 

그런 다음 MainActivity에서 setContent부분에 AppTheme을 씌워주면 적용된 모습을 볼 수 있다.

난 강의 예제에서 나온 색이 아닌... 위에 나온 색으로 진행했다. 내 눈엔 저게 더 예쁨ㅋ

setContent {
   val uiState by viewModel.uiState.collectAsStateWithLifecycle()

   AppTheme {
       ReplyApp(/*..*/)
   }
}

// ---

@Preview(
    uiMode = UI_MODE_NIGHT_YES,
    name = "DefaultPreviewDark",
)
@Preview(
    uiMode = UI_MODE_NIGHT_NO,
    name = "DefaultPreviewLight",
    showBackground = true
)
@Composable
fun ReplyAppPreviewLight() {
    AppTheme {
        ReplyApp(
            replyHomeUIState = ReplyHomeUIState(
                emails = LocalEmailsDataProvider.allEmails
            )
        )
    }
}

 

앱을 실행해보면 이렇게 컬러가 적용된 모습을 확인할 수 있다!


2. Surface로 색조와 그림자 설정

Surface는 Material Design 3의 색조와 그림자 고도를 지원한다.

Surface로 한 번 더 감싸주면 아래 이미지와 같이 UI가 좀 더 대비를 이루게 된다!

 

Surface의 tonalElevation은 설정한 값이 높을 수록 대비를 많이 느낄 수 있다. (밝은 테마에서는 어두운 색, 어두운 테마에서는 밝은 색이 나타남) 5.dp로 적당히 준 듯...

AppTheme {
   Surface(tonalElevation = 5.dp) {
       ReplyApp(
          // ...
         )
   }
}

< Surfece 적용 전 / Surface 적용 후 >


3. 색 변경을 통한 강조

색을 변경하여 각 기능을 강조시킬 수 있다.

검색 바를 좀 더 눈에 띄게 만들고, 플로팅 버튼과 중요 메일의 경우 배경 색을 다르게 지정하여 보기 편하게 만들 수 있다!

MaterialTheme의 colorScheme을 이용해 아래와 같이 컬러를 변경해준다.

1번에 쓰인 강조 색, 덜 강조되는 색, 배경 색 등등을 참고하여 색을 고르면 된다.

Card(
   modifier =  modifier
       .padding(horizontal = 16.dp, vertical = 4.dp)
       .semantics { selected = isSelected }
       .clickable { navigateToDetail(email.id) },
   colors = CardDefaults.cardColors(
   		// 이 부분!
       containerColor = if (email.isImportant)
           MaterialTheme.colorScheme.secondaryContainer
       else MaterialTheme.colorScheme.surfaceVariant
   )
){
  /*..*/   
}

< 색 강조 전 / 색 강조 후 >

 

참고로 앱 바 색 변경의 경우, 강의에선 아래 코드를 통해 변경했는데

@Composable
fun AppTheme(
   useDarkTheme: Boolean =  isSystemInDarkTheme(),
   content: @Composable () -> Unit
) {
 
 // color scheme selection code

 // Add primary status bar color from chosen color scheme.
 val view = LocalView.current
 if (!view.isInEditMode) {
    SideEffect {
        val window = (view.context as Activity).window
        window.statusBarColor = colors.primary.toArgb()
        WindowCompat
            .getInsetsController(window, view)
            .isAppearanceLightStatusBars = useDarkTheme
    }
 }
   
  MaterialTheme(
    // ...
   )
}

 window statusbarcolor가 deprecated되어서 구글링을 해보니 다음과 같은 해결법이 있었다.

https://stackoverflow.com/questions/78832208/how-to-change-the-status-bar-color-in-android-15

 

How to change the status bar color in Android 15+?

For Android 14 or below, it can be done with: window.statusBarColor = Color.RED, after upgrading to Android 15, this is deprecated and doesn't work. In Android Studio, it recommends to use: Draw p...

stackoverflow.com

 

나도 이렇게 변경~

fun setStatusBarColor(window: Window, color: Int) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { // Android 15+
        window.decorView.setOnApplyWindowInsetsListener { view, insets ->
            val statusBarInsets = insets.getInsets(WindowInsets.Type.statusBars())
            view.setBackgroundColor(color)

            view.setPadding(0, statusBarInsets.top, 0, 0)
            insets
        }
    } else {
        // For Android 14 and below
        window.statusBarColor = color
    }
}

// -------

@Composable
fun AppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable() () -> Unit
) {
    // ...

	// 이 부분~
    val view = LocalView.current
    val window = (view.context as Activity).window

    setStatusBarColor(window, colorScheme.primary.toArgb())


  MaterialTheme(
    // ...
  )
}

 


4. 서체 스타일 설정

Material Design 3는 서체 스케일을 Headline, Title, Body, Lable로 정의하고 있고, 각각 L, M, S 크기가 있다.

1번에서 다운받았던 Type.kt를 보면 아래와 같이 정의가 되어있을 것이다.

val typography = Typography(
   headlineSmall = TextStyle(
       fontWeight = FontWeight.SemiBold,
       fontSize = 24.sp,
       lineHeight = 32.sp,
       letterSpacing = 0.sp
   ),
   titleLarge = TextStyle(
       fontWeight = FontWeight.Normal,
       fontSize = 18.sp,
       lineHeight = 28.sp,
       letterSpacing = 0.sp
   ),
   bodyLarge = TextStyle(
       fontWeight = FontWeight.Normal,
       fontSize = 16.sp,
       lineHeight = 24.sp,
       letterSpacing = 0.15.sp
   ),
   bodyMedium = TextStyle(
       fontWeight = FontWeight.Medium,
       fontSize = 14.sp,
       lineHeight = 20.sp,
       letterSpacing = 0.25.sp
   ),
   labelMedium = TextStyle(
       fontWeight = FontWeight.SemiBold,
       fontSize = 12.sp,
       lineHeight = 16.sp,
       letterSpacing = 0.5.sp
   )
)

 

이런 스타일들을 아래와 같이 사용하여 서체 스타일을 변경할 수 있다!

Text(
   text = "Hello",
   style = MaterialTheme.typography.titleLarge
)

 

< 서체 스타일 변경 전 / 후 >

 


5. 도형(모서리) 설정

애플이 모든 모서리를 똑같이 맞춰놓은 사진 본 적 잇으신지...

모서리를 맞출 때 통일감을 얻을 수 있는 것처럼, 앱을 설정할 때도 도형 크기들을 원하는 사이즈로 설정할 수 있다.

ui/theme에 Shape.kt를 만들고 다음과 같이 코드를 짜면 된다.

 

도형 크기에 따라 원하는 사이즈를 정하고 이를 사용하면 통일감을 주는 도형들을 만들 수 있다.

import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Shapes
import androidx.compose.ui.unit.dp

val shapes = Shapes(
   extraSmall = RoundedCornerShape(4.dp),
   small = RoundedCornerShape(8.dp),
   medium = RoundedCornerShape(16.dp),
   large = RoundedCornerShape(24.dp),
   extraLarge = RoundedCornerShape(32.dp)
)

 

이걸 AppTheme에 새로 적용한다.

@Composable
fun AppTheme(
   useDarkTheme: Boolean = isSystemInDarkTheme(),
   content: @Composable() () -> Unit
) {
  // dynamic theming content

   MaterialTheme(
       colorScheme = colors,
       typography = typography,
       shapes = shapes,
       content = content
   )
}

 

이렇게 설정하면 다음과 같은 코드로 도형을 만들 수 있다.

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

< 도형(모서리) 설정 전 / 후 >

완성~~!!


Material Theme Builder 사이트를 사용해서 앱 테마 색 설정하는 거는 안드 뉴스에서 알게 되었는데, 이 강의 통해서 더 자세히 배울 수 있어서 좋았다~

참고로 안드 뉴스에서 읽은 포스트는 이거다

https://proandroiddev.com/material3-color-system-basics-for-android-developers-2b0c73a58b2d

 

Material3 Color System Basics for Android Developers

Material3 is the newest iteration of Material Design, with dynamic theming, revised components and more… however, it can also be…

proandroiddev.com

 

글고 이런 테마 공부는 플젝할 때도 변형해서 사용 가능하니까 잘 배운듯여 ㅎㅎ

반응형
Comments