👏
Jetpack Compose では同一方向にスクロール可能な Composable をネストできない
Android において、同一方向にスクロール可能なコンテンツをネストしたいというのはよくある話です。
具体的には、縦スクロール可能なScrollView
の中にListView
を置くという形ですね。
例えば以下のように、コンテンツ一覧を表示する ComposableListContents
を作成し、それを複数表示する ComposableMultipleLists
を作成したいとします。
@Composable
fun MultipleLists(contents1: List<String>, contents2: List<String>) {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Text(text = "コンテンツ1")
ListContents(contents = contents1)
Text(text = "コンテンツ2")
ListContents(contents = contents2)
}
}
@Composable
fun ListContents(contents: List<String>) {
LazyColumn {
items(contents) {
Text(text = it)
}
}
}
Column
のmodifier
にverticalScroll(rememberScrollState())
を付与し、縦スクロールを可能にしました。
これにより、ListContents
が膨大になってコンテンツが画面に収まりきらなくても、画面全体を縦スクロールして閲覧できるようにしました。
しかし、これを実際に表示しようとすると、下記の例外が出力されます。
java.lang.IllegalStateException: Nesting scrollable in the same direction layouts like LazyColumn and Column(Modifier.verticalScroll()) is not allowed. If you want to add a header before the list of items please take a look on LazyColumn component which has a DSL api which allows to first add a header via item() function and then the list of items via items().
どうやら Jetpack Compose では、LazyColumn
(LazyRow
)またはスクロール可能なColumn
(Row
)はネストできないようです。
解決方法
ListContents
の中身を解体して、以下のようにitem
やitems
を使って定義するのが良さそうです。
@Composable
fun MultipleLists(contents1: List<String>, contents2: List<String>) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
item {
Text(text = "コンテンツ1")
}
items(contents1) {
Text(text = it)
}
item {
Text(text = "コンテンツ2")
}
items(contents2) {
Text(text = it)
}
}
}
一旦これで解決しましたが、他にもっとより良い方法があれば教えてください。
Discussion
あまりどういう実装がしたいのかイメージがつかないのですがこういった感じでしょうか?