【KMP】LazyRowのクラッシュ問題を解決する
はじめに
Android StudioでKotlin Multiplatform(KMP)
を使用して開発した際に、ScrollableTabRow
内にLazyRow
を配置するとアプリがクラッシュする問題が発生しました。
実行例
@Composable
fun ExampleTabRow(
coroutineScope: CoroutineScope,
pagerState: PagerState,
tabItems: List<String>
) {
Column {
ScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
edgePadding = 0.dp,
indicator = { tabPositions ->
Box(
Modifier
.tabIndicatorOffset(tabPositions[pagerState.currentPage])
.height(3.dp)
.background(color = Color(0xFF007993))
)
}
) {
LazyRow(
modifier = Modifier.fillMaxSize()
) {
itemsIndexed(tabItems) { index, title ->
TabItem(
selected = pagerState.currentPage == index,
text = title,
onClick = { coroutineScope.launch { pagerState.scrollToPage(index) } },
)
}
}
}
}
}
この記事は、私がその問題を解決した方法について紹介するものになります。
結論
レイアウトの競合が発生しています。
ScrollableTabRow
内にLazyRow
ではなく別のものを配置しましょう。
説明
ScrollableTabRow
とLazyRow
はどちらもスクロール可能なコンポーネントです。
そのため、ScrollableTabRow
の内部でLazyRow
を使用するとレイアウトの競合が発生します。
これだけだと分かりにくいかもしれないので雑に例えてみます。
遊園地に「列に並んで乗るアトラクション」があるとした場合、「ジェットコースター🎢(ScrollableTabRow
)」に「観覧車🎡(LazyRow
)」を乗せると大混乱が起きますよね。
解決するには、ジェットコースターにそのまま並べば良いだけの話なのです。
今回、私はLazyRow
を使わずにforEachIndexed
で一つずつTabItem
を追加することで、正常に動作するように修正しました。
修正後
@Composable
fun ExampleTabRow(
coroutineScope: CoroutineScope,
pagerState: PagerState,
tabItems: List<String>
) {
Column {
ScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
edgePadding = 0.dp,
indicator = { tabPositions ->
Box(
Modifier
.tabIndicatorOffset(tabPositions[pagerState.currentPage])
.height(3.dp)
.background(color = Color(0xFF007993))
)
}
) {
tabItems.forEachIndexed { index, title ->
TabItem(
selected = pagerState.currentPage == index,
text = title,
onClick = { coroutineScope.launch { pagerState.scrollToPage(index) } },
)
}
}
}
}
レイアウトを組む時は、各コンポーネントを適切に使用しましょう!
さいごに
ここまで記事を読んでくださり、ありがとうございました!
UIを実装する時は各コンポーネントのスクロール特性を理解することが大事ですね。
皆さんも素敵なハッピーKMPライフを!!!🌸

地域のためのコミュニケーションアプリ「CocBan(コクバン)」のテックブログです。CocBanの開発・運用にまつわる技術的な知見を投稿します。お問い合わせはこちら(cocban.com/contacts/)です。
Discussion