Compose UI:LazyRow

投稿日:  更新日:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。

そのライブラリ中のLazyRowについて、構成や使用方法などをまとめます。

※環境:Android Studio Koala | 2024.1.1 Patch 1
    Kotlin 1.9.0
    Compose Compiler 1.5.1
    androidx.compose.foundation:foundation 1.6.8

スポンサーリンク

UIの概要

LazyRowは「複数のデータやオブジェクト」または「コレクション」を一覧(リスト)表示するUIです。

1つのデータや要素をアイテムとして、横(行:Row)方向に並べます。

コレクションのサンプル

    LazyRow(
        modifier = Modifier.fillMaxSize(),
        horizontalArrangement = Arrangement.spacedBy(2.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        @OptIn(ExperimentalFoundationApi::class)
        stickyHeader {  // ← 実験的な実装
            headerItem()
        }
        items(memberList) { item ->
            memberItem(item.imgId, item.name, item.group)
        }
    }

LazyRowのサンプル

スポンサーリンク

関数の引数

LayzyRowの状態(装飾、演出など)は、引数により指定できます。

@Composable
fun LazyRow(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),
    contentPadding: PaddingValues = PaddingValues(0.dp),
    reverseLayout: Boolean = false,
    horizontalArrangement: Arrangement.Horizontal =
        if (!reverseLayout) Arrangement.Start else Arrangement.End,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    content: LazyListScope.() -> Unit
) { ... }
引数概要
modifierModifierUI全般のCompose修飾子
stateLazyListStateスクロールの状態を監視・制御
contentPaddingPaddingValueコンテンツ(リスト)の周りの空白
reverseLayoutBooleanアイテムの並びを反転
 false:正転(上から下へ並べる)、デフォルト
 true:反転(下から上へ並べる)
horizontalArrangementArrangement.Horizontalコンテンツ(リスト)の配置、水平方向
※詳細は「配置パラメータ」を参照
※詳細は「リストの配置」を参照
verticalAlignmentAlignment.Verticalコンテンツ(リスト)の配置、垂直方向
※詳細は「配置パラメータ」を参照
※詳細は「リストの配置」を参照
flingBehaviorFlingBehaviorスクロールの動きを定義
userScrollEnabledBooleanジェスチャーによるスクロールの許可
 false:不許可
 true:許可、デフォルト
※ジェスチャー:画面のスワイプ、フリック
contentLazyListScope.() -> Unitコンテンツ(リスト)のスロット
・LazyListScope DSLが利用可能
・DSLコマンドでアイテムを並べて配置
配置パラメータ概要
AlignmentCenterVertical垂直方向の中央
Top上端
Bottom下端
ArrangementCenter水平方向の中央
Start左端
End右端
SpaceAround空きスペースの均一化
※詳細は「特殊な配置1」を参照
SpaceBetween
SpaceEvenly
SpaceByアイテム間のスペース(後述)
※詳細は「特殊な配置2」を参照
スポンサーリンク

関数の構成

LazyRow(横に並べる)はLazyList関数を呼び出す構成になっています。

LazyList関数はLazyListScope DSLを実行するエンジンです。コマンドに従ってアイテムを並べる処理(レイアウトフェーズで配置)を行います。

縦に並べる処理の原理も同じであるため、LazyColumn(縦に並べる)も同じエンジンを用いています。ただし、LazyColumnはフラグが異なります(isVertical = true)。

LazyColumnの構成(参考)LazyRowの構成
@Composable
fun LazyColumn(
    ...
    content: LazyListScope.() -> Unit
) {
    LazyList(
        modifier = modifier,
        state = state,
        contentPadding = contentPadding,
        flingBehavior = flingBehavior,
        horizontalAlignment = horizontalAlignment,
        verticalArrangement = verticalArrangement,
        isVertical = true,
        reverseLayout = reverseLayout,
        userScrollEnabled = userScrollEnabled,
        content = content
    )
}
@Composable
fun LazyRow(
    ...
    content: LazyListScope.() -> Unit
) {
    LazyList(
        modifier = modifier,
        state = state,
        contentPadding = contentPadding,
        verticalAlignment = verticalAlignment,
        horizontalArrangement = horizontalArrangement,
        isVertical = false,
        flingBehavior = flingBehavior,
        reverseLayout = reverseLayout,
        userScrollEnabled = userScrollEnabled,
        content = content
    )
}
スポンサーリンク

リストの実装

リストの実装は、「LazyListScope DSL」を用いて行います。

実装方法

LazyRow関数の最後の引数contentは、LazyListScopeレシーバーを持つスロットになっています。

ここにDSLコマンドを使って、アイテムの並びを記述します。

LazyRowの実装方法

「記述順=並び順」になるので、直感的に判り易いと思います。

LazyListScope DSL

表に挙げるDSLコマンドが用意されています。

コマンド概要
item( )標準関数単体のアイテムを追加
items(count: Int)カウント値のアイテムを追加
stickyHeader( )リストの先頭に固定されるヘッダーを追加
items(items: Array)拡張関数Arrayで列挙されたアイテムを追加
items(items: List)Listで列挙されたアイテムを追加
itemsIndexed(items: Array)Arrayで列挙されたIndex付きアイテムを追加
itemsIndexed(items: List)Listで列挙されたIndex付きアイテムを追加

拡張関数のitemsは最終的に標準関数のitemsに落とし込まれて処理されます。

inline fun <T> LazyListScope.items(
    items: List<T>,
    noinline key: ((item: T) -> Any)? = null,
    noinline contentType: (item: T) -> Any? = { null },
    crossinline itemContent: @Composable LazyItemScope.(item: T) -> Unit
) = items(
    count = items.size,
    key = if (key != null) { index: Int -> key(items[index]) } else null,
    contentType = { index: Int -> contentType(items[index]) }
) {
    itemContent(items[it])
}

※各DSLの使い方は「Compose LazyColumn:LazyListScope DSL」を参照

スポンサーリンク

リストの配置

「表示可能な範囲(LazyRowのサイズ)>リスト(コンテンツ)のサイズ」の時、verticalAlignmentとhorizontalArrangementを使って、リストの配置を指定できます。

図は代表して3箇所の配置を示しています。表示可能な箇所は全部で9カ所あります。

        LazyRow(
            modifier = Modifier.fillMaxSize(),
			// Vertical
            verticalAlignment = Alignment.Top,
        //    verticalAlignment = Alignment.CenterVertically,
        //    verticalAlignment = Alignment.Bottom,
			// Horizontal
            horizontalArrangement = Arrangement.Start
        //    horizontalArrangement = Arrangement.Center
        //    horizontalArrangement = Arrangement.End
        ) {
            items(3) {
                Box(
                    modifier = Modifier
                        .size(60.dp, 80.dp)
                        .background(_containerColor),
                    contentAlignment = Alignment.Center
                ) {
                    Text(text = "item %02d".format(it))
                }

            }
        }

リストの配置

スポンサーリンク

特殊は配置1(空きスペースの均一化)

アイテムを配置した時に生まれる空きスペースを均一化することが出来ます。

        LazyRow(
            modifier = Modifier.fillMaxSize(),
			// Vertical
            verticalAlignment = Alignment.Top,
         //   verticalAlignment = Alignment.CenterVertically,
         //   verticalAlignment = Alignment.Bottom,
			// Horizontal
            horizontalArrangement = Arrangement.SpaceAround
        //    horizontalArrangement = Arrangement.SpaceBetween
        //    horizontalArrangement = Arrangement.SpaceEvenly
        ) {
            items(3) {
                Box(
                    modifier = Modifier
                        .size(60.dp, 80.dp)
                        .background(_containerColor),
                    contentAlignment = Alignment.Center
                ) {
                    Text(text = "item %02d".format(it))
                }

            }
        }

空きスペースの均一化

スポンサーリンク

特殊な配置2(アイテム間のスペース)

隣り合うアイテム間にスペースを設けることが出来ます。

        LazyRow(
            modifier = Modifier.fillMaxSize(),
			// Vertical
            verticalAlignment = Alignment.Top,
        //    verticalAlignment = Alignment.CenterVertically,
        //    verticalAlignment = Alignment.Bottom,
			// Horizontal
            horizontalArrangement = Arrangement.spacedBy(2.dp)
        //    horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally)
        //    horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End)
        ) {
            items(3) {
                Box(
                    modifier = Modifier
                        .size(60.dp, 80.dp)
                        .background(_containerColor),
                    contentAlignment = Alignment.Center
                ) {
                    Text(text = "item %02d".format(it))
                }

            }
        }

アイテム間のスペース

スポンサーリンク

アイテムの並びを反転(reverseLayout)

reverseLayout引数は、アイテムの並びを反転させます。

【reverseLayout = false(デフォルト)】

reverseLayout = false
【reverseLayout = true】

reverseLayout = true

並びが反転するだけでなく、配置の開始も下からになります。

スポンサーリンク

スクロールの状態を監視・制御(state)

LazyListStateはスクロールの状態を監視・制御するクラスです。引数stateに指定します。

デフォルトはremenberLazyListState( )になっているので、監視・制御の必要がなければ、指定を省略できます。

LazyListStateのサンプル

以下は、リストの先頭へ移動するボタンを、スクロールの状況に合わせて表示・非表示するサンプルです。

        val _listState = rememberLazyListState()
        val _coroutineScope = rememberCoroutineScope()

        val _visible = remember {
            derivedStateOf { _listState.firstVisibleItemIndex > 1 }
			//               ↑↑ 先頭アイテムのインデックス ↑↑
        }

        LazyRow(state = _listState) {
            items(24) {
                ItemBox { Text(text = "item\n %02d ".format(it)) }
            }
        }

        AnimatedVisibility(  // ButtonのVisibilityをOn/Off
            modifier = Modifier.align(Alignment.BottomEnd).padding(10.dp),
            visible = _visible.value
        ) {
            Button(
                onClick = {
                    _coroutineScope.launch {
                        _listState.scrollToItem(index = 0)
					//  ↑↑  リストの先頭へスクロール  ↑↑
                    }
                }
            ) { Text(text = "Top") }
        }

LazyListState#firstVisibleItemIndexは先頭アイテムのインデックスです。このインデックスの大小を用いて、ボタンのVisibilityを切り替えています。

LazyListState#scrollToItem( )は指定したアイテムへスクロールで移動します。

スポンサーリンク

スクロールの動きを定義(flingBehavior)

FlingBehaviorはスクロールの動きを定義するクラスです。引数flingBehaviorに指定します。

デフォルトはScrollableDefaults.flingBehavior( )になっているので、変更の必要がなければ、指定を省略できます。

FlingBehaviorのサンプル

以下は、スクロールの停止位置を表示範囲の中心へスナップ(ぴったりと入る)させるサンプルです。

            val _listState = rememberLazyListState()
            val _flingBehavior = rememberSnapFlingBehavior(
                lazyListState = _listState
            )  // ↑↑ foundation 1.3.0で追加 ↑↑
            LazyRow(
                modifier = Modifier.fillMaxSize(),
                verticalAlignment = Alignment.CenterVertically,
                state = _listState,
                flingBehavior = _flingBehavior
            ) {
                items(100) {
                    ItemBox { Text(text = "item %02d".format(it)) }
                }
            }

ライブラリで提供される既成の動きは2つのみです。

ScrollableDefaults.flingBehavior( )は、フリングの強さに合わせてスクロール距離が変化する動きです(動画の上)。

rememberSnapFlingBehavior( )は、スクロールの停止位置をリストの中心へスナップさせます(動画の下)。

ちなみに、次期APIの「foundation 1.7.0」は、スナップする停止位置を表示範囲の先頭(Start)もしくは末尾(End)にできます。

            val _listState = rememberLazyListState()
            val _flingBehavior = rememberSnapFlingBehavior(
                lazyListState = _listState,
//                snapPosition = SnapPosition.Start
//                snapPosition = SnapPosition.Center // デフォルト
                snapPosition = SnapPosition.End
            )  // ↑↑ foundation 1.7.0で追加 ↑↑
            LazyRow(
                modifier = Modifier.fillMaxSize(),
                verticalAlignment = Alignment.CenterVertically,
                state = _listState,
                flingBehavior = _flingBehavior
            ) {
                items(100) {
                    ItemBox { Text(text = "item %02d".format(it)) }
                }
            }
スポンサーリンク

関連記事:

Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSurfaceについて、構成や使用方法などをまとめます。 ※環境:Android Studio Flamingo | 2022.2.1    :androidx.compose.material3:material3:1.1.1    :androidx.compose.ui:ui:1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のRadioButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中にUI要素を格納する機能をもつコンテナ型のUIがあります。 Column/Row/Boxがコンテナ型のUIです。構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 1     Kotlin 1.8.10     Compose Compiler 1.4.3 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のImageについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のDividerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSpacerについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation 1.5.0 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSliderについて、構成や使用方法などをまとめます。 ※環境:Android Studio Hedgehog | 2023.1.1 Patch 2     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のScaffoldについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のTopAppBarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のBottomAppBarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のFloatingActionButtonについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のSnackbarについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.material3:material3 1.1.1 ...
Jetpack composeは、アプリ開発に必要な一通りのUIコンポーネントをライブラリで提供しています。 そのライブラリ中のLazyColumnについて、構成や使用方法などをまとめます。 ※環境:Android Studio Koala | 2024.1.1     Kotlin 1.9.0     Compose Compiler 1.5.1     androidx.compose.foundation:foundation 1.6.8 ...
スポンサーリンク