{"id":45513,"date":"2021-11-07T19:42:24","date_gmt":"2021-11-07T10:42:24","guid":{"rendered":"https:\/\/www.charlezz.com\/?p=45513"},"modified":"2021-11-12T16:33:03","modified_gmt":"2021-11-12T07:33:03","slug":"jetpack-compose-basics-%eb%a7%88%eb%ac%b4%eb%a6%ac-%ec%9e%91%ec%97%85","status":"publish","type":"post","link":"https:\/\/charlezz.com\/?p=45513","title":{"rendered":"Jetpack Compose basics &#8211; \ub9c8\ubb34\ub9ac \uc791\uc5c5"},"content":{"rendered":"\n<p>\uc774\ubc88 \uacfc\uc815\uc5d0\uc11c\ub294 \uc774\ubbf8 \uc54c\uace0\uc788\ub294 \uac83\ub4e4\uc744 \uc801\uc6a9\ud558\uace0 \uba87\uac00\uc9c0 \ud78c\ud2b8\uc640 \ud568\uaed8 \uc0c8\ub85c\uc6b4 \uac1c\ub150\uc744 \ubc30\uc6b0\uac83\uc774\ub2e4. <\/p>\n\n\n\n<p>\uc774 \ud654\uba74\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uc790.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"300\" height=\"534\" src=\"https:\/\/www.charlezz.com\/wordpress\/wp-content\/uploads\/2021\/11\/www.charlezz.com-jetpack-compose-basics-87f2753c576d26f2.gif\" alt=\"\" class=\"wp-image-45514\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\ubc84\ud2bc\uc744 \uc544\uc774\ucf58\uc73c\ub85c \uad50\uccb4\ud558\uae30<\/h2>\n\n\n\n<ul><li>\ud558\uc704 Icon\uacfc IconButton \ucef4\ud3ec\uc800\ube14\uc744 \ud568\uaed8 \uc0ac\uc6a9\ud55c\ub2e4.<\/li><li>\uc544\uc774\ucf58 \ub9ac\uc18c\uc2a4\ub294 material-icons-extended \uc544\ud2f0\ud329\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\uac00\ub2a5\ud55c Icons.Filled.ExpandLess \ubc0f Icons.Filled.ExpandMore\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \ub2e4\uc74c\uc758 \ucf54\ub4dc\ub77c\uc778\uc744 app\/build.gradle \ud30c\uc77c\uc758 \uc758\uc874\uc131\uc73c\ub85c \ucd94\uac00\ud55c\ub2e4.<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>implementation \"androidx.compose.material:material-icons-extended:$compose_version\"<\/code><\/pre>\n\n\n\n<ul><li>padding\uc744 \uc218\uc815\ud558\uc5ec \uc815\ub82c\ud55c\ub2e4.<\/li><li>\uc811\uadfc\uc131\uc744 \uc704\ud574 content description\uc744 \ucd94\uac00\ud558\uc790.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\ubb38\uc790\uc5f4 \ub9ac\uc18c\uc2a4 \uc0ac\uc6a9\ud558\uae30<\/h2>\n\n\n\n<p>&#8220;Show more&#8221; \ubc0f &#8220;Show less&#8221; \uc5d0 \ub300\ud55c content description\uc744 \ub098\ud0c0\ub0b4\uace0, \uc774\ub97c if \ubb38\uc744 \uc0ac\uc6a9\ud558\uc5ec \uac04\ub2e8\ud788 \ucd94\uac00\ud558\uc790.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>contentDescription = if (expanded) \"Show less\" else \"Show more\"<\/code><\/pre>\n\n\n\n<p>\ud558\uc9c0\ub9cc \ud558\ub4dc\ucf54\ub529\ub41c \ubb38\uc790\uc5f4\uc740 \uc88b\uc9c0 \ubabb\ud55c \ubc29\ubc95\uc774\uace0 strings.xml \ud30c\uc77c\ub85c\ubd80\ud130 \uac00\uc838\uc624\ub294 \uac83\uc774 \uc88b\ub2e4.<\/p>\n\n\n\n<p>\uac01 \ubb38\uc790\uc5f4\uc5d0 \ub300\ud574 Extract string resource\ub97c \uc0ac\uc6a9\ud558\uc790. \uc548\ub4dc\ub85c\uc774\ub4dc \uc2a4\ud29c\ub514\uc624\uc5d0 \uc788\ub294 Context Actions\uc5d0\uc11c \uc774\ub7f0 \uc791\uc5c5\uc744 \uc790\ub3d9\uc73c\ub85c \ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p>\ub300\uc548\uc73c\ub85c\ub294 app\/src\/res\/values\/strings.xml \uc744 \uc5f4\uace0 \ub2e4\uc74c\uc758 \ub77c\uc778\uc744 \ucd94\uac00\ud558\ub294 \uac83\uc774\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;string name=\"show_less\"&gt;Show less&lt;\/string&gt;<br>&lt;string name=\"show_more\"&gt;Show more&lt;\/string&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\ub354 \ubcf4\uae30 \ub098\ud0c0\ub0b4\uae30<\/h2>\n\n\n\n<p>\uac01 \uce74\ub4dc \uc0ac\uc774\uc988\uc5d0 \ub9de\uac8c \ubcc0\uacbd\ub418\ub3c4\ub85d &#8220;Composem ipsum&#8221; \ud14d\uc2a4\ud2b8\ub294 \ub098\ud0c0\ub098\uac70\ub098 \uc0ac\ub77c\uc9c4\ub2e4.<\/p>\n\n\n\n<ul><li>\uc0c8\ub85c\uc6b4 Text \ucef4\ud3ec\uc800\ube14\uc744 Column\uc5d0 Greeting\uc73c\ub85c \ucd94\uac00\ud558\uace0 \uc544\uc774\ud15c\uc774 \ud655\uc7a5\ub420 \ub54c \ubcf4\uc5ec\uc904 \uc218 \uc788\ub3c4\ub85d \ud55c\ub2e4.<\/li><li>extraPadding\uc740 \uc81c\uac70\ud558\uace0 \ub300\uc2e0\uc5d0 animateContentSize\ub97c Row\uc5d0 \ucd94\uac00\ud55c\ub2e4. \uc774\ub97c \ud1b5\ud574 \uc218\ub3d9\uc73c\ub85c \uc870\uc791\ud558\uae30 \uc5b4\ub824\uc6b4 \uc560\ub2c8\uba54\uc774\uc158\uc744 \uc0dd\uc131 \uc791\uc5c5\uc744 \uc790\ub3d9\ud654 \ud55c\ub2e4. \ub610\ud55c, \uc774\ub294 coerceAtLeast\ud568\uc218\ub97c \uc81c\uac70\ud560 \uc218 \uc788\ub3c4\ub85d \ud55c\ub2e4.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">elevation \ubc0f shapes<\/h2>\n\n\n\n<ul><li>shadow\uc640 clip\uc744 \ud568\uaed8 \uc0ac\uc6a9\ud558\uc5ec \uce74\ub4dc \ucc98\ub7fc \ubcf4\uc774\uac8c \ub9cc\ub4e4 \uc218 \uc788\ub2e4. \ud558\uc9c0\ub9cc \uba38\ud14c\ub9ac\uc5bc \ucef4\ud3ec\uc800\ube14\uc5d0 \ud3ec\ud568\ub41c Card\ub77c\ub294 \uac83\uc774 \uc874\uc7ac\ud55c\ub2e4.<\/li><\/ul>\n\n\n\n<p>\ucd5c\uc885 \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class MainActivity : ComponentActivity() {<br>&nbsp; &nbsp; override fun onCreate(savedInstanceState: Bundle?) {<br>&nbsp; &nbsp; &nbsp; &nbsp; super.onCreate(savedInstanceState)<br>&nbsp; &nbsp; &nbsp; &nbsp; setContent {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BasicsCodelabTheme {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MyApp()<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>@Composable<br>private fun MyApp() {<br>&nbsp; &nbsp; var shouldShowOnboarding by rememberSaveable { mutableStateOf(true) }<br><br>&nbsp; &nbsp; if (shouldShowOnboarding) {<br>&nbsp; &nbsp; &nbsp; &nbsp; OnboardingScreen(onContinueClicked = { shouldShowOnboarding = false })<br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; Greetings()<br>&nbsp; &nbsp; }<br>}<br><br>@Composable<br>private fun OnboardingScreen(onContinueClicked: () -&gt; Unit) {<br>&nbsp; &nbsp; Surface {<br>&nbsp; &nbsp; &nbsp; &nbsp; Column(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modifier = Modifier.fillMaxSize(),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; verticalArrangement = Arrangement.Center,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; horizontalAlignment = Alignment.CenterHorizontally<br>&nbsp; &nbsp; &nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text(\"Welcome to the Basics Codelab!\")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Button(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modifier = Modifier.padding(vertical = 24.dp),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onClick = onContinueClicked<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text(\"Continue\")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>@Composable<br>private fun Greetings(names: List&lt;String&gt; = List(1000) { \"$it\" } ) {<br>&nbsp; &nbsp; LazyColumn(modifier = Modifier.padding(vertical = 4.dp)) {<br>&nbsp; &nbsp; &nbsp; &nbsp; items(items = names) { name -&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Greeting(name = name)<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>@Composable<br>private fun Greeting(name: String) {<br>&nbsp; &nbsp; Card(<br>&nbsp; &nbsp; &nbsp; &nbsp; backgroundColor = MaterialTheme.colors.primary,<br>&nbsp; &nbsp; &nbsp; &nbsp; modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)<br>&nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; CardContent(name)<br>&nbsp; &nbsp; }<br>}<br><br>@Composable<br>private fun CardContent(name: String) {<br>&nbsp; &nbsp; var expanded by remember { mutableStateOf(false) }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; Row(<br>&nbsp; &nbsp; &nbsp; &nbsp; modifier = Modifier<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .padding(12.dp)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .animateContentSize(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; animationSpec = spring(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dampingRatio = Spring.DampingRatioMediumBouncy,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stiffness = Spring.StiffnessLow<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; Column(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modifier = Modifier<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .weight(1f)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .padding(12.dp)<br>&nbsp; &nbsp; &nbsp; &nbsp; ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text(text = \"Hello, \")<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text = name,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style = MaterialTheme.typography.h4.copy(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fontWeight = FontWeight.ExtraBold<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (expanded) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text = (\"Composem ipsum color sit lazy, \" +<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \"padding theme elit, sed do bouncy. \").repeat(4),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; IconButton(onClick = { expanded = !expanded }) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Icon(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imageVector = if (expanded) Filled.ExpandLess else Filled.ExpandMore,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contentDescription = if (expanded) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stringResource(R.string.show_less)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stringResource(R.string.show_more)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>@Preview(<br>&nbsp; &nbsp; showBackground = true,<br>&nbsp; &nbsp; widthDp = 320,<br>&nbsp; &nbsp; uiMode = UI_MODE_NIGHT_YES,<br>&nbsp; &nbsp; name = \"DefaultPreviewDark\"<br>)<br>@Preview(showBackground = true, widthDp = 320)<br>@Composable<br>fun DefaultPreview() {<br>&nbsp; &nbsp; BasicsCodelabTheme {<br>&nbsp; &nbsp; &nbsp; &nbsp; Greetings()<br>&nbsp; &nbsp; }<br>}<br><br>@Preview(showBackground = true, widthDp = 320, heightDp = 320)<br>@Composable<br>fun OnboardingPreview() {<br>&nbsp; &nbsp; BasicsCodelabTheme {<br>&nbsp; &nbsp; &nbsp; &nbsp; OnboardingScreen(onContinueClicked = {})<br>&nbsp; &nbsp; }<br>}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\uc774\ubc88 \uacfc\uc815\uc5d0\uc11c\ub294 \uc774\ubbf8 \uc54c\uace0\uc788\ub294 \uac83\ub4e4\uc744 \uc801\uc6a9\ud558\uace0 \uba87\uac00\uc9c0 \ud78c\ud2b8\uc640 \ud568\uaed8 \uc0c8\ub85c\uc6b4 \uac1c\ub150\uc744 \ubc30\uc6b0\uac83\uc774\ub2e4. \uc774 \ud654\uba74\uc744 \ub9cc\ub4e4\uc5b4 \ubcf4\uc790. \ubc84\ud2bc\uc744 \uc544\uc774\ucf58\uc73c\ub85c \uad50\uccb4\ud558\uae30 \ud558\uc704 Icon\uacfc IconButton \ucef4\ud3ec\uc800\ube14\uc744 \ud568\uaed8 \uc0ac\uc6a9\ud55c\ub2e4. \uc544\uc774\ucf58 \ub9ac\uc18c\uc2a4\ub294 material-icons-extended \uc544\ud2f0\ud329\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\uac00\ub2a5\ud55c Icons.Filled.ExpandLess \ubc0f Icons.Filled.ExpandMore\ub97c \uc0ac\uc6a9\ud55c\ub2e4. \ub2e4\uc74c\uc758 \ucf54\ub4dc\ub77c\uc778\uc744 app\/build.gradle \ud30c\uc77c\uc758 \uc758\uc874\uc131\uc73c\ub85c \ucd94\uac00\ud55c\ub2e4. padding\uc744 \uc218\uc815\ud558\uc5ec \uc815\ub82c\ud55c\ub2e4. \uc811\uadfc\uc131\uc744 \uc704\ud574 content description\uc744 \ucd94\uac00\ud558\uc790. \ubb38\uc790\uc5f4 \ub9ac\uc18c\uc2a4 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[38],"tags":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45513"}],"collection":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=45513"}],"version-history":[{"count":1,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45513\/revisions"}],"predecessor-version":[{"id":45515,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45513\/revisions\/45515"}],"wp:attachment":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=45513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=45513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=45513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}