Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Jetpack ComposeのBottomSheetとの戦い / Fight with Bo...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Masatoshi Kubode
July 23, 2024
Programming
1.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Jetpack ComposeのBottomSheetとの戦い / Fight with BottomSheet of Jetpack Compose
https://sansan.connpass.com/event/321922/
Masatoshi Kubode
July 23, 2024
More Decks by Masatoshi Kubode
See All by Masatoshi Kubode
AIチャットの改善から見えた、良いAI体験とは / What Constitutes a Good AI Experience: Insights from Improving AI Chat
kubode
0
160
3リポジトリーを2ヶ月でモノレポ化した話 / How I turned 3 repositories into a monorepo in 2 months
kubode
0
250
ウォンテッドリーの「ココロオドル」モバイル開発 / Wantedly's "kokoro odoru" mobile development
kubode
2
1.4k
Firebase Dynamic Linksの代替手段を自作する / Create your own Firebase Dynamic Links alternative
kubode
0
740
技術を根付かせる / How to make technology take root
kubode
1
510
WantedlyでのKotlin Multiplatformの導入と課題 / Kotlin Multiplatform Implementation and Challenges at Wantedly
kubode
0
660
Google Play Consoleデベロッパー アカウントの確認 / Verifying your Play Console developer account
kubode
1
1.4k
Make your Android app into Multiplatform app
kubode
0
240
ウォンテッドリーにおけるモバイルアプリ開発 / iOSDC Japan 2024 Sponsor Session
kubode
1
1.5k
Other Decks in Programming
See All in Programming
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
280
FDEが実現するAI駆動経営の現在地
gonta
2
280
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
210
プロポーザルを書いてもらう
pvcresin
0
480
React本体のコードリーディング
high_g_engineer
1
140
Building a Meta Ray-Ban display app
akkeylab
0
130
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
330
Detecting Compromised CI with eBPF and Cilium Tetragon
lizrice
0
180
Google Apps Script で Ruby を動かす
kawahara
0
210
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.5k
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
690
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
170
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.3k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
200
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
200
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Code Review Best Practice
trishagee
74
20k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
The Pragmatic Product Professional
lauravandoore
37
7.4k
My Coaching Mixtape
mlcsv
0
220
Transcript
© 2024 Wantedly, Inc. Jetpack Composeの BottomSheetとの戦い Mobile勉強会#14 2024/07/23 久保出雅俊
© 2024 Wantedly, Inc. wantedly.com/id/kubode @swiz_ard @kubode
© 2024 Wantedly, Inc. Agenda • BottomSheetの苦労話 • 実装については少し難しめの話
© 2024 Wantedly, Inc. Jetpack Composeの標準のBottomSheet実装
© 2024 Wantedly, Inc. 標準のBottomSheet実装 https://m3.material.io/components/bottom-sheets/overview ① Standard ② Modal
Material 2 BottomSheetScaffold ModalBottomSheetLayout Material 3 BottomSheetScaffold ModalBottomSheet
© 2024 Wantedly, Inc. Modalの実装の違い @Composable private fun M3ModalPreview() {
var showSheet by remember { mutableStateOf(false) } Button(onClick = { showSheet = true }) { Text("Show") } if (showSheet) { ModalBottomSheet( onDismissRequest = { showSheet = false } ) { Text("Hello, World!") } } } @Composable private fun M2ModalPreview() { val sheetState = rememberModalBottomSheetState( ModalBottomSheetValue.Hidden ) val coroutineScope = rememberCoroutineScope() ModalBottomSheetLayout( sheetContent = { Text("Hello, World!") }, sheetState = sheetState ) { Button( onClick = { coroutineScope.launch { sheetState.show() } } ) { Text("Show") } } }
© 2024 Wantedly, Inc. 課題
© 2024 Wantedly, Inc. やりたいこと • 検索画面のフィルターをModalで表示 したい • 複数選択のフィルター項目の場合、
OKボタンを画面の下にStickyで出す
© 2024 Wantedly, Inc. 課題 1 BottomNavigationは Activityが所有する XMLのView Activity
BottomNavigation FragmentContainer SearchFragment with Compose
© 2024 Wantedly, Inc. 課題 1 StandardやMaterial2のModalは BottomNavigationが前面に出る (Material3のModalだと問題ないが、現 状はMaterial2を使用
© 2024 Wantedly, Inc. 課題 2 標準のModalの上には、コンテンツを 配置できない
© 2024 Wantedly, Inc. 解決策
© 2024 Wantedly, Inc. 解決策 Modalを自作した • ウィンドウ操作が必要と判断 • ComposeのDialogのコードをもとに自作
◦ Material3のModalじゃない理由は後述しますが、Material3のModalとほぼ同じ実 装
© 2024 Wantedly, Inc. @Composable fun Modal( onDismissRequest: () !>
Unit, sheetContent: @Composable () !> Unit, overlayContent: @Composable (() !> Unit)? = null, sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden), ) { !/ 色々省略あり val dialog = remember(view) { DialogWrapper(/*省略*/).apply { setContent(composition) { DialogLayout { Box(modifier = Modifier.fillMaxSize()) { ModalLayout( sheetState = sheetState, onDismissRequest = onDismissRequest, sheetContent = sheetContent, ) if (overlayContent != null) { OverlayContent( sheetState = sheetState, overlayContent = overlayContent, ) } } } } } }
© 2024 Wantedly, Inc. @Composable fun Modal( onDismissRequest: () !>
Unit, sheetContent: @Composable () !> Unit, overlayContent: @Composable (() !> Unit)? = null, sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden), ) { !/ 色々省略あり val dialog = remember(view) { DialogWrapper(/*省略*/).apply { setContent(composition) { DialogLayout { Box(modifier = Modifier.fillMaxSize()) { ModalLayout( sheetState = sheetState, onDismissRequest = onDismissRequest, sheetContent = sheetContent, ) if (overlayContent != null) { OverlayContent( sheetState = sheetState, overlayContent = overlayContent, ) } } } } } } 透明なフルスクリーンウィンドウ
© 2024 Wantedly, Inc. @Composable fun Modal( onDismissRequest: () !>
Unit, sheetContent: @Composable () !> Unit, overlayContent: @Composable (() !> Unit)? = null, sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden), ) { !/ 色々省略あり val dialog = remember(view) { DialogWrapper(/*省略*/).apply { setContent(composition) { DialogLayout { Box(modifier = Modifier.fillMaxSize()) { ModalLayout( sheetState = sheetState, onDismissRequest = onDismissRequest, sheetContent = sheetContent, ) if (overlayContent != null) { OverlayContent( sheetState = sheetState, overlayContent = overlayContent, ) } } } } } } ウィンドウの中にBottomSheet BottomSheetの制御系
© 2024 Wantedly, Inc. @Composable fun Modal( onDismissRequest: () !>
Unit, sheetContent: @Composable () !> Unit, overlayContent: @Composable (() !> Unit)? = null, sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden), ) { !/ 色々省略あり val dialog = remember(view) { DialogWrapper(/*省略*/).apply { setContent(composition) { DialogLayout { Box(modifier = Modifier.fillMaxSize()) { ModalLayout( sheetState = sheetState, onDismissRequest = onDismissRequest, sheetContent = sheetContent, ) if (overlayContent != null) { OverlayContent( sheetState = sheetState, overlayContent = overlayContent, ) } } } } } } BottomSheetの前面にオーバーレイ BottomSheetのスクロールには連動 しない→Sticky
© 2024 Wantedly, Inc. Usage @Composable private fun ModalPreview() {
var showSheet by remember { mutableStateOf(false) } Button(onClick = { showSheet = true }) { Text("Show") } if (showSheet) { Modal( onDismissRequest = { showSheet = false }, sheetContent = { Text("Content") }, overlayContent = { Button(/*省略*/) }, ) } }
© 2024 Wantedly, Inc. まとめ • ないものは作る • ソースを読んで理解する ◦
ComposeのWindow関連APIは結構泥臭いことをやってて面白い • 下調べは重要 ◦ 実装時はMaterial3のModalを知らなかった ◦ 知っていれば、もう少し実装時間を減らせたはず
© 2024 Wantedly, Inc.