🚀

LazyColumnによるスクロール位置などの取得方法とRecylerViewとのマッピング表

2022/06/10に公開

概要

RecylerViewでのスクロール位置、
たとえば、LinearLayoutManager#findLastVisibleItemPosition()のような画面上に表示されている最後のアイテムの位置(index)など色々あると思いますが、Jetpack Composeではどう取得するかのマッピング表です。

表示されているリストアイテムの最後のindex

RecylerViewの場合

val manager = recylerView.layoutManager
if (manager is LinearLayoutManager) {
    manager.findLastVisibleItemPosition() // これ
}

LazyColumの場合

val listState = rememberLazyListState()
LazyColumn(
  state = listState
) {
・・・
}
・・・
listState.layoutInfo.visibleItemsInfo.last().index // これ

リストの指定したindexにあるViewの高さやViewの上部のピクセル値

RecylerViewの場合

val itemView = recyclerView.layoutManager?.findViewByPosition(index) ?:return
val itemHeight = itemView.height // 指定のviewの高さ
val itemTop = itemView.top // 指定のViewの上部のピクセル位置

LazyColumの場合

val itemHeight = listState.layoutInfo.visibleItemsInfo[index].size // 指定のviewの高さ
val itemTop = listState.layoutInfo.visibleItemsInfo[index].offset // 指定のViewの上部のピクセル位置

一覧の表示領域の高さ

RecylerViewの場合

val visibleListHeight = recyclerView.height

LazyColumの場合

val visibleListHeight = listState.layoutInfo.viewportSize.height

表示されていない部分も含む一覧の数

RecylerViewの場合

val totalCount = recylerView.adapter?.itemCount ?: 0

LazyColumの場合

val totalCount = listState.layoutInfo.totalItemsCount

表示されている一覧の数

RecylerViewの場合

val visibleCount = recylerView.childCount

LazyColumの場合

val visibleCount = listState.layoutInfo.visibleItemsInfo.size

その他

上記があればほとんどの要件に足りる気がしますので、LazyColumのインターフェイスを雑にそのまま貼っておきます。

(次回は、LazyColumnのスクロール時に上記の値を使い、一定の条件の時だけログを送信するサンプルを書きたいと思います。)

listState.layoutInfo

/**
 * Contains useful information about the currently displayed layout state of lazy lists like
 * [LazyColumn] or [LazyRow]. For example you can get the list of currently displayed item.
 *
 * Use [LazyListState.layoutInfo] to retrieve this
 */
interface LazyListLayoutInfo {
    /**
     * The list of [LazyListItemInfo] representing all the currently visible items.
     */
    val visibleItemsInfo: List<LazyListItemInfo>

    /**
     * The start offset of the layout's viewport in pixels. You can think of it as a minimum offset
     * which would be visible. Usually it is 0, but it can be negative if non-zero [beforeContentPadding]
     * was applied as the content displayed in the content padding area is still visible.
     *
     * You can use it to understand what items from [visibleItemsInfo] are fully visible.
     */
    val viewportStartOffset: Int

    /**
     * The end offset of the layout's viewport in pixels. You can think of it as a maximum offset
     * which would be visible. It is the size of the lazy list layout minus [beforeContentPadding].
     *
     * You can use it to understand what items from [visibleItemsInfo] are fully visible.
     */
    val viewportEndOffset: Int

    /**
     * The total count of items passed to [LazyColumn] or [LazyRow].
     */
    val totalItemsCount: Int

    /**
     * The size of the viewport in pixels. It is the lazy list layout size including all the
     * content paddings.
     */
    val viewportSize: IntSize get() = IntSize.Zero

    /**
     * The orientation of the lazy list.
     */
    val orientation: Orientation get() = Orientation.Vertical

    /**
     * True if the direction of scrolling and layout is reversed.
     */
    val reverseLayout: Boolean get() = false

    /**
     * The content padding in pixels applied before the first item in the direction of scrolling.
     * For example it is a top content padding for LazyColumn with reverseLayout set to false.
     */
    val beforeContentPadding: Int get() = 0

    /**
     * The content padding in pixels applied after the last item in the direction of scrolling.
     * For example it is a bottom content padding for LazyColumn with reverseLayout set to false.
     */
    val afterContentPadding: Int get() = 0
}

listState.layoutInfo.visibleItemsInfo[index]


/**
 * Contains useful information about an individual item in lazy lists like [LazyColumn]
 *  or [LazyRow].
 *
 * @see LazyListLayoutInfo
 */
interface LazyListItemInfo {
    /**
     * The index of the item in the list.
     */
    val index: Int

    /**
     * The key of the item which was passed to the item() or items() function.
     */
    val key: Any

    /**
     * The main axis offset of the item in pixels. It is relative to the start of the lazy list container.
     */
    val offset: Int

    /**
     * The main axis size of the item in pixels. Note that if you emit multiple layouts in the composable
     * slot for the item then this size will be calculated as the sum of their sizes.
     */
    val size: Int
}
NewsPicks の Zenn

Discussion