{"id":45784,"date":"2021-11-24T14:13:54","date_gmt":"2021-11-24T05:13:54","guid":{"rendered":"https:\/\/www.charlezz.com\/?p=45784"},"modified":"2021-11-24T14:13:56","modified_gmt":"2021-11-24T05:13:56","slug":"migrating-to-jetpack-compose-%ec%bb%b4%ed%8f%ac%ec%a6%88-%ec%bd%94%eb%93%9c-%eb%82%b4%ec%9d%98-view","status":"publish","type":"post","link":"https:\/\/charlezz.com\/?p=45784","title":{"rendered":"Migrating to Jetpack Compose &#8211; \ucef4\ud3ec\uc988 \ucf54\ub4dc \ub0b4\uc758 View"},"content":{"rendered":"\n<p>\uc774\uc81c \uc2dd\ubb3c \uc124\uba85\uc744 \ub9c8\uc774\uadf8\ub808\uc774\uc158\ud574 \ud574\ubcf4\uc790. fragment_plant_detail.xml\uc758 \ucf54\ub4dc\uc5d0\ub294 \ud654\uba74\uc5d0 \ud45c\uc2dc\ud560 \ud14d\uc2a4\ud2b8\ub97c XML\uc5d0 \uc54c\ub824\uc8fc\uae30 \uc704\ud574 app:renderHtml=&#8221;@{viewModel.plant.description}&#8221;\uc774 \uc788\ub294 TextView\uac00 \uc788\ub2e4. renderHtml\uc740 PlantDetailBindingAdapters.kt \ud30c\uc77c\uc5d0\uc11c \ucc3e\uc744 \uc218 \uc788\ub294 \ubc14\uc778\ub529 \uc5b4\ub311\ud130\ub2e4. \uad6c\ud604\uc740 HtmlCompat.fromHtml\uc744 \uc0ac\uc6a9\ud558\uc5ec TextView\uc758 \ud14d\uc2a4\ud2b8\ub97c \uc124\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<p>\uadf8\ub7ec\ub098 \ucef4\ud3ec\uc988\ub294 \ud604\uc7ac Spanned \ud074\ub798\uc2a4\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, HTML \ud615\uc2dd\uc758 \ud14d\uc2a4\ud2b8\ub97c \ud45c\uc2dc\ud558\uc9c0 \uc54a\ub294\ub2e4. \ub530\ub77c\uc11c \uc774 \ud55c\uacc4\ub97c \uc6b0\ud68c\ud558\ub824\uba74, \ucef4\ud3ec\uc988 \ucf54\ub4dc\uc758 View \uc2dc\uc2a4\ud15c\uc5d0\uc11c TextView\ub97c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p>\ucef4\ud3ec\uc988\ub294 \uc544\uc9c1 HTML \ucf54\ub4dc\ub97c \ub80c\ub354\ub9c1\ud560 \uc218 \uc5c6\uc73c\ubbc0\ub85c, <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:ui\/ui-core\/src\/androidMain\/kotlin\/androidx\/ui\/viewinterop\/ComposedView.kt\">AndroidView<\/a> API\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc815\ud655\ud788 \uc774\ub97c \uc218\ud589\ud558\ub3c4\ub85d \ud504\ub85c\uadf8\ub798\ubc0d \ubc29\uc2dd\uc73c\ub85c TextView\ub97c \uc0dd\uc131\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p>AndroidView\ub294 View\ub97c \ub9e4\uac1c\ubcc0\uc218\ub85c \uc0ac\uc6a9\ud558\uace0, View\uac00 \uc804\uac1c\ub418\uc5c8\uc744 \ub54c \ucf5c\ubc31\uc744 \uc81c\uacf5\ud55c\ub2e4.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p><strong>Note<\/strong>: AndroidView\ub294 \ud504\ub85c\uadf8\ub798\ubc0d \ubc29\uc2dd\uc73c\ub85c \uc0dd\uc131\ub41c View\ub97c \uc0ac\uc6a9\ud55c\ub2e4. XML \ud30c\uc77c\uc744 \uc0bd\uc785\ud558\ub824\ub294 \uacbd\uc6b0 androidx.compose.ui:ui-viewbinding \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c AndroidViewBinding API\ub85c <a href=\"https:\/\/developer.android.com\/topic\/libraries\/view-binding\">View Binding<\/a>\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc0bd\uc785\ud560 \uc218 \uc788\ub2e4<\/p><\/blockquote>\n\n\n\n<p>\uc0c8 PlantDescription \ucef4\ud3ec\uc800\ube14\uc744 \ub9cc\ub4e4\uc5b4 \uc774\ub97c \uc218\ud589\ud574\ubcf4\uc790. \uc774 \ucef4\ud3ec\uc800\ube14\uc740 \ubc29\uae08 \ub78c\ub2e4\uc5d0\uc11c \uae30\uc5b5\ud55c(remember \ud568\uc218\ub85c \ucef4\ud3ec\uc9c0\uc158 \ud2b8\ub9ac \ub0b4\ubd80\uc5d0 \uc800\uc7a5\ud55c) TextView\uc640 \ud568\uaed8 AndroidView\ub97c \ud638\ucd9c\ud55c\ub2e4. factory \ucf5c\ubc31\uc5d0\uc11c \uc8fc\uc5b4\uc9c4 Context\ub97c \uc0ac\uc6a9\ud558\uc5ec HTML \uc0c1\ud638 \uc791\uc6a9\uc5d0 \ubc18\uc751\ud558\ub294 TextView\ub97c \ucd08\uae30\ud654\ud55c\ub2e4. \uadf8\ub9ac\uace0 \uc5c5\ub370\uc774\ud2b8 \ucf5c\ubc31\uc5d0\uc11c \uae30\uc5b5\ub41c HTML \ud615\uc2dd\uc758 description\uc73c\ub85c \ud14d\uc2a4\ud2b8\ub97c \uc124\uc815\ud55c\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">PlantDetailDescription.kt<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>@Composable\nprivate fun PlantDescription(description: String) {\n\u00a0 \u00a0 \/\/ HTML \ud615\uc2dd\uc758 description\uc744 \ub0b4\ubd80\uc5d0 \uc800\uc7a5\ud55c\ub2e4. \uc0c8\ub85c\uc6b4 description\uc774 \ub4e4\uc5b4\uc624\uba74 \ub78c\ub2e4\uc2dd\uc744 \uc7ac\uc2e4\ud589\ud55c\ub2e4.\n\u00a0 \u00a0 val htmlDescription = remember(description) {\n\u00a0 \u00a0 \u00a0 \u00a0 HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_COMPACT)\n\u00a0 \u00a0 }\n\n\u00a0 \u00a0 \/\/ \ud654\uba74\uc0c1\uc5d0 TextView\ub97c \ud45c\uc2dc\ud558\uace0 \uc804\uac1c \ub420 \ub54c HTML description\uc744 \uc5c5\ub370\uc774\ud2b8 \ud55c\ub2e4.\n\u00a0 \u00a0 \/\/ htmlDescription\uc744 \uc5c5\ub370\uc774\ud2b8 \ud558\ub294 \uac83\uc740 AndroidView\ub97c \uc7ac\uad6c\uc131\ud558\ub3c4\ub85d \ub9cc\ub4e4\uace0, \ud14d\uc2a4\ud2b8\ub97c \uc5c5\ub370\uc774\ud2b8 \uc2dc\ud0a8\ub2e4.\n\u00a0 \u00a0 AndroidView(\n\u00a0 \u00a0 \u00a0 \u00a0 factory = { context ->\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TextView(context).apply {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 movementMethod = LinkMovementMethod.getInstance()\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 \u00a0 \u00a0 },\n\u00a0 \u00a0 \u00a0 \u00a0 update = {\n\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 it.text = htmlDescription\n\u00a0 \u00a0 \u00a0 \u00a0 }\n\u00a0 \u00a0 )\n}\n\n@Preview\n@Composable\nprivate fun PlantDescriptionPreview() {\n\u00a0 \u00a0 MaterialTheme {\n\u00a0 \u00a0 \u00a0 \u00a0 PlantDescription(\"HTML&lt;br>&lt;br>description\")\n\u00a0 \u00a0 }\n}<\/code><\/pre>\n\n\n\n<p>\ubbf8\ub9ac\ubcf4\uae30\ub85c \ubcf4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-migration\/img\/95d8ca1832c1ef26.png\" alt=\"95d8ca1832c1ef26.png\"\/><\/figure><\/div>\n\n\n\n<p><br>htmlDescription\uc740 \ub9e4\uac1c\ubcc0\uc218\ub85c \uc804\ub2ec\ub41c \uc8fc\uc5b4\uc9c4 \uc124\uba85\uc5d0 \ub300\ud55c HTML description\uc744 \ub0b4\ubd80\uc5d0 \uc800\uc7a5\ud55c\ub2e4. description \ub9e4\uac1c\ubcc0\uc218\uac00 \ubcc0\uacbd\ub418\uba74 \uba54\ubaa8\ub9ac \ub0b4\ubd80\uc758 htmlDescription \ucf54\ub4dc\uac00 \ub2e4\uc2dc \uc2e4\ud589\ub41c\ub2e4.<\/p>\n\n\n\n<p>\ub9c8\ucc2c\uac00\uc9c0\ub85c, htmlDescription\uc774 \ubcc0\uacbd\ub418\uba74, AndroidView \uc5c5\ub370\uc774\ud2b8 \ucf5c\ubc31\uc740 \uc7ac\uad6c\uc131(recompose)\ud55c\ub2e4. \ucf5c\ubc31 \ub0b4\ubd80\uc5d0\uc11c \uc77d\uc740 \ubaa8\ub4e0 \uc0c1\ud0dc\ub294 \uc7ac\uad6c\uc131\uc744 \uc720\ubc1c\uc2dc\ud0a4\ub294 \uc694\uc18c\uac00 \ub41c\ub2e4.<\/p>\n\n\n\n<p>PlantDetailContent \ucef4\ud3ec\uc800\ube14\uc5d0 PlantDescription\uc744 \ucd94\uac00\ud558\uace0, HTML description\ub3c4 \ud45c\uc2dc\ud558\ub3c4\ub85d \ubbf8\ub9ac\ubcf4\uae30 \ucf54\ub4dc\ub97c \ubcc0\uacbd\ud574 \ubcf4\uc790.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">PlantDetailDescription.kt<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>@Composable<br>fun PlantDetailContent(plant: Plant) {<br>&nbsp; &nbsp; Surface {<br>&nbsp; &nbsp; &nbsp; &nbsp; Column(Modifier.padding(dimensionResource(R.dimen.margin_normal))) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PlantName(plant.name)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PlantWatering(plant.wateringInterval)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PlantDescription(plant.description)<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>@Preview<br>@Composable<br>private fun PlantDetailContentPreview() {<br>&nbsp; &nbsp; val plant = Plant(\"id\", \"Apple\", \"HTML&lt;br&gt;&lt;br&gt;description\", 3, 30, \"\")<br>&nbsp; &nbsp; MaterialTheme {<br>&nbsp; &nbsp; &nbsp; &nbsp; PlantDetailContent(plant)<br>&nbsp; &nbsp; }<br>}<\/code><\/pre>\n\n\n\n<p>\ubbf8\ub9ac\ubcf4\uae30\ub85c \ubcf4\uba74 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-migration\/img\/aa43efe444af4f75.png\" alt=\"aa43efe444af4f75.png\"\/><\/figure><\/div>\n\n\n\n<p>\uc5ec\uae30\uae4c\uc9c0, \uc6d0\ubcf8 ConstraintLayout \ub0b4\uc758 \ubaa8\ub4e0 \ucf58\ud150\uce20\ub97c \ucef4\ud3ec\uc988\ub85c \ub9c8\uc774\uadf8\ub808\uc774\uc158 \ud588\ub2e4. \uc571\uc744 \uc2e4\ud589\ud558\uc5ec \uc608\uc0c1\ub300\ub85c \uc791\ub3d9\ud558\ub294\uc9c0 \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/developer.android.com\/codelabs\/jetpack-compose-migration\/img\/e2f5c3ec20d4966f.gif\" alt=\"e2f5c3ec20d4966f.gif\" width=\"393\" height=\"803\"\/><\/figure><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc774\uc81c \uc2dd\ubb3c \uc124\uba85\uc744 \ub9c8\uc774\uadf8\ub808\uc774\uc158\ud574 \ud574\ubcf4\uc790. fragment_plant_detail.xml\uc758 \ucf54\ub4dc\uc5d0\ub294 \ud654\uba74\uc5d0 \ud45c\uc2dc\ud560 \ud14d\uc2a4\ud2b8\ub97c XML\uc5d0 \uc54c\ub824\uc8fc\uae30 \uc704\ud574 app:renderHtml=&#8221;@{viewModel.plant.description}&#8221;\uc774 \uc788\ub294 TextView\uac00 \uc788\ub2e4. renderHtml\uc740 PlantDetailBindingAdapters.kt \ud30c\uc77c\uc5d0\uc11c \ucc3e\uc744 \uc218 \uc788\ub294 \ubc14\uc778\ub529 \uc5b4\ub311\ud130\ub2e4. \uad6c\ud604\uc740 HtmlCompat.fromHtml\uc744 \uc0ac\uc6a9\ud558\uc5ec TextView\uc758 \ud14d\uc2a4\ud2b8\ub97c \uc124\uc815\ud55c\ub2e4. \uadf8\ub7ec\ub098 \ucef4\ud3ec\uc988\ub294 \ud604\uc7ac Spanned \ud074\ub798\uc2a4\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\uace0, HTML \ud615\uc2dd\uc758 \ud14d\uc2a4\ud2b8\ub97c \ud45c\uc2dc\ud558\uc9c0 \uc54a\ub294\ub2e4. \ub530\ub77c\uc11c \uc774 \ud55c\uacc4\ub97c \uc6b0\ud68c\ud558\ub824\uba74, \ucef4\ud3ec\uc988 \ucf54\ub4dc\uc758 View [&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\/45784"}],"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=45784"}],"version-history":[{"count":1,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45784\/revisions"}],"predecessor-version":[{"id":45785,"href":"https:\/\/charlezz.com\/index.php?rest_route=\/wp\/v2\/posts\/45784\/revisions\/45785"}],"wp:attachment":[{"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=45784"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=45784"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/charlezz.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=45784"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}