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

[Android, Kotlin] Compose์—์„œ glance๋ฅผ ์ด์šฉํ•ด ์œ„์ ฏ ๋งŒ๋“ค๊ธฐ

by immgga 2023. 10. 6.

 

์ด๋ฒˆ์— ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์€ compose๋กœ ์œ„์ ฏ์„ ๋งŒ๋“œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ glance์ด๋‹ค.

glance์˜ ์กด์žฌ(?)๋Š” ์ด์ „์— ๋“ค์œผ๋Ÿฌ ๊ฐ”๋˜ ์ปจํผ๋Ÿฐ์Šค ๊ฐ•์—ฐ์—์„œ glance์— ๊ด€๋ จ๋œ ๊ฐ•์—ฐ์„ ๋“ค๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ๊ทธ๋•Œ๋ถ€ํ„ฐ ๊ธฐํšŒ๊ฐ€ ๋˜๋ฉด ๊ณต๋ถ€ํ•ด ๋ณด์ž ๋ผ๋Š” ์ƒ๊ฐ์„ ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ๊ฒŒ ์ง€๊ธˆ์ด๋‹ค.

glance๋Š” compose์—์„œ ์œ„์ ฏ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ  2023๋…„ 8~9์›”์— 1.0.0์„ ์ถœ์‹œํ•œ ๋”ฐ๋ˆ๋”ฐ๋ˆํ•œ ์‹ ์ƒ(?) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์•„๋ฌดํŠผ ๊ทธ๋ž˜์„œ ์ด๋ฒˆ์— compose glance๋ฅผ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•œ๋‹ค.

๊ทธ๋Ÿผ ๋ฐ”๋กœ glance ์‚ฌ์šฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

 

1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ํ•˜๊ธฐ

๋จผ์ € glance ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.

// glance
implementation("androidx.glance:glance-appwidget:1.0.0")
implementation("androidx.glance:glance-material3:1.0.0")

 

2. ์œ„์ ฏ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑํ•˜๊ธฐ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ํ›„, ๋‹ค์Œ์œผ๋กœ๋Š” ์œ„์ ฏ์˜ UI๋ฅผ ๊ตฌ์„ฑํ•ด ๋ณด๊ฒ ๋‹ค.

object CounterWidget: GlanceAppWidget() {
    // widget body
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // use provideContent, you can use composable function
        provideContent {
            
        }
    }
}

์œ„์ ฏ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” GlanceAppWidget์„ ์ƒ์†๋ฐ›์•„์„œ provideGlance ํ•จ์ˆ˜ ์•ˆ์— widget ui๋ฅผ ๊ตฌ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๋ƒฅ provideGlance ํ•จ์ˆ˜ ์•ˆ์—์„œ๋Š” Text๋‚˜ Button ๊ฐ™์€ composable function์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ provideContent๋ฅผ ์‚ฌ์šฉํ•ด ๊ทธ ์•ˆ์— ui๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.

 

์ด๋ฒˆ์— ํ•„์ž๊ฐ€ ๋งŒ๋“ค ์˜ˆ์ œ๋Š” philipp lackner์˜ ์˜์ƒ์œผ๋กœ ๊ณต๋ถ€ํ–ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์˜์ƒ์— ๋‚˜์˜ค๋Š” ์œ„์ ฏ ์•ˆ์— ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ˆซ์ž๊ฐ€ +1 ๋˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.

https://www.youtube.com/watch?v=bhrN7yFG0D4&t=729s&pp=ygUWYW5kcm9pZCBjb21wb3NlIGdsYW5jZQ%3D%3D 

 

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด UI๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

Text(
    text = "0",
    style = TextStyle(
        fontWeight = FontWeight.Medium,
        color = ColorProvider(Color.White),
        fontSize = 26.sp
    )
)

Button(
    text = "์ถ”๊ฐ€",
    onClick = // add action
)

Text ๋ถ€๋ถ„์—๋Š” ํด๋ฆญํ•˜๋ฉด text๊ฐ€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋„๋ก ๋กœ์ง์„ ์งœ์•ผํ•˜๊ณ , Button์—์„œ๋Š” click ํ–ˆ์„ ๋•Œ click action์„ ์ƒ์„ฑํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ๋ˆˆ์น˜๊ฐ€ ๋น ๋ฅธ ๋ถ„๋“ค์€ ์ด์ƒํ•จ์„ ๋Š๊ผˆ์„ ๊ฒƒ์ด๋‹ค.

๋ฐ”๋กœ onClick๋ถ€๋ถ„์ด lambda(๋žŒ๋‹ค) ํ˜•์‹์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์ธ๋ฐ, ์œ„์— ํ•„์ž๊ฐ€ ์–ธ๊ธ‰ํ•œ ์˜์ƒ์„ ๋ณด๋ฉด ๊ธˆ๋ฐฉ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์œ„์˜ Text์™€ Button Composable function๋“ค์€ android์—์„œ ์ž์ฒด ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ glance์—์„œ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋“ค์ด๋‹ค.

๊ทธ๋ž˜์„œ ๊ธฐ๋ณธ composable function๋“ค๊ณผ ํ˜ผ๋™ํ•˜์ง€ ์•Š๋„๋ก ์ฃผ์˜ํ•˜์ž(ํ•จ์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ๋“ค๋„ ๋‹ค๋ฅด๊ธฐ์—)

ํ•˜์ง€๋งŒ ๊ทธ๋ƒฅ glance function ๋ง๊ณ  ๊ธฐ๋ณธ function์€ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.

๋นŒ๋“œ๋˜๋Š” ๋ฐ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์œ„์ ฏ์„ ํฐ์—์„œ ๋งŒ๋“ค๋ฉด UI ์š”์†Œ ๋Œ€์‹  ์œ„์ ฏ์„ ๋กœ๋“œํ•  ์ˆ˜ ์—†๋‹ค๋Š” ํ…์ŠคํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„๋“ค์„ ๋ฐ˜๊ฒจ์ค„ ๊ฒƒ์ด๋‹ค.

 

๊ทธ๋Ÿฌ๋ฉด ์ค‘๊ฐ„ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

object CounterWidget: GlanceAppWidget() {
    // widget body
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // use provideContent, you can use composable function
        provideContent {
            Text(
                text = "0",
                style = TextStyle(
                    fontWeight = FontWeight.Medium,
                    color = ColorProvider(Color.White),
                    fontSize = 26.sp
                )
            )

            Button(
                text = "์ถ”๊ฐ€",
                onClick = // add action
            )
        }
    }
}

์ด์ œ๋Š” Button์˜ click action์„ ๋งŒ๋“ค์–ด์ค„ ์ฐจ๋ก€์ด๋‹ค.

 

3. Click action ๋งŒ๋“ค๊ธฐ

๋จผ์ € ๋ฒ„ํŠผ ํด๋ฆญ ์•ก์…˜ ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ์ƒ์„ฑ ํ›„, glance์˜ ActionCallback์„ ์ƒ์†๋ฐ›์•„ ์ค€๋‹ค.

// widget update action callback
object IncrementActionCallback: ActionCallback {
    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters
    ) {
    
    }
}

onAction์•ˆ์— ํด๋ฆญ action์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

์˜์ƒ์—์„œ๋Š” Text์˜ ์ •๋ณด๋ฅผ preferenceKey๋กœ ์ €์žฅํ•˜์˜€๊ธฐ์— preferenceKey๋ฅผ ๋‹ด์€ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

val countKey = intPreferencesKey("count")

๊ทธ๋ฆฌ๊ณ  Text์— ์ ์šฉํ•  ํด๋ฆญ ์นด์šดํŠธ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

val count = currentState(key = countKey) ?: 0

countKey์˜ value๊ฐ€ null์ด๋ฉด ๊ธฐ๋ณธ๊ฐ’(0)์œผ๋กœ ์‹œ์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค์–ด ์ฃผ์—ˆ๋‹ค.

 

์ด์ œ๋Š” click action ํด๋ž˜์Šค์—์„œ ์ž‘์—…์„ ํ•ด์ค„ ์ฐจ๋ก€์ด๋‹ค.

glance์—์„œ๋Š” action์„ ์ˆ˜ํ–‰ ์‹œ ์œ„์ ฏ์„ update ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ๋ณ€๊ฒฝ๋œ UI๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

updateAppWidgetState(context, glanceId) { prefs ->
    val currentCount = prefs[CounterWidget.countKey]
    if (currentCount != null) prefs[CounterWidget.countKey] = currentCount + 1
    else prefs[CounterWidget.countKey] = 1
}
CounterWidget.update(context, glanceId)

updateAppWidgetState์˜ param์œผ๋กœ ์ด์ „์— ์ƒ์„ฑํ•œ onAction์˜ param์„ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ˜„์žฌ count๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” ์ด์ „ count์˜ +1์„,

null(0)์ธ ๊ฒฝ์šฐ์—๋Š” 1๋กœ ๋ฐ”๋€Œ๋„๋ก ์ž‘์—…์„ ํ•ด ์ฃผ์—ˆ๋‹ค.

 

updateAppWidgetState ์ž‘์—…์„ ํ•ด์ฃผ๊ณ  ๋‚˜์„œ ์œ„์ ฏ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•ด ์ฃผ๋Š” ์ž‘์—…์€ ํ•„์ˆ˜์ด๋‹ค.

 

Click action callback์˜ ์ „์ฒด ์ฝ”๋“œ

// widget update action callback
object IncrementActionCallback: ActionCallback {
    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters
    ) {
        updateAppWidgetState(context, glanceId) { prefs ->
            val currentCount = prefs[CounterWidget.countKey]
            if (currentCount != null) prefs[CounterWidget.countKey] = currentCount + 1
            else prefs[CounterWidget.countKey] = 1
        }
        CounterWidget.update(context, glanceId)
    }
}

์ด์ œ ๊ธฐ๋Šฅ์  ๋ถ€๋ถ„์€ ์™„๋ฃŒํ•˜์˜€์œผ๋‹ˆ ํ•ธ๋“œํฐ์—์„œ ๋ณด์ด๊ฒŒ ํ•˜๋Š” ์ž‘์—…์„ ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

 

4.  ์œ„์ ฏ ๋งˆ๋ฌด๋ฆฌ ์ž‘์—…

์ด๋ฒˆ์— ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ์ž‘์—…์€ ํœด๋Œ€์ „ํ™”์—์„œ ์œ„์ ฏ์ด ๋ณด์ด๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด,

์œ„์˜ ์‹œ๊ณ„ ์•ฑ์˜ ์œ„์ ฏ์ฒ˜๋Ÿผ, ํ•˜๋‹จ์˜ Title๊ณผ ๊ธฐ๋ณธ ํฌ๊ธฐ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

res -> xml ํŒจํ‚ค์ง€ ์•ˆ์— ํœด๋Œ€ํฐ์— ๋ณด์ด๋Š” ์œ„์ ฏ์˜ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ฃผ๊ฒ ๋‹ค.

ํŒŒ์ผ ์ด๋ฆ„ ์„ค์ • ํ›„, root element๋ฅผ appwidget-provider๋กœ ์„ค์ •ํ•˜๊ณ  ์ƒ์„ฑํ•œ๋‹ค.

 

counter_widget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:previewImage="@drawable/compose"
    android:description="@string/app_name"
    android:minResizeWidth="50dp"
    android:minResizeHeight="50dp"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen" />

description์ด ํฐ์—์„œ ๋ณด์ด๋Š” Title์ด๊ณ  minReziseWidth/Height๋กœ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํฌ๊ธฐ๋ฅผ ์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

resizeMode๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์œ„์ ฏ์„ ๊ธธ๊ฒŒ ๋ˆ„๋ฅด๋ฉด ์œ„์ ฏ์„ ๊ฐ€๋กœ ๋˜๋Š” ์„ธ๋กœ๋กœ ๋Š˜๋ฆด ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

๊ธฐ๋ณธ ์œ„์ ฏ
๊ฐ€๋กœ๋กœ ๋Š˜๋ฆฐ ์œ„์ ฏ
์„ธ๋กœ๋กœ ๋Š˜๋ฆฐ ์œ„์ ฏ

previewImage๋Š” ์œ„์ ฏ์„ ํ™”๋ฉด์— ๋„ฃ์„ ๋•Œ ๋œจ๋Š” ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.(์œ„์˜ ์‹œ๊ณ„ ์œ„์ ฏ์˜ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๊ฐ€ ์‹œ๊ณ„์ธ ๊ฒƒ์ฒ˜๋Ÿผ)

์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ manifest๋ฅผ ๊ฑด๋“œ๋ ค์•ผ ํ•  ์ฐจ๋ก€์ด๋‹ค.

 

manifest์—์„œ๋Š” ์œ„์ ฏ์„ receiver ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด ์œ„์ ฏ ๋ฆฌ์‹œ๋ฒ„๋ฅผ ๋‹ฌ์•„ ์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ ๊ทธ๊ฒƒ์ด GlanceAppWidgetReceiver์ด๋‹ค.

ํ•˜์ง€๋งŒ ์•„์ง ๋งŒ๋“ค์–ด์ฃผ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด ์ฃผ๋„๋ก ํ•˜๊ฒ ๋‹ค.

class SimpleCountWidgetReceiver : GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget
        get() = CounterWidget
}

ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด GlanceAppWidgetReceiver๋ฅผ ์ƒ์†๋ฐ›์€ ํ›„, glanceAppWidget ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์™€ get() ๋ถ€๋ถ„์— ์ž์‹ ์ด ์ƒ์„ฑํ•œ ์œ„์ ฏ ์ด๋ฆ„์„ ๋„ฃ์–ด ์ค€๋‹ค.

 

์œ„์ ฏ ๋ฆฌ์‹œ๋ฒ„ ์ƒ์„ฑ๊นŒ์ง€ ์™„๋ฃŒํ–ˆ์œผ๋ฉด ์ง„์งœ๋กœ manifest์— ๋ฆฌ์‹œ๋ฒ„๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ์ž‘์—…์„ ํ•ด์ฃผ๊ฒ ๋‹ค.

๋ฆฌ์‹œ๋ฒ„๋Š” application ์•ˆ์— ๋„ฃ์–ด์ฃผ์ž.

<receiver android:name=".SimpleCountWidgetReceiver" android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/counter_widget_info" />
</receiver>

 

receiver name์— ๋ฐ”๋กœ ์ „์— ๋งŒ๋“  GlanceAppWidgetReceiver ํด๋ž˜์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ , meta data์— resource์— ์ด์ „์— ์ƒ์„ฑํ•œ xml ํŒŒ์ผ์„ ๋„ฃ์–ด์ค€๋‹ค.

intent filter์˜ name๊ณผ meta data์˜ name์˜ ์ž๋™์™„์„ฑ์ด ์•ˆ ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฑด๋ฐ, ๋‹นํ™ฉํ•˜์ง€ ๋ง๊ณ  ์ •ํ™•ํžˆ ํƒ€์ดํ•‘์„ ํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ์ „ํ˜€ ๋ฌธ์ œ ๋  ๊ฒŒ ์—†์œผ๋‹ˆ ์•ˆ์‹ฌํ•ด๋„ ๋œ๋‹ค.

 

์œ„์˜ ์ž‘์—…๊นŒ์ง€ ์™„๋ฃŒํ–ˆ์œผ๋ฉด, ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด ๋ณด์ž.

 

5. ๊ฒฐ๊ณผ

์ง์ ‘ ๋งŒ๋“  ์œ„์ ฏ์ด ์ •์ƒ์ ์œผ๋กœ ์—…๋กœ๋“œ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์œ„์ ฏ์„ ๋„ฃ์–ด์ฃผ๊ณ  ๋‚˜๋ฉด, ์ฒ˜์Œ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์œ„์ ฏ์ด ์ƒ์„ฑ๋  ๊ฒƒ์ด๋‹ค.

์ถ”๊ฐ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด text๊ฐ€ ์ •์ƒ์ ์œผ๋กœ count ๋˜์–ด ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

์ •๋ฆฌ


  • compose๋กœ ์œ„์ ฏ์„ ๋งŒ๋“ค์–ด๋ณผ ๊ธฐํšŒ๊ฐ€ ์—†๊ธฐ๋„ ํ–ˆ๊ณ , ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋Š” ์ค„๋„ ๋ชฐ๋ž์—ˆ๋Š”๋ฐ ์ปจํผ๋Ÿฐ์Šค์—์„œ ์šฐ์—ฐํžˆ ๋“ฃ๊ฒŒ ๋œ ๋‚ด์šฉ์œผ๋กœ glance๋ฅผ ๊ณต๋ถ€ํ•˜์—ฌ ์ง์ ‘ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์•˜๋‹ค. ์ปจํผ๋Ÿฐ์Šค ๊ฐ•์‚ฌ๋‹˜๊ป˜ ๊ฐ์‚ฌ๋ฅผ ํ‘œํ•œ๋‹ค :)
  • glance๋Š” ์•„์ง ์ถœ์‹œ ์ดˆ๊ธฐ์ธ๋ฐ๋„ ์ƒ๋‹นํžˆ ์™„์„ฑ๋„๊ฐ€ ๋†’์•„ ๋ณด์˜€๋‹ค. ์ž์‹ ์ด ์›ํ•˜๋Š” ์œ„์ ฏ์„ ์ž์œ ๋กญ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žฅ์  ๊ฐ™๋‹ค. ๋‹จ์ ์„ ๋ฝ‘์ž๋ฉด glance์˜ composable๊ณผ ๊ธฐ์กด compose์˜ composable์˜ ์ด๋ฆ„์ด ๋˜‘๊ฐ™์•„์„œ ํ˜ผ๋™์ด ์˜ค๋Š” ์ •๋„?
  • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด์„œ ์•„์šฐ ์œ ์šฉํ•œ compose ์ „์šฉ ์œ„์ ฏ ์ƒ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋  ๊ฒƒ ๊ฐ™๋‹ค.

glance์— ๊ด€ํ•œ ์œ ์šฉํ•œ ์ •๋ณด์™€ ์ œ ๊ธ€์˜ ์ž˜๋ชป๋œ ์ ์„ ์•Œ๊ณ  ๊ณ„์‹  ๋ถ„๋“ค์˜ ๋Œ“๊ธ€์€ ์ ๊ทน ํ™˜์˜์ž…๋‹ˆ๋‹ค.

728x90