[Jetpack Compose] 縦スクロールと横スクロールの基本

実装

縦スクロール

Column & verticalScrollを使用

@Composable
private fun VerticalScrollView() {
    Column(
        modifier = Modifier
            .padding(12.dp)
            .verticalScroll(rememberScrollState()), // 横スクロール許容
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        repeat(20) {
            Image(
                modifier = Modifier
                    .width(200.dp)
                    .height(200.dp),
                painter = painterResource(id = R.drawable.my_dog),
                contentDescription = "My Dog",
                contentScale = ContentScale.Crop,
            )
        }
    }
}

横スクロール

Row & horizontalScrollを使用

@Composable
private fun HorizontalScrollView() {
    Row(
        modifier = Modifier
            .padding(12.dp)
            .horizontalScroll(rememberScrollState()),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        repeat(20) {
            Image(
                modifier = Modifier
                    .width(200.dp)
                    .height(200.dp),
                painter = painterResource(id = R.drawable.my_dog),
                contentDescription = "My Dog",
                contentScale = ContentScale.Crop,
            )
        }
    }
}

スクロール機能カスタマイズ

スクロール位置の制御

rememberScrollState()で取得したScrollStateを使って、スクロール位置をプログラムから制御することが可能。

@Composable
private fun HorizontalScrollView() {
    val scrollState = rememberScrollState()
    val coroutineScope = rememberCoroutineScope()
    Row(
        modifier = Modifier
            .padding(12.dp)
            .horizontalScroll(scrollState),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Button(onClick = {
            coroutineScope.launch {
                scrollState.animateScrollTo(scrollState.maxValue)
            }
        }) {
            Text("最下部までスクロール")
        }
        repeat(20) {
            Image(
                modifier = Modifier
                    .width(200.dp)
                    .height(200.dp),
                painter = painterResource(id = R.drawable.my_dog),
                contentDescription = "My Dog",
                contentScale = ContentScale.Crop,
            )
        }
    }
}

スクロールイベントの検知

@Composable
private fun HorizontalScrollView() {
    val scrollState = rememberScrollState()
    Row(
        modifier = Modifier
            .padding(12.dp)
            .horizontalScroll(scrollState),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text("スクロール位置: ${scrollState.value}")
        repeat(20) {
            Image(
                modifier = Modifier
                    .width(200.dp)
                    .height(200.dp),
                painter = painterResource(id = R.drawable.my_dog),
                contentDescription = "My Dog",
                contentScale = ContentScale.Crop,
            )
        }
    }
}

LazyColumn / LazyRowとの組み合わせ

@Composable
private fun HorizontalScrollView() {
    LazyRow(
        modifier = Modifier.padding(12.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        items(20) {
            Image(
                modifier = Modifier
                    .width(200.dp)
                    .height(200.dp),
                painter = painterResource(id = R.drawable.my_dog),
                contentDescription = "My Dog",
                contentScale = ContentScale.Crop,
            )
        }
    }
}

LazyColumnは、画面に表示されるアイテムのみを生成するため、メモリ使用量を抑え、スムーズなスクロールにできるそう。