Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JetpackCompose触ってみた

Avatar for jambo-develop-team jambo-develop-team
March 11, 2024
15

 JetpackCompose触ってみた

Jetpack Composeとは

Android のネイティブ UI を構築するためのツールキット Googleによって2021年リリース
高速かつ簡単に、コード量を少なくUIを作成することを目指して設計されてい る
Swiftで言うSwiftUI?

Avatar for jambo-develop-team

jambo-develop-team

March 11, 2024
Tweet

Transcript

  1. 1. Jetpack ComposeͬͯԿʁ • Android ͷωΠςΟϒ UI Λߏங͢ΔͨΊͷπʔϧΩοτ • GoogleʹΑͬͯ2021೥ϦϦʔε

    • ߴ଎͔ͭ؆୯ʹɺίʔυྔΛগͳ͘UIΛ࡞੒͢Δ͜ͱΛ໨ࢦͯ͠ઃܭ͞Ε͍ͯ Δ • SwiftͰݴ͏SwiftUIʁ🤔 Jetpack Composeͱ͸ 
  2. 1. Jetpack ComposeͬͯԿʁ • એݴతUI • ίϯϙʔωϯτϕʔεͷΞʔΩςΫνϟ • ϞμϯͳσβΠϯ •

    πʔϧͱͷ౷߹ • ΞχϝʔγϣϯΛ؆୯ʹ࣮૷Մೳ ಛ௃ Preview: ެࣜΑΓҾ༻ 
  3. 1. Jetpack ComposeͬͯԿʁ • એݴతUI • ίϯϙʔωϯτϕʔεͷΞʔΩςΫνϟ • ϞμϯͳσβΠϯ •

    πʔϧͱͷ౷߹ • ΞχϝʔγϣϯΛ؆୯ʹ࣮૷Մೳ ಛ௃ 💡 ࠓ೔͸͜͜Λઆ໌͠·͢ 
  4. 2. એݴతUIͬͯԿʁ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

    xmlns:app="http://schemas.android.com/apk/res-auto" tools:context=".MainActivity"> <!-- activity_main.xml --> <TextView android:id="@+id/count" android:layout_width="wrap_content" android:layout_height="wrap_content" … /> <Button android:id="@+id/plus_button" android:layout_width="wrap_content" android:layout_height="wrap_content" … /> </androidx.constraintlayout.widget.ConstraintLayout> ໋ྩతUIʢैདྷͷViewʣ Xmlͷ௥Ճ 
  5. 2. એݴతUIͬͯԿʁ class MainActivity : AppCompatActivity() { private lateinit var

    binding: ActivityMainBinding private var count = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) val view = binding.root setContentView(view) binding.plusButton.setOnClickListener(onClickPlusButton) } // Χ΢ϯτΛϓϥεɺςΩετΛมߋ private val onClickPlusButton = View.OnClickListener { count++ 1⃣ binding.count.text = count.toString() 2⃣ } } ໋ྩతUIʢैདྷͷViewʣ ϩδοΫͷ௥Ճ 
  6. 2. એݴతUIͬͯԿʁ • 🐛 ίʔυͷൟࡶ͞ • 🐛 όάͷϦεΫ • 🐛

    อकੑͷ໰୊ • 🐛 มߋ௨஌Λݟಀ͢Մೳੑ͕͋ΔͨΊɺUIͱঢ়ଶͱͷ੔߹ੑ͕ଛͳΘΕΔՄ ೳੑ͕͋Δ σʔλ͕มߋޙʹUIΛมߋ͢Δॲཧ΋ॻ͘ඞཁ͕͋Δ 
  7. 2. એݴతUIͬͯԿʁ var count by remember { mutableStateOf(0) } 2⃣

    Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Column( horizontalAlignment = Alignment.CenterHorizontally ) { // ͜͜Ͱදࣔ͢ΔσʔλΛઌʹએݴ͢Δ Text( text = count.toString(), fontSize = 52.sp ) Button( onClick = { count += 1 }, 1⃣ modifier = Modifier .padding(top = 40.dp) ) { Text(text = "+1") } } } એݴతUIʢJetpack Composeʣ 
  8. 2. એݴతUIͬͯԿʁ ҎԼ՝୊͕ղܾ͞ΕΔ • 🙆 ίʔυͷൟࡶ͕͞ͳ͘ͳΔ • 🙆 όάͷϦεΫ͕ݮΔ •

    🙆 ։ൃऀ͸UIͷݟӫ͑ʹूதͰ͖Δ • 🙆 มߋ௨஌Λݟಀ͢Մೳੑ͕ͳ͘ͳΔ એݴతUIͰॻ͘͜ͱͰσʔλ͕มߋ͞ΕΔ౓ʹ։ൃऀ͕UIΛมߋ͢Δඞཁ ͕ͳ͘ͳΔ 
  9. 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ @Composable fun AlignYourBodyElement( @DrawableRes drawable: Int, @StringRes text:

    Int, modifier: Modifier = Modifier ) { Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier ) { Image( painter = painterResource(drawable), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier .size(88.dp) .clip(CircleShape) ) Text( text = stringResource(text), modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp), style = MaterialTheme.typography.bodyMedium ) } }  ެࣜνϡʔτϦΞϧΑΓҾ༻
  10. 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ @Composable fun FavoriteCollectionCard( @DrawableRes drawable: Int, @StringRes text:

    Int, modifier: Modifier = Modifier ) { Surface( shape = MaterialTheme.shapes.medium, color = MaterialTheme.colorScheme.surfaceVariant, modifier = modifier ) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.width(255.dp) .background(MaterialTheme.colorScheme.surfaceVariant) ) { Image( painter = painterResource(drawable), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.size(80.dp) ) Text( text = stringResource(text), style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(horizontal = 16.dp) ) } } }  ެࣜνϡʔτϦΞϧΑΓҾ༻
  11. 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ @Composable fun HomeSection( @StringRes title: Int, modifier: Modifier

    = Modifier, content: @Composable () -> Unit ) { Column(modifier = modifier .background(MaterialTheme.colorScheme.background) ) { // λΠτϧ Text( text = stringResource(title), style = MaterialTheme.typography.titleMedium, modifier = Modifier .paddingFromBaseline(top = 40.dp, bottom = 16.dp) .padding(horizontal = 16.dp) ) // ಺༰ content() } }  ެࣜνϡʔτϦΞϧΑΓҾ༻
  12. 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ @Composable fun HomeScreen( modifier: Modifier = Modifier )

    { Column( modifier.verticalScroll(rememberScrollState()) ) { Spacer(Modifier.height(16.dp)) HomeSection(title = R.string.align_your_body) { AlignYourBodyRow() } HomeSection(title = R.string.favorite_collections) { FavoriteCollectionsGrid() } Spacer(Modifier.height(16.dp)) } }  ެࣜνϡʔτϦΞϧΑΓҾ༻
  13. 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ 👍ϝϦοτ ♻ ࠶ར༻ੑ ֤ίϯϙʔωϯτ͸ಠཱ͓ͯ͠ΓɺҟͳΔ৔ॴͰ࠶ར༻Ͱ͖ΔͷͰίʔυͷॏෳΛݮΒ͠ɺ։ൃͷޮ཰͕ྑ͘ͳΔ 🔧 ϞδϡϥϦςΟ UIΛখ͞ͳ෦඼ʹ෼ׂ͢Δ͜ͱͰɺ֤ίϯϙʔωϯτ͕ಛఆͷػೳ΍දࣔΛ୲౰͠ɺΑΓ؅ཧ͠΍͘͢ͳΔ 📀

    ಠཱͨ͠ঢ়ଶ؅ཧ ίϯϙʔωϯτ͸ͦΕͧΕಠࣗͷঢ়ଶΛ࣋ͪɺͦͷঢ়ଶʹج͍ͮͯUIΛඳը͢Δ ͜ΕʹΑΓɺΞϓϦέʔγϣϯશମͷঢ়ଶ؅ཧ͕༰қʹͳΔ 📚 ॊೈͳߏ੒ ίϯϙʔωϯτΛ૊Έ߹ΘͤΔ͜ͱͰɺෳࡶͳUIΛߏஙͰ͖Δ 
  14. 4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ ίϯϙδγϣϯͱ࠶ίϯϙʔζ @Composable fun ListComposable(modifier: Modifier) { Box(

    modifier = modifier, contentAlignment = Alignment.Center ) { LazyColumn() { items(50) { ListItem() } } } } @Composable fun ListItem() { val title = "͍Ζ͸ʹ΄΁ͱ ͪΓ͵ΔΛ Θ͔ΑͨΕͦʢলུʣ” var open by remember { mutableStateOf(false) } Column(modifier = Modifier .fillMaxWidth() .background(if (open) Color.Green else Color.Transparent) ) { Row( modifier = Modifier .fillMaxWidth() .padding(12.dp) .clickable { open = !open }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { Text( text = title, fontWeight = FontWeight.Bold, maxLines = if (open) Int.MAX_VALUE else 1, ) } Divider( modifier = Modifier .fillMaxWidth() .size(2.dp) ) } } 
  15. 4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ ίϯϙδγϣϯͱ࠶ίϯϙʔζ @Composable fun ListComposable(modifier: Modifier) { Box(

    modifier = modifier, contentAlignment = Alignment.Center ) { LazyColumn() { items(50) { ListItem() } } } } @Composable fun ListItem() { val title = "͍Ζ͸ʹ΄΁ͱ ͪΓ͵ΔΛ Θ͔ΑͨΕͦʢলུʣ” var open by remember { mutableStateOf(false) } Column(modifier = Modifier .fillMaxWidth() .background(if (open) Color.Green else Color.Transparent) ) { Row( modifier = Modifier .fillMaxWidth() .padding(12.dp) .clickable { open = !open }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { Text( text = title, fontWeight = FontWeight.Bold, maxLines = if (open) Int.MAX_VALUE else 1, ) } Divider( modifier = Modifier .fillMaxWidth() .size(2.dp) ) } } @Composable fun ListComposable(modifier: Modifier) { • 👉 Jetpack ComposeͰUIͷੜ੒͢Δࡍ͸@ComposableΛ෇ ༩ͨؔ͠਺Ͱߦ͏ • 👉 @ComposableΞϊςʔγϣϯ͕෇͍ͨؔ਺Λίϯϙʔβϒ ϧؔ਺ͱ͍͏ • 👉 ίϯϙʔβϒϧؔ਺͕࣮ߦ͞ΕΔ͜ͱͰUIཁૉ͕ੜ੒͞Ε Δʢ=ίϯϙδγϣϯʣ 
  16. 4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ ίϯϙδγϣϯͱ࠶ίϯϙʔζ var open by remember { mutableStateOf(false)

    } @Composable fun ListComposable(modifier: Modifier) { Box( modifier = modifier, contentAlignment = Alignment.Center ) { LazyColumn() { items(50) { ListItem() } } } } @Composable fun ListItem() { val title = "͍Ζ͸ʹ΄΁ͱ ͪΓ͵ΔΛ Θ͔ΑͨΕͦʢলུʣ” var open by remember { mutableStateOf(false) } Column(modifier = Modifier .fillMaxWidth() .background(if (open) Color.Green else Color.Transparent) ) { Row( modifier = Modifier .fillMaxWidth() .padding(12.dp) .clickable { open = !open }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { Text( text = title, fontWeight = FontWeight.Bold, maxLines = if (open) Int.MAX_VALUE else 1, ) } Divider( modifier = Modifier .fillMaxWidth() .size(2.dp) ) } } • 👉 mutableStateOf͸σʔλͷߋ৽Λݕ஌͢Δͱɺࠓ͍Δίϯ ϙʔβϒϧΛ࠶ඳը͢Δʢ=࠶ίϯϙʔζʣ • 👉 remember͸࠶ίϯϙʔζ࣌ʹม਺͕ॳظԽ͞ΕΔͷΛ๷͙ 
  17. 4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ 6*ߋ৽ͷͨΊͷؔ਺͕+FUQBDL$PNQPTF΍,PUMJOϥΠϒϥϦʹ༻ҙ͞Ε͍ͯΔ 6*ߋ৽ͷͨΊͷؔ਺ɾπʔϧ πʔϧ / ؔ਺ ༻్ આ໌

    remember Ұ࣌తͳঢ়ଶͷอ࣋ ίϯϙʔβϒϧؔ਺ͷݺͼग़ؒ͠Ͱ஋Λอ࣋͠ɺ࠶ίϯϙʔζʹΑΔ ࠶ॳظԽΛ๷͙ mutableStateOf ϦΞΫςΟϒͳঢ়ଶ؅ཧ ஋ͷมߋΛ؂ࢹ͠ɺมߋ͕͋ͬͨ৔߹ʹUIΛ࠶ίϯϙʔζ͢Δ StateFlow + collectAsState ϦΞΫςΟϒͳσʔλετϦ ʔϜͷ؂ࢹ StateFlow ͷ஋ͷมߋΛ؂ࢹ͠ɺComposeͷ State ʹม׵ͯ͠UI ͷ࠶ίϯϙʔζΛτϦΨʔ͢Δ LiveData + observeAsState σʔλͷมߋͷ؂ࢹ LiveData ͷ஋ͷมߋΛ؂ࢹ͠ɺมߋ͕͋ͬͨࡍʹComposeͷUIΛ ߋ৽͢Δ UIߋ৽ͷͨΊͷؔ਺ɾπʔϧͷྫ 
  18. 5. ·ͱΊ • 💁 Jetpack Compose͸GoogleʹΑͬͯ։ൃ͞ΕͨAndroid ͷωΠςΟϒ UI Λ ߏங͢ΔͨΊͷ࠷৽ͷπʔϧΩοτ

    • 💁 ߴ଎͔ͭগͳ͍ίʔυͰUIΛ࡞੒Ͱ͖Δ • 💁 એݴతUIΛ࢖͍ͬͯͯɺUIͷߋ৽͸Jetpack Compose͕΍ͬͯ͘ΕΔ • 💁 ίϯϙʔωϯτϕʔεͷϝϦοτΛ׆͔ͤΔ • 💁 Jetpack ComposeͷUIੜ੒ɾߋ৽ʹ͸ίϯϙδγϣϯͱ࠶ίϯϙʔζͱ͍͏ ϓϩηε͕࣮ߦ͞ΕΔ