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
Compose for iOS for ZOZOTOWN
Search
ねも
July 14, 2023
Programming
2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Compose for iOS for ZOZOTOWN
ねも
July 14, 2023
More Decks by ねも
See All by ねも
Compose Multiplatform for iOS開発でぶつかった壁
kohei_inoue
0
1.9k
ノンプログラマのための ~アルゴリズムパズル プログラマのための数学パズル入門~
kohei_inoue
0
100
ノンデザイナーズ・デザインブックを読んだので名刺作ってみた
kohei_inoue
0
100
Compose Multiplatform for iOSで音声再生しようぜ!!
kohei_inoue
0
390
夏 × Jetpack Compose
kohei_inoue
0
110
Other Decks in Programming
See All in Programming
조합이폭발하는디자인시스템이걸눈으로도테스트하라고요
giljongyu
0
680
SODA - FACT BOOK(JP)
sodainc
1
40k
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
1.2k
AI時代のFlutter品質設計 — アプリ品質を守るQuality Layers
omatty198
0
330
Event is what happens
moro
2
2.6k
JIS keyboard support in Omarchy
lef237
0
180
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
260
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
1.7k
Optunaを作ったときにやりたかったこと、その後 (2026/10/16, Optuna Meetup #3)
iwiwi
4
1.4k
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
1.9k
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
14
11k
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
2.2k
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
960
The agentic SEO stack - context over prompts
schlessera
0
990
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.6k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
What the history of the web can teach us about the future of AI
inesmontani
PRO
2
770
Building Applications with DynamoDB
mza
96
7.3k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
320
Marketing to machines
jonoalderson
1
6k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Transcript
Compose for iOS for ZOZOTOWN 2023/07/11 ZOZO Tech
Meetup - iOS/Android 株式会社ZOZO ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android1ブロック 財部彰太 ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android2ブロック 井上晃平 Copyright © ZOZO, Inc. 1
© ZOZO, Inc. 株式会社ZOZO ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android1ブロック 財部 彰太 食べる事が好きです。
2
© ZOZO, Inc. 株式会社ZOZO ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android2ブロック 井上 晃平
最近はワンパンマンにハマっていて、ONE先生版と村田先 生版の両方を読み返した 温泉旅館にいくために、そろそろ自動車免許が欲しい 3
© ZOZO, Inc. アジェンダ 1. 発表内容に関する注意と登壇の目的 2. Compose for iOSの基礎知識
2.1. JetBrainsが作るマルチプラットフォームの世界 2.2. Compose for iOSとは 2.3. レンダリング 2.4. Compose for iOSの優れている点 2.5. 今後注意したい動向 3. ZOZOTOWNをCompose for iOSで作った 3.1. 今回作ったもの 3.2. カルーセル部分の作成 3.3. スライダー部分の作成 3.4. それ以外はハリボテです 4. まとめ 4
© ZOZO, Inc. 注意 Compose for iOSは2023年7月現在alpha版 -> 今後大きな変更が加わる可能性がある
目的 すぐ仕事で使ってみてください!というよりは、今後の可能性をお伝えしたい。 フィードバック窓口 https://github.com/JetBrains/compose-multiplatform/issues 1 発表内容に関する注意と登壇の目的 KotlinConf’23 https://kotlinconf.com/talks/ 5
© ZOZO, Inc. 6 Compose for iOSの基礎知識
© ZOZO, Inc. 7 JetBrainsが作る マルチプラットフォームの世界
© ZOZO, Inc. 2.1 JetBrainsが作るマルチプラットフォームの世界 • Kotlin Multiplatform ◦ 複数のプラットフォームでKotlinで書かれたコードを共有する技術
◦ 2023年7月現在beta版であり、ドキュメントによるともうほぼstableとのこと • Kotlin Multiplatform for mobile(KMM) ◦ Kotlin Multiplatformのうち、モバイルに特化した場合の呼称 ◦ データ層のコードや、ViewModelなど、可能な限りの機能をKotlinで作成し、共有する ◦ UIの記述はiOS/Android 各プラットフォームに任せている • Compose Multiplatform ◦ AndroidのUIを宣言的に作成できるJetpack Composeを用いて、Desktop, Web, Androidといったプラットフォー ムのUIを記述できるようにするための仕組み Kotlin Multiplatform https://kotlinlang.org/docs/multiplatform.html Compose Multiplatform https://www.jetbrains.com/ja-jp/lp/compose-multiplatform/ 8
© ZOZO, Inc. 9 Compose for iOSとは
© ZOZO, Inc. Compose MultiplatformのiOSへの対応がalpha版に!! Compose Multiplatform https://www.jetbrains.com/ja-jp/lp/compose-multiplatform/ 10 Button(
onClick = { //hogehoge } ) { Text("Hello $platform") } 2.2 Compose for iOSとは
© ZOZO, Inc. compose-multiplatform-ios-android-template https://github.com/JetBrains/compose-multiplatform-ios-android-template/#readme 11 2.2 Compose for iOSとは
© ZOZO, Inc. 2.2 Compose for iOSとは Compose Multiplatformと Kotlin
Multiplatform for mobileを組み合わせることで、モバイ ルアプリ開発のネットワーク通信からUIの記述までの全範囲 をKotlinで作成し、共有することが可能に! The Kotlin Blog https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 12
© ZOZO, Inc. 13 レンダリング
© ZOZO, Inc. 2.3 レンダリング • Android ◦ 従来の形でレンダリングされる
• iOS ◦ Skikoによってレンダリングされる ◦ Skiko ▪ SkiaをKotlin Multiplatformの中で使えるようにしたもの ◦ Skia ▪ Googleによって作成されたオープンソースの2Dグラフィックスライブラリ ▪ Chrome、Android、Flutterなど様々なハードウェアやソフトウェアプラットフォームで動作する JetBrains/Skiko https://github.com/JetBrains/skiko Skia https://skia.org/ Shader compilation jank https://docs.flutter.dev/perf/shader 14
© ZOZO, Inc. 2.3 レンダリング • FlutterはSkiaを使用した場合、レンダリングパフォーマンス上の課題が発生していた ◦ Compose for
iOSにおいても、Skiaを使用することによるレンダリングパフォーマンスの課題を持つのではない か • KotlinConfの発表(25分あたり)でも、16msの画面の停止を観測したとの解説がある ◦ 今後2msまで縮めていくとのこと 15 Compose Multiplatform on iOS by: Sebastian Aigner and Nikita Lipsky https://www.youtube.com/watch?v=FWVi4aV36d8 Shader compilation jank https://docs.flutter.dev/perf/shader
© ZOZO, Inc. 16 Compose for iOSの優れている点
© ZOZO, Inc. 2.4 優れている点① Jetpack ComposeのAPIがそのまま使える • Android開発で用いるJetpack ComposeのAPIそ
のものがiOSでも動作する • 作成したComposableが無駄にならない The Kotlin Blog https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 17 @Composable fun App() { MaterialTheme { var showImage by remember { mutableStateOf(false) } Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { Button(onClick = { showImage = !showImage }) { Text("Toggle image") } AnimatedVisibility(showImage) { Image( painterResource("compose-multiplatform.xml"), "Compose Multiplatform Logo" } } } } import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Button import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.Alignment import androidx.compose.material.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.painterResource
© ZOZO, Inc. 2.4 優れている点① Jetpack ComposeのAPIがそのまま使える The Kotlin Blog
https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 18
© ZOZO, Inc. 2.4 優れている点② 相互運用性が高い • UIKitView ◦ iOS側の、地図、WebView、メディアプレイヤー、カメラといったプラットフォーム固有のウィジェットをComposeの
なかに組み込むことができる • ComposeUIViewController ◦ ComposeをSwift UIアプリケーションに埋め込むことができる →段階的な移行が可能に The Kotlin Blog https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 19
© ZOZO, Inc. 2.4 優れている点② 相互運用性が高い ComposeUIViewControllerを使うとiOSネイティブとの接続も簡単 The Kotlin Blog
https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 20 @main struct iOSApp: App { var body: some Scene { WindowGroup { ZStack { Color.white.ignoresSafeArea(.all) // status bar color ContentView() }.preferredColorScheme(.light) } } } struct ContentView: View { var body: some View { ComposeView() .ignoresSafeArea(.all, edges: .bottom) } } struct ComposeView: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIViewController { Main_iosKt.MainViewController() } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} } iOSプロジェクト側(iosAppパッケージ)
© ZOZO, Inc. fun MainViewController() = ComposeUIViewController { App() }
@Composable fun App() { MaterialTheme { Screen() } } @Composable fun Screen() { // 実際のホーム画面を構成するコード } 2.4 優れている点② 相互運用性が高い sharedモジュール/iosMainパッケージ sharedモジュール/commonMainパッケージ ComposeUIViewControllerが iOSネイティブとComposeを接続!!! compose-multiplatform-ios-android-template https://github.com/JetBrains/compose-multiplatform-ios-android-template/
© ZOZO, Inc. 22 今後注意したい動向
© ZOZO, Inc. 2.5 今後注意したい動向 テーマ、デザインの方向性が未確定 • Compose for iOSはキャンバスベースのレンダリング
◦ iOSとAndroidアプリケーションはどちらも同じように表示される • 現状Compose Multiplatformは全てのプラットフォームでMaterialのウィジェットが適用されている • ターゲットのプラットフォームの外観にUIを寄せていく仕組みを作るのか、統一的なUIにしていくかは未確定とのこ と => もしCompose for iOSがiOSへデザインを寄せずにAndroidライクなデザインのみを提供することになったら、Stable になっても導入は難しそう The Kotlin Blog https://blog.jetbrains.com/ja/kotlin/2023/05/compose-multiplatform-for-ios-is-in-alpha/ 23
© ZOZO, Inc. 24 ZOZOTOWNをCompose for iOSで作った
© ZOZO, Inc. 25 今回作ったもの
© ZOZO, Inc. 3.1 今回作った物 Compose Multiplatformにより一つのコードで、iOSとAndroid版のホーム画面を作成 26 iOS版 Android版
© ZOZO, Inc. 27 動画だとこんな感じ
© ZOZO, Inc. 28 • カルーセルをスライドした時のテキストのアニメーションの部分 •
複雑なUIである、商品のGrid状のスライダー → 作れます。そう、Compose for iOSならね。 実装上のポイント
© ZOZO, Inc. 29 カルーセル部分の作成
© ZOZO, Inc. 3.2 カルーセル部分の作成 • HorizontalPagerを使用 •
要素のスライド時に、タイトルとサブテキストだけ アニメーション付きでスライドインする 30
© ZOZO, Inc. カルーセルの作成 31 • HorizontalPagerで横方向のカルーセルを実装する。ページの 設定、ページ間のマージン、ページの表示範囲等を引数で設定 している。 •
Android開発の時と同じ書き方でカルーセルを実装できる。 @Composable fun Carousel( modifier: Modifier = Modifier, items: List<CarouselItemModel>, ) { val pagerState = rememberPagerState() Column(/* Columnの諸設定 */) { HorizontalPager( pageCount = items.size, state = pagerState, contentPadding = PaddingValues(horizontal = 20.dp), pageSpacing = 12.dp, ) { page -> CarouselItem(/* 後述します */) } // DotsIndicatorの実装 } }
© ZOZO, Inc. カルーセルの要素の作成 32 • BoxWithConstraintsでComposableの横幅を計測しつつ、要素を重ねるよ うに配置していく • 引数で受け取ったpageOffsetFractionと、BoxWithConstraintsで計測した
横幅で、カルーセルのスライド幅を算出している • Modifier.graphicsLayerで、カルーセル自体 < タイトル < サブテキストの順 番でスライドスピードが早くなるようなアニメーションを設定している @Composable fun CarouselItem( // その他の引数 pageOffsetFraction: Float, ) { BoxWithConstraints(/* BoxWithConstraintsの諸設定 */) { val width = LocalDensity.current.run { constraints.maxWidth.toDp() } val pageOffset = width.value * pageOffsetFraction Image(/* カルーセルの画像 */) Column(/* タイトルとサブテキストを保持する Column */) { Text( modifier = Modifier .graphicsLayer { translationX = - pageOffset * 1.8f }, // タイトルのその他の設定 ) Text( modifier = Modifier .graphicsLayer { translationX = - pageOffset * 2.2f }, // サブテキストのその他の設定 ) } } }
© ZOZO, Inc. 33 スライダー部分の作成
© ZOZO, Inc. 3.3 スライダー部分の作成 34 • LazyHorizontalGridを使用 • GridCells.Fixedで2を設定することで、2行の横方
向のスライダーを実現
© ZOZO, Inc. スライダーの作成 35 • 引数でrowFixedCountとして受け取った行数を、 LazyHorizontalGridのrowsで渡す • LazyHorizontalGridの内部で、SliderItemというスライダーの要
素のコンポーザブルを配置する @Composable fun Slider( // その他引数 sliderItemModels: List<sliderItemModel>, rowFixedCount: Int, ) { Column(/* Column 設定 */) { Text(/* セクションのタイトル(アイテムランキング)表示 */) LazyHorizontalGrid( // Modifier設定 rows = GridCells.Fixed(rowFixedCount), ) { sliderItemModels.forEachIndexed { index, model -> item { SliderItem(/* 後述します */) } } } } }
© ZOZO, Inc. スライダーの要素の作成 36 • SliderItemModelとして表示要素(ブランド名、値段、etc..)を受 け取る • RowとColumnを組み合わせた基本的なレイアウト
@Composable fun SliderItem( model: SliderItemModel, // その他引数 ) { Column( modifier = modifier.width(120.dp) ) { Image(/* 商品画像 */) Column( modifier = Modifier.fillMaxWidth() ) { Row(/* 1行目のブランド名の部分 */) { Text(/* Brand Name */) } Row(/* 2行目の値段とハートの部分 */) { Text(/* 値段 */) Image(/* ハート */) } } } }
© ZOZO, Inc. 37 それ以外はハリボテです
© ZOZO, Inc. 3.4 それ以外はハリボテです 38 • 実際に押せたり検索できたりはせず、見た目だけ作成 • Columnの内部のZOZOTOWNのロゴを保持しているRowで
は、左端のSpacerと、通知とカートのアイコンを保持するRow にweight(1f)を指定することでZOZOTOWNのロゴで余った部 分を等分している @Composable fun TopAppBar() { Column( modifier = Modifier .background(color = ZozoColor.GrayScaleFE) ) { Row(/* 設定 */) { Spacer(modifier = Modifier.weight(1f)) Icon(/* ZOZOTOWNのロゴ */) Row( modifier = Modifier.weight(1f) ) { /* 通知とカートのアイコン */ } } SearchBar(/* 検索バー */) TabLayout(/* すべて、シューズ、コスメのTabLayout */) } }
© ZOZO, Inc. 39 • これが画面に表示されるだけで、アプリのホーム画面がそ れっぽくなった • シンプルにRowに画像を3つ載せている @Composable
fun AttributeSelector( modifier: Modifier = Modifier ) { Row( modifier = modifier.padding(vertical = 12.dp) ) { Image(/* メンズ */) Image(/* レディース */) Image(/* キッズ */) } } メンズ、レディース、キッズの選択UI
© ZOZO, Inc. 40 完成!!
© ZOZO, Inc. 41 まとめ
© ZOZO, Inc. まとめ • KMMと合わせて、Kotlinエコシステムでアプリを作っていけるようになれば嬉しい。ワクワク。 • Swiftをほとんど書かず、Androidアプリを作ってる時と同じ感覚でiOSアプリを作れた。 • やっぱり両OSのコードを共通化できると嬉しい。
• カメラ等ネイティブの機能をふんだんに活用したりといったことは今回していないので、もしかしたら落とし穴はたくさんある かもしれない。 Kotlin Multiplatform https://kotlinlang.org/docs/multiplatform.html 42
None