๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ฑ| Android/๐Ÿš€ | Jetpack

[Android, Kotlin] compose custom theme ๋งŒ๋“ค๊ธฐ

by immgga 2023. 8. 18.

 

์ด๋ฒˆ ํฌ์ŠคํŒ…์€ ์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ ๋งํ–ˆ๋‹ค์‹œํ”ผ ์ปค์Šคํ…€ ํ…Œ๋งˆ์— ๋Œ€ํ•œ ๊ฐ„๋‹จ ์„ค๋ช…๊ณผ ์ฝ”๋“œ๋ฅผ ์•Œ๋ ค์ฃผ๋„๋ก ํ•˜๊ฒ ๋‹ค.

์ปค์Šคํ…€ ํ…Œ๋งˆ๋ฅผ ์™œ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•œ ์‚ฌ๋žŒ๋“ค์ด ์žˆ์„ ๊ฒƒ ๊ฐ™์•„ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด

๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‹ค ๋ณด๋ฉด color๊ฐ€ ๋‹ค์–‘ํ•ด์งˆ ์ˆ˜ ์žˆ๊ธฐ์— ๊ธฐ๋ณธ์ ์œผ๋กœ android studio์—์„œ ์ œ๊ณตํ•˜๋Š” color palette๊ฐ€ ๋ถ€์กฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋””์ž์ด๋„ˆ๊ฐ€ ์ •ํ•œ color๋ช…์„ ๊ทธ๋Œ€๋กœ ์ ์šฉํ•˜๊ธฐ ํž˜๋“ค๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๋Ÿด ๋•Œ์—๋Š” custom theme๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•„์ž๋Š” ์ด๋ฒˆ ๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ์— ๋Œ€๋น„ํ•ด ์ปค์Šคํ…€ ํ…Œ๋งˆ๋ฅผ ์ œ์ž‘ํ•ด ๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

์ž ๊ทธ๋Ÿผ ์ด์ œ ์ฝ”๋“œ๋กœ ํ•„์ž๊ฐ€ custom theme๋ฅผ ๋งŒ๋“ค์—ˆ๋˜ ๊ณผ์ •์„ ํ™•์ธํ•ด ๋ณด์ž.

 

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—!

์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” theme ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” enum class๋ฅผ ์ƒ์„ฑํ•ด ์ค€๋‹ค.

enum class Theme {
    LIGHT,
    DARK
}

 

1. color ์ •์˜ํ•˜๊ธฐ

์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ design system์„ ์ด์šฉํ•ด color๋ฅผ ์ •์˜ํ•ด ๋ณด์ž.

val Black = Color(0xFF000000)
val White = Color(0xFFFFFFFF)
val Transparent = Color(0x00000000)

val Primary10Light = Color(0xFF6F7AEC)
val Primary20Light = Color(0xFFEEF0FD)
val Primary30Light = Color(0xFFC5CAF7)
val Neutral10Light = Color(0xFF292E3D)
val Neutral20Light = Color(0xFF656B80)
val Neutral30Light = Color(0xFFBBBBCC)
val Neutral40Light = Color(0xFFE2E2EE)
val Neutral50Light = Color(0xFFF2F2F4)
val BackGroundLight = Color(0xFFF7F7F9)
val CardBackGroundLight = Color(0xFFFDFDFD)
val ErrorLight = Color(0xFFD84D4D)
val PositiveLight = Color(0xFF2E8546)
val SubGreenLight = Color(0xFF9BDA93)
val SubYellowLight = Color(0xFFEEE170)
val SubRedLight = Color(0xFFF3A199)

val Primary10Dark = Color(0xFF5966E9)
val Primary20Dark = Color(0xFF1D2136)
val Primary30Dark = Color(0xFF24295D)
val Neutral10Dark = Color(0xFFCDCDD5)
val Neutral20Dark = Color(0xFF818198)
val Neutral30Dark = Color(0xFF626274)
val Neutral40Dark = Color(0xFF292930)
val Neutral50Dark = Color(0xFF1E1E26)
val BackGroundDark = Color(0xFF1F1E2B)
val CardBackGroundDark = Color(0xFF17161F)
val ErrorDark = Color(0xFFFF7D7D)
val PositiveDark = Color(0xFF5EFF8B)
val SubGreenDark = Color(0xFF79CE6F)
val SubYellowDark = Color(0xFFE9D844)
val SubRedDark = Color(0xFFEE786D)

ํ•„์ž์˜ ๊ฒฝ์šฐ์—๋Š” dark, light ๊ตฌ๋ถ„ํ•ด์„œ color๋ฅผ ์ •์˜ํ–ˆ๋‹ค. dark theme๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ณ , color์˜ ๊ตฌ์„ฑ๋„ ์—ฌ๋Ÿฌ๋ถ„๋“ค์˜ design system์„ ์ด์šฉํ•ด ์ž์œ ๋กญ๊ฒŒ custom ํ•ด๋ณด์‹œ๊ธธ..(ํ•„์ž์˜ ์ฝ”๋“œ๋Š” ์˜ˆ์‹œ์ด๋‹ค.)

 

๊ทธ๋ฆฌ๊ณ  color ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•˜๋Š” color palette class์™€ color ๋ณต์‚ฌ update์šฉ ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

์ดํ›„์— ๋งŒ๋“ค typography์™€ ๋‹ค๋ฅธ ์ ์€ copy์™€ update๊ฐ€ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด ๋‘ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ์ด์œ ๋Š” ํ•„์ž์˜ theme๋Š” dark/light๋กœ ๊ณ„์†ํ•ด์„œ ๋ฐ”๋€Œ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•˜๊ธฐ ์œ„ํ•ด copy์™€ update ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ๋‹ค.

class Colors(
    primary10: Color,
    primary20: Color,
    primary30: Color,
    neutral10: Color,
    neutral20: Color,
    neutral30: Color,
    neutral40: Color,
    neutral50: Color,
    background: Color,
    cardBackground: Color,
    error: Color,
    positive: Color,
    subGreen: Color,
    subYellow: Color,
    subRed: Color
) {
    var primary10 by mutableStateOf(primary10)
        private set
    var primary20 by mutableStateOf(primary20)
        private set
    var primary30 by mutableStateOf(primary30)
        private set

    var neutral10 by mutableStateOf(neutral10)
        private set
    var neutral20 by mutableStateOf(neutral20)
        private set
    var neutral30 by mutableStateOf(neutral30)
        private set
    var neutral40 by mutableStateOf(neutral40)
        private set
    var neutral50 by mutableStateOf(neutral50)
        private set

    var background by mutableStateOf(background)
        private set
    var cardBackground by mutableStateOf(cardBackground)
        private set

    var error by mutableStateOf(error)
        private set
    var positive by mutableStateOf(positive)
        private set

    var subGreen by mutableStateOf(subGreen)
        private set
    var subYellow by mutableStateOf(subYellow)
        private set

    var subRed by mutableStateOf(subRed)
        private set

    fun update(colors: Colors) {
        this.primary10 = colors.primary10
        this.primary20 = colors.primary20
        this.primary30 = colors.primary30
        this.neutral10 = colors.neutral10
        this.neutral20 = colors.neutral20
        this.neutral30 = colors.neutral30
        this.neutral40 = colors.neutral40
        this.neutral50 = colors.neutral50
        this.background = colors.background
        this.cardBackground = colors.cardBackground
        this.subGreen = colors.subGreen
        this.subYellow = colors.subYellow
        this.subRed = colors.subRed
        this.error = colors.error
        this.positive = colors.positive
    }

    fun copy() = Colors(
        primary10 = primary10,
        primary20 = primary20,
        primary30 = primary30,
        neutral10 = neutral10,
        neutral20 = neutral20,
        neutral30 = neutral30,
        neutral40 = neutral40,
        neutral50 = neutral50,
        background = background,
        cardBackground = cardBackground,
        error = error,
        positive = positive,
        subGreen = subGreen,
        subYellow = subYellow,
        subRed = subRed
    )
}

 

 

2. typography ๋งŒ๋“ค๊ธฐ

๊ทธ๋‹ค์Œ์—๋Š” font๋ฅผ ์ ์šฉํ•œ typography๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ๊ฒ ๋‹ค.

val suitFont = FontFamily(
    Font(R.font.suit_bold, FontWeight.Bold),
    Font(R.font.suit_medium, FontWeight.Medium),
    Font(R.font.suit_semi_bold, FontWeight.SemiBold)
)

object Typography {

    @Stable
    val h1 = TextStyle(
        fontFamily = suitFont,
        fontSize = 48.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val h2 = TextStyle(
        fontFamily = suitFont,
        fontSize = 32.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val h3 = TextStyle(
        fontFamily = suitFont,
        fontSize = 24.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val h4 = TextStyle(
        fontFamily = suitFont,
        fontSize = 20.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val subTitle1 = TextStyle(
        fontFamily = suitFont,
        fontSize = 18.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val subTitle2 = TextStyle(
        fontFamily = suitFont,
        fontSize = 16.sp,
        fontWeight = FontWeight.Bold
    )

    @Stable
    val subTitle3 = TextStyle(
        fontFamily = suitFont,
        fontSize = 18.sp,
        fontWeight = FontWeight.Medium
    )

    @Stable
    val smallTitle = TextStyle(
        fontFamily = suitFont,
        fontSize = 14.sp,
        fontWeight = FontWeight.SemiBold
    )

    @Stable
    val body = TextStyle(
        fontFamily = suitFont,
        fontSize = 16.sp,
        fontWeight = FontWeight.Medium,
        lineHeight = 1.5f.sp
    )

    @Stable
    val body2 = TextStyle(
        fontFamily = suitFont,
        fontSize = 14.sp,
        fontWeight = FontWeight.Medium
    )

    @Stable
    val caption = TextStyle(
        fontFamily = suitFont,
        fontSize = 12.sp,
        fontWeight = FontWeight.Medium
    )
}

internal val LocalTypography = staticCompositionLocalOf { Typography }

fontfamily์™€ font object๋ฅผ ์ƒ์„ฑํ•˜๊ณ  localTypography๋Š” staticCompositionLocalOf์„ ์ด์šฉํ•ด ํŠน์ • composable๊นŒ์ง€ ์ ‘๊ทผ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.(์‚ฌ์‹ค staticCompositionLocalOf์€ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ด์„œ ์ œ๋Œ€๋กœ ์„ค๋ช…์„ ๋“œ๋ฆด ์ˆ˜๊ฐ€ ์—†์„ ๊ฒƒ ๊ฐ™์•„์„œ ํ•„์ž๊ฐ€ ์ฐธ๊ณ ํ•œ ๋ธ”๋กœ๊ทธ ์ฃผ์†Œ๋ฅผ ๋ณด๋‚ด์ฃผ๋„๋ก ํ•˜๊ฒ ๋‹ค.)

https://www.charlezz.com/?p=46403 

 

Compose์˜ CompositionLocal ์ดํ•ดํ•˜๊ธฐ | ์ฐฐ์Šค์˜ ์•ˆ๋“œ๋กœ์ด๋“œ

์ปดํฌ์ €๋ธ” ํ•จ์ˆ˜๋Š” ํŠธ๋ฆฌ(tree)๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. ์ด ๋•Œ ์ƒํƒœ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํŠธ๋ฆฌ์—์„œ ๊ฐ€๋Šฅํ•œ ํ•œ ๊ฐ€์žฅ ๋†’์€ ๋…ธ๋“œ์— ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค(์ƒํƒœ ํ˜ธ์ด์ŠคํŒ…). ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ ‡๊ฒŒ ์„ ์–ธ๋œ ์ƒํƒœ๋Š” ํ•˜์œ„ ํŠธ๋ฆฌ๋กœ

www.charlezz.com

 

3. theme ๋งŒ๋“ค๊ธฐ

color์™€ typography๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ์ด์ œ๋Š” ํ…Œ๋งˆ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

๋จผ์ € ์ด์ „์— ๋งŒ๋“ค์–ด๋‘” color Palette๋ฅผ ์ด์šฉํ•ด color๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

private val darkColors = Colors(
    primary10 = Primary10Dark,
    primary20 = Primary20Dark,
    primary30 = Primary30Dark,
    neutral10 = Neutral10Dark,
    neutral20 = Neutral20Dark,
    neutral30 = Neutral30Dark,
    neutral40 = Neutral40Dark,
    neutral50 = Neutral50Dark,
    background = BackGroundDark,
    cardBackground = CardBackGroundDark,
    subGreen = SubGreenDark,
    subYellow = SubYellowDark,
    subRed = SubRedDark,
    error = ErrorDark,
    positive = PositiveDark
)

private val lightColors = Colors(
    primary10 = Primary10Light,
    primary20 = Primary20Light,
    primary30 = Primary30Light,
    neutral10 = Neutral10Light,
    neutral20 = Neutral20Light,
    neutral30 = Neutral30Light,
    neutral40 = Neutral40Light,
    neutral50 = Neutral50Light,
    background = BackGroundLight,
    cardBackground = CardBackGroundLight,
    subGreen = SubGreenLight,
    subYellow = SubYellowLight,
    subRed = SubRedLight,
    error = ErrorLight,
    positive = PositiveLight
)

๋˜ํ•œ typography ๋•Œ์™€ ๊ฐ™์ด color ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” staticCompositionLocalOf ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

private val LocalColorProvider = staticCompositionLocalOf { DotoriLightColors }

 

๋‹ค์Œ์œผ๋กœ ํ…Œ๋งˆ๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.

@Composable
private fun ThemeLocalProvider(
    colors: DotoriColors,
    typography: DotoriTypography,
    content: @Composable () -> Unit
) {
    val colorPalette = remember { colors.copy() }

    colorPalette.update(dotoriColors = colors)
    CompositionLocalProvider(
        LocalColorProvider provides colorPalette,
        LocalTypography provides typography,
        content = content
    )
}

private val Theme.colors: Colors
    get() = when(this) {
        Theme.DARK -> DarkColors
        Theme.LIGHT -> LightColors
    }

color๋Š” light/dark๋กœ ๋ฐ”๋€Œ๊ธฐ ๋•Œ๋ฌธ์— color์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  colors๊ฐ€ ๋ฐ”๋€Œ๋ฉด remember์—์„œ๋„ ๋ณ€๊ฒฝ๋˜๊ฒŒ ๋งŒ๋“ค์—ˆ๊ณ , compositionLocalProvider๋กœ color์™€ typography๋ฅผ ์ œ๊ณตํ–ˆ๋‹ค.

colors ๋ณ€์ˆ˜๋Š” theme ์ƒํƒœ์— ๋”ฐ๋ผ ์œ„์—์„œ ์ œ์ž‘ํ•œ color palette๋ฅผ ์ ์šฉํ•ด ์ฃผ๋Š” ๋ถ€๋ถ„์ด๋‹ค.

 

๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์‚ฌ์šฉํ•  theme๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ๋Š” ๊ณผ์ •์ด๋‹ค.

object Theme {
    val colors: Colors
        @Composable
        get() = LocalColorProvider.current

    val typography: Typography
        @Composable
        get() = LocalTypography.current

    var theme by mutableStateOf(Theme.LIGHT)

    fun isSystemIsDarkTheme(): Boolean {
        return dotoriTheme == Theme.DARK
    }
}

@Composable
fun Theme(
    theme: Theme = Theme.theme,
    typography: Typography = Theme.typography,
    content: @Composable () -> Unit
) {
    ThemeLocalProvider(
        colors = theme.colors,
        typography = typography,
        content = content
    )
}

object์˜ theme๋Š” ์‚ฌ์šฉ์ž๊ฐ€ color์™€ typography๋ฅผ ์ ์šฉํ•  ๋•Œ ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋‹ค.

color์™€ typography์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ๋˜ํ•œ ํ˜„์žฌ ํ…Œ๋งˆ๊ฐ€ dark theme์ธ์ง€๋„ ๊ฒ€์‚ฌํ•˜๋Š” ํ•จ์ˆ˜๋„ ์ƒ์„ฑํ–ˆ๋‹ค.(์ด ํ•จ์ˆ˜๋Š” ์—†์–ด๋„ ๋œ๋‹ค. ํ•„์š”ํ•œ ๋ถ„๋“ค๋งŒ ๋งŒ๋“œ์‹œ๊ธธ)

composable function theme๋Š” android studio project๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” AppNameTheme {}์™€ ๊ฐ™์€ ์—ญํ• ์ด๋‹ค.

theme์™€ typography param์„ ์ •์˜ํ•ด ๋†“์•˜๊ธฐ์— ์‚ฌ์šฉํ•  ๋•Œ ๊ตณ์ด param์„ ์ •์˜ํ•˜๋ผ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.

 

4. ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ

์ด์ œ ํ…Œ๋งˆ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ์‚ฌ์šฉํ•ด ๋ณด์ž.

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            Theme {
            	// ui component
            }
        }
    }
}

์ด์ „์— ์ƒ์„ฑํ•œ Theme composable function์„ ์ด์šฉํ•ด ํ…Œ๋งˆ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

color์™€ typography๋ฅผ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Column(
    modifier = Modifier
        .fillMaxSize()
        .background(Theme.colors.background)	// color ์‚ฌ์šฉ
) {
	Text(
        modifier = Modifier.fillMaxWidth(),
        text = "theme typography",
        style = Theme.typography.body,			// typographuy ์‚ฌ์šฉ
        textAlign = TextAlign.Center,
        color = DotoriTheme.colors.neutral10
    )
}

์ด์ „์— ๋งŒ๋“  theme object class๋ฅผ ์ด์šฉํ•ด ์ •์˜ํ•œ color์™€ typography๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ •๋ฆฌ

  • ํ…Œ๋งˆ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์ฒ˜์Œ์ด๋ผ ์–ด๋ ค์› ๋˜ ์ ์ด ๋งŽ์•˜๋Š”๋ฐ, ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ์™€ youtube ์˜์ƒ์„ ์ฐธ๊ณ ํ–ˆ์—ˆ๋Š”๋ฐ ๊ธฐ์–ต์ด ๋‚˜์ง€ ์•Š๋Š”๋‹ค. ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค :(
  • custom theme๋ฅผ ์ œ์ž‘ํ•˜๋ฉด์„œ ๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ์—์„œ ์“ธ๋ชจ๊ฐ€ ๋งŽ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ณ , ์ƒ‰์˜ ๋ณ€ํ™˜(dark/light)๊ณผ typography๊ฐ€ ๋ณ€๊ฒฝ๋œ ๋ชจ์Šต์„ ์ฒ˜์Œ ๋ดค์„ ๋•Œ์—๋Š” ์—„์ฒญ ๊ธฐ๋ปํ–ˆ์—ˆ๋‹ค.(์ด๋ž˜์„œ ๋‚ด๊ฐ€ ์ฝ”๋”ฉ์„ ๋Š์„ ์ˆ˜๊ฐ€ ์—†๋‹ค ใ…Žใ…Ž)
  • ์•„์ง๋„ ์ดํ•ด๊ฐ€ ์™„์ „ํžˆ ๋˜์ง€ ์•Š์•„์„œ ์ฝ”๋“œ์˜ ๋ถ€๊ฐ€ ์„ค๋ช…์„ ํ•ด์ฃผ์‹œ๊ฑฐ๋‚˜ ๋” ํšจ์œจ์ด ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์•„์‹œ๋Š” ๋ถ„์€ ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ์ข‹์€ ๊ณต๋ถ€๊ฐ€ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค >:D

 

์ฐธ๊ณ ํ•œ ๋ธ”๋กœ๊ทธ

https://velog.io/@vov3616/Compose-Custom-Theme-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

[Compose] Custom Theme ๋งŒ๋“ค๊ธฐ

์ปดํฌ์ฆˆ๋กœ Material Theme๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด, ํ…Œ๋งˆ ๊ฐ€์ง“์ˆ˜์— ๊ณ ๊ฐœ๋ฅผ ๊ฐธ์šฐ๋šฑํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค.ํ•˜์–€ ๊ฐ•์•„์ง€(์•ฝ 12๊ฐ€์ง€ ์ปฌ๋Ÿฌ๋ฅผ ์ง€์›ํ•˜๋Š” )Jetpack Compose์—์„œ ๋งž์ถค ํ…Œ๋งˆ ๋นŒ๋“œJetpack Compose์—์„œ ๋งž์ถค ํ…Œ๋งˆ ๋งŒ๋“ค๊ธฐ

velog.io

728x90

๋Œ“๊ธ€