Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
JetpackCompose触ってみた 西村
Search
nakagawa
November 04, 2024
6
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
JetpackCompose触ってみた 西村
nakagawa
November 04, 2024
Featured
See All Featured
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
My Coaching Mixtape
mlcsv
0
360
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
330
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
600
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
480
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
540
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.7k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
360
Navigating Team Friction
lara
192
16k
Transcript
ଜ 2023/12/15 Jetpack Compose৮ͬͯΈͨ
Content 1. Jetpack ComposeͬͯԿʁ 2. એݴతUIͬͯԿʁ 3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ 4. Jetpack
ComposeͷUIߋ৽ͷྲྀΕ 5. ·ͱΊ
Jetpack ComposeͬͯԿʁ ̍
1. Jetpack ComposeͬͯԿʁ • Android ͷωΠςΟϒ UI Λߏங͢ΔͨΊͷπʔϧΩοτ • GoogleʹΑͬͯ2021ϦϦʔε
• ߴ͔ͭ؆୯ʹɺίʔυྔΛগͳ͘UIΛ࡞͢Δ͜ͱΛࢦͯ͠ઃܭ͞Ε͍ͯ Δ • SwiftͰݴ͏SwiftUIʁ🤔 Jetpack Composeͱ
1. Jetpack ComposeͬͯԿʁ 👀 ͜ΜͳUI60~70ߦͰ࣮Ͱ͖Δ
1. Jetpack ComposeͬͯԿʁ • એݴతUI • ίϯϙʔωϯτϕʔεͷΞʔΩςΫνϟ • ϞμϯͳσβΠϯ •
πʔϧͱͷ౷߹ • ΞχϝʔγϣϯΛ؆୯ʹ࣮Մೳ ಛ Preview: ެࣜΑΓҾ༻
1. Jetpack ComposeͬͯԿʁ • એݴతUI • ίϯϙʔωϯτϕʔεͷΞʔΩςΫνϟ • ϞμϯͳσβΠϯ •
πʔϧͱͷ౷߹ • ΞχϝʔγϣϯΛ؆୯ʹ࣮Մೳ ಛ 💡 ࠓ͜͜Λઆ໌͠·͢
એݴతUIͬͯԿʁ ̎
2. એݴతUIͬͯԿʁ 🤔 એݴతUIͱ • ཁૉʢUIʣ༩͑ΒΕΔύϥϝʔλʹΑ੍ͬͯޚ͞Εɺσʔλͷঢ়ଶΛUIʹม ͢Δͱ͍͏֓೦ • એݴతUIͰUI͕ࣗಈతʹঢ়ଶʢσʔλʣʹԠ͠ɺUIΛ࠶ඳը͢Δ •
ରʹ։ൃऀ͕σʔλͷঢ়ଶͰUIΛมߋ͢Δ͜ͱΛ໋ྩతUIͱ͍͏ • એݴతUIΛ࠾༻͍ͯ͠Δྫͱͯ͠ReactɺFlutter͕͋Δ
2. એݴతUIͬͯԿʁ 👀 ࣮ࡍʹΞϓϦͰݟͯΈΔ
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ͷՃ
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ʣ ϩδοΫͷՃ
2. એݴతUIͬͯԿʁ • 🐛 ίʔυͷൟࡶ͞ • 🐛 όάͷϦεΫ • 🐛
อकੑͷ • 🐛 มߋ௨Λݟಀ͢Մೳੑ͕͋ΔͨΊɺUIͱঢ়ଶͱͷ߹ੑ͕ଛͳΘΕΔՄ ೳੑ͕͋Δ σʔλ͕มߋޙʹUIΛมߋ͢Δॲཧॻ͘ඞཁ͕͋Δ
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ʣ
2. એݴతUIͬͯԿʁ ҎԼ՝͕ղܾ͞ΕΔ • 🙆 ίʔυͷൟࡶ͕͞ͳ͘ͳΔ • 🙆 όάͷϦεΫ͕ݮΔ •
🙆 ։ൃऀUIͷݟӫ͑ʹूதͰ͖Δ • 🙆 มߋ௨Λݟಀ͢Մೳੑ͕ͳ͘ͳΔ એݴతUIͰॻ͘͜ͱͰσʔλ͕มߋ͞ΕΔʹ։ൃऀ͕UIΛมߋ͢Δඞཁ ͕ͳ͘ͳΔ
ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ ̏
3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ 🤔 ίϯϙʔωϯτϕʔεͷUIͱ • UIΛখ͞ͳ࠶ར༻Մೳͳʮίϯϙʔωϯτʯͱׂͯ͢͠ΔΞϓϩʔν • ύζϧͷϐʔεͷΑ͏ʹUIΛ࡞͢Δ͜ͱ͕Ͱ͖Δ • ίϯϙʔωϯτϕʔεͷUIΛ࠾༻͍ͯ͠Δྫͱͯ͠ReactɺVue.jsɺFlutter͕͋
Δ
3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ ެࣜνϡʔτϦΞϧΑΓҾ༻
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 ) } } ެࣜνϡʔτϦΞϧΑΓҾ༻
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) ) } } } ެࣜνϡʔτϦΞϧΑΓҾ༻
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() } } ެࣜνϡʔτϦΞϧΑΓҾ༻
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)) } } ެࣜνϡʔτϦΞϧΑΓҾ༻
3. ίϯϙʔωϯτϕʔεͷUIͬͯԿʁ 👍ϝϦοτ ♻ ࠶ར༻ੑ ֤ίϯϙʔωϯτಠཱ͓ͯ͠ΓɺҟͳΔॴͰ࠶ར༻Ͱ͖ΔͷͰίʔυͷॏෳΛݮΒ͠ɺ։ൃͷޮ͕ྑ͘ͳΔ 🔧 ϞδϡϥϦςΟ UIΛখ͞ͳ෦ʹׂ͢Δ͜ͱͰɺ֤ίϯϙʔωϯτ͕ಛఆͷػೳදࣔΛ୲͠ɺΑΓཧ͘͢͠ͳΔ 📀
ಠཱͨ͠ঢ়ଶཧ ίϯϙʔωϯτͦΕͧΕಠࣗͷঢ়ଶΛ࣋ͪɺͦͷঢ়ଶʹج͍ͮͯUIΛඳը͢Δ ͜ΕʹΑΓɺΞϓϦέʔγϣϯશମͷঢ়ଶཧ͕༰қʹͳΔ 📚 ॊೈͳߏ ίϯϙʔωϯτΛΈ߹ΘͤΔ͜ͱͰɺෳࡶͳUIΛߏஙͰ͖Δ
Jetpack ComposeͷUIߋ৽ͷྲྀΕ ̐
4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ ίϯϙδγϣϯͱ࠶ίϯϙʔζ w ίϯϙδγϣϯ 6*ͷॳظߏஙͷϓϩηεΛίϯϙδγϣϯͱ͍͏ ੜ͞Εͨ6*ཁૉ෦తͳ6*πϦʔʹஔ͞ΕΔ w ࠶ίϯϙʔζ
σʔλͷมߋ͕ݕ͞Εͨͱ͖ʹɺґଘ͢Δίϯϙʔβϒϧ͕ؔ࠶࣮ߦ͞Εͯ6*͕ߋ৽͞ΕΔϓϩηε
4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ 👀 ࣮ࡍʹΞϓϦͰݟͯΈΔ
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) ) } }
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ཁૉ͕ੜ͞Ε Δʢ=ίϯϙδγϣϯʣ
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࠶ίϯϙʔζ࣌ʹม͕ॳظԽ͞ΕΔͷΛ͙
4. Jetpack ComposeͷUIߋ৽ͷྲྀΕ 6*ߋ৽ͷͨΊͷ͕ؔ+FUQBDL$PNQPTF,PUMJOϥΠϒϥϦʹ༻ҙ͞Ε͍ͯΔ 6*ߋ৽ͷͨΊͷؔɾπʔϧ πʔϧ / ؔ ༻్ આ໌
remember Ұ࣌తͳঢ়ଶͷอ࣋ ίϯϙʔβϒϧؔͷݺͼग़ؒ͠ͰΛอ࣋͠ɺ࠶ίϯϙʔζʹΑΔ ࠶ॳظԽΛ͙ mutableStateOf ϦΞΫςΟϒͳঢ়ଶཧ ͷมߋΛࢹ͠ɺมߋ͕͋ͬͨ߹ʹUIΛ࠶ίϯϙʔζ͢Δ StateFlow + collectAsState ϦΞΫςΟϒͳσʔλετϦ ʔϜͷࢹ StateFlow ͷͷมߋΛࢹ͠ɺComposeͷ State ʹมͯ͠UI ͷ࠶ίϯϙʔζΛτϦΨʔ͢Δ LiveData + observeAsState σʔλͷมߋͷࢹ LiveData ͷͷมߋΛࢹ͠ɺมߋ͕͋ͬͨࡍʹComposeͷUIΛ ߋ৽͢Δ UIߋ৽ͷͨΊͷؔɾπʔϧͷྫ
·ͱΊ ̑
5. ·ͱΊ • 💁 Jetpack ComposeGoogleʹΑͬͯ։ൃ͞ΕͨAndroid ͷωΠςΟϒ UI Λ ߏங͢ΔͨΊͷ࠷৽ͷπʔϧΩοτ
• 💁 ߴ͔ͭগͳ͍ίʔυͰUIΛ࡞Ͱ͖Δ • 💁 એݴతUIΛ͍ͬͯͯɺUIͷߋ৽Jetpack Compose͕ͬͯ͘ΕΔ • 💁 ίϯϙʔωϯτϕʔεͷϝϦοτΛ׆͔ͤΔ • 💁 Jetpack ComposeͷUIੜɾߋ৽ʹίϯϙδγϣϯͱ࠶ίϯϙʔζͱ͍͏ ϓϩηε͕࣮ߦ͞ΕΔ
ऴΘΓ