🌈 Create new beautiful Compose Gradients with our new wesite ->
Class

ScalingLazyListState

A state object that can be hoisted to control and observe scrolling.

Source set: Android
@Deprecated(
    "Was moved to androidx.wear.compose.foundation.lazy package. " + "Please use it instead"
)
public class ScalingLazyListState constructor(
    private var initialCenterItemIndex: Int = 1,
    private var initialCenterItemScrollOffset: Int = 0,
) : ScrollableState

A state object that can be hoisted to control and observe scrolling.

In most cases, this will be created via rememberScalingLazyListState.

If the developer wants custom control over position and spacing they can switch off autoCentering and provide contentPadding.

Note that it is not always possible for the values provided by initialCenterItemIndex and initialCenterItemScrollOffset to be honored, e.g. If initialCenterItemIndex is set to a value larger than the number of items initially in the list, or to an index that can not be placed in the middle of the screen due to the contentPadding or autoCentering properties provided to the ScalingLazyColumn. After the ScalingLazyColumn is initially drawn the actual values for the centerItemIndex and centerItemScrollOffset can be read from the state.

Parameters

initialCenterItemIndex the initial value for ScalingLazyListState.centerItemIndex, defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and the first item (index == 0) before it.
initialCenterItemScrollOffset the initial value for ScalingLazyListState.centerItemScrollOffset

Properties

centerItemIndex

Source set: Android
public val centerItemIndex: Int

The index of the item positioned closest to the viewport center

centerItemScrollOffset

Source set: Android
public val centerItemScrollOffset: Int

The offset of the item closest to the viewport center. Depending on the ScalingLazyListAnchorType of the ScalingLazyColumn the offset will be relative to either the items Edge or Center.

A positive value indicates that the center item's anchor point is above the viewport center-line, a negative value indicates that the center item anchor point is below the viewport center-line.

layoutInfo

Source set: Android
public val layoutInfo: ScalingLazyListLayoutInfo by derivedStateOf {
        if (
            extraPaddingPx.value == null ||
                scalingParams.value == null ||
                gapBetweenItemsPx.value == null ||
                viewportHeightPx.value == null ||
                anchorType.value == null ||
                reverseLayout.value == null ||
                beforeContentPaddingPx.value == null
        ) {
            EmptyScalingLazyListLayoutInfo
        } else {
            val visibleItemsInfo = mutableListOf<ScalingLazyListItemInfo>()
            val viewportHeightPx = viewportHeightPx.value!!
            var newCenterItemIndex = 0
            var newCenterItemScrollOffset = 0
            val visible = initialized.value || localInspectionMode.value

            // The verticalAdjustment is used to allow for the extraPadding that the
            // ScalingLazyColumn employs to ensure that there are sufficient list items composed
            // by the underlying LazyList even when there is extreme scaling being applied that
            // could result in additional list items be eligible to be drawn.
            // It is important to adjust for this extra space when working out the viewport
            // center-line based coordinate system of the ScalingLazyList.
            val verticalAdjustment =
                lazyListState.layoutInfo.viewportStartOffset + extraPaddingPx.value!!

            // Find the item in the middle of the viewport
            val centralItemArrayIndex = findItemNearestCenter(verticalAdjustment)
            if (centralItemArrayIndex != null) {
                val originalVisibleItemsInfo = lazyListState.layoutInfo.visibleItemsInfo
                val centralItem = originalVisibleItemsInfo[centralItemArrayIndex]

                // Place the center item
                val centerItemInfo: ScalingLazyListItemInfo =
                    calculateItemInfo(
                        centralItem.offset,
                        centralItem,
                        verticalAdjustment,
                        viewportHeightPx,
                        viewportCenterLinePx(),
                        scalingParams.value!!,
                        beforeContentPaddingPx.value!!,
                        anchorType.value!!,
                        autoCentering.value,
                        visible,
                    )
                visibleItemsInfo.add(centerItemInfo)

                newCenterItemIndex = centerItemInfo.index
                newCenterItemScrollOffset = -centerItemInfo.offset

                // Find the adjusted position of the central item in the coordinate system of the
                // underlying LazyColumn by adjusting for any scaling
                val centralItemAdjustedUnderlyingOffset =
                    centralItem.offset +
                        ((centerItemInfo.startOffset(anchorType.value!!) -
                                centerItemInfo.unadjustedStartOffset(anchorType.value!!)))
                            .roundToInt()

                // Go Up
                // nextItemBottomNoPadding uses the coordinate system of the underlying LazyList. It
                // keeps track of the top of the next potential list item that is a candidate to be
                // drawn in the viewport as we walk up the list items from the center. Going up
                // involved making offset smaller/negative as the coordinate system of the LazyList
                // starts at the top of the viewport. Note that the start of the lazy list
                // coordinates starts at '- start content padding in pixels' and goes beyond the
                // last visible list items to include the end content padding in pixels.

                // centralItem.offset is a startOffset in the coordinate system of the
                // underlying lazy list.
                var nextItemBottomNoPadding =
                    centralItemAdjustedUnderlyingOffset - gapBetweenItemsPx.value!!

                (centralItemArrayIndex - 1 downTo 0).forEach { ix ->
                    if (nextItemBottomNoPadding >= verticalAdjustment) {
                        val currentItem = lazyListState.layoutInfo.visibleItemsInfo[ix]
                        if (!discardAutoCenteringListItem(currentItem)) {
                            val itemInfo =
                                calculateItemInfo(
                                    nextItemBottomNoPadding - currentItem.size,
                                    currentItem,
                                    verticalAdjustment,
                                    viewportHeightPx,
                                    viewportCenterLinePx(),
                                    scalingParams.value!!,
                                    beforeContentPaddingPx.value!!,
                                    anchorType.value!!,
                                    autoCentering.value,
                                    visible,
                                )
                            visibleItemsInfo.add(0, itemInfo)
                            nextItemBottomNoPadding =
                                nextItemBottomNoPadding - itemInfo.size - gapBetweenItemsPx.value!!
                        }
                    } else {
                        return@forEach
                    }
                }

                // Go Down
                // nextItemTopNoPadding uses the coordinate system of the underlying LazyList. It
                // keeps track of the top of the next potential list item that is a candidate to be
                // drawn in the viewport as we walk down the list items from the center.
                var nextItemTopNoPadding =
                    centralItemAdjustedUnderlyingOffset +
                        centerItemInfo.size +
                        gapBetweenItemsPx.value!!

                (((centralItemArrayIndex + 1) until originalVisibleItemsInfo.size)).forEach { ix ->
                    if ((nextItemTopNoPadding - viewportHeightPx) <= verticalAdjustment) {
                        val currentItem = lazyListState.layoutInfo.visibleItemsInfo[ix]
                        if (!discardAutoCenteringListItem(currentItem)) {
                            val itemInfo =
                                calculateItemInfo(
                                    nextItemTopNoPadding,
                                    currentItem,
                                    verticalAdjustment,
                                    viewportHeightPx,
                                    viewportCenterLinePx(),
                                    scalingParams.value!!,
                                    beforeContentPaddingPx.value!!,
                                    anchorType.value!!,
                                    autoCentering.value,
                                    visible,
                                )

                            visibleItemsInfo.add(itemInfo)
                            nextItemTopNoPadding += itemInfo.size + gapBetweenItemsPx.value!!
                        }
                    } else {
                        return@forEach
                    }
                }
            }
            val totalItemsCount =
                if (autoCentering.value != null) {
                    (lazyListState.layoutInfo.totalItemsCount - 2).coerceAtLeast(0)
                } else {
                    lazyListState.layoutInfo.totalItemsCount
                }

            // Decide if we are ready for the 2nd stage of initialization
            // 1. We are not yet initialized and

            val readyForInitialScroll =
                if (!initialized.value) {
                    // 1. autoCentering is off or
                    // 2. The list has no items or
                    // 3. the before content autoCentering Spacer has been sized.
                    // NOTE: It is possible, if the first real item in the list is large, that the
                    // size
                    // of the Spacer is 0.
                    autoCentering.value == null ||
                        (lazyListState.layoutInfo.visibleItemsInfo.size >= 2 &&
                            (
                            // or Empty list (other than the 2 spacers)
                            lazyListState.layoutInfo.visibleItemsInfo.size == 2 ||
                                // or first item is correctly size
                                topSpacerIsCorrectlySized(
                                    lazyListState.layoutInfo.visibleItemsInfo,
                                    lazyListState.layoutInfo.totalItemsCount,
                                )))
                } else {
                    // We are already initialized and have an incomplete scroll to finish
                    incompleteScrollItem.value != null
                }

            DefaultScalingLazyListLayoutInfo(
                internalVisibleItemsInfo = visibleItemsInfo,
                totalItemsCount = totalItemsCount,
                viewportStartOffset =
                    lazyListState.layoutInfo.viewportStartOffset + extraPaddingPx.value!!,
                viewportEndOffset =
                    lazyListState.layoutInfo.viewportEndOffset - extraPaddingPx.value!!,
                centerItemIndex = if (initialized.value) newCenterItemIndex else 0,
                centerItemScrollOffset = if (initialized.value) newCenterItemScrollOffset else 0,
                reverseLayout = reverseLayout.value!!,
                orientation = lazyListState.layoutInfo.orientation,
                viewportSize =
                    IntSize(
                        width = lazyListState.layoutInfo.viewportSize.width,
                        height =
                            lazyListState.layoutInfo.viewportSize.height -
                                extraPaddingPx.value!! * 2,
                    ),
                beforeContentPadding = beforeContentPaddingPx.value!!,
                afterContentPadding = afterContentPaddingPx.value!!,
                beforeAutoCenteringPadding =
                    calculateTopAutoCenteringPaddingPx(visibleItemsInfo, totalItemsCount),
                afterAutoCenteringPadding =
                    calculateBottomAutoCenteringPaddingPx(visibleItemsInfo, totalItemsCount),
                readyForInitialScroll = readyForInitialScroll,
                initialized = initialized.value,
            )
        }
    }

The object of ScalingLazyListLayoutInfo calculated during the last layout pass. For example, you can use it to calculate what items are currently visible.

isScrollInProgress

Source set: Android
override val isScrollInProgress: Boolean

canScrollForward

Source set: Android
override val canScrollForward: Boolean

canScrollBackward

Source set: Android
override val canScrollBackward: Boolean

Functions

dispatchRawDelta

Source set: Android
override fun dispatchRawDelta(delta: Float): Float

scroll

Source set: Android
override suspend fun scroll(
        scrollPriority: MutatePriority,
        block: suspend ScrollScope.() -> Unit,
    )

scrollToItem

Source set: Android
public suspend fun scrollToItem(
        /*@IntRange(from = 0)*/
        index: Int,
        /*@IntRange(from = 0)*/
        scrollOffset: Int = 0,
    )

Instantly brings the item at index to the center of the viewport and positions it based on the anchorType and applies the scrollOffset pixels.

Parameters

index the index to which to scroll. Must be non-negative.
scrollOffset the offset that the item should end up after the scroll. Note that positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will scroll the item further upward (taking it partly offscreen).

animateScrollToItem

Source set: Android
public suspend fun animateScrollToItem(
        /*@IntRange(from = 0)*/
        index: Int,
        /*@IntRange(from = 0)*/
        scrollOffset: Int = 0,
    )

Animate (smooth scroll) the given item at index to the center of the viewport and position it based on the anchorType and applies the scrollOffset pixels.

Parameters

index the index to which to scroll. Must be non-negative.
scrollOffset the offset that the item should end up after the scroll (same as scrollToItem) - note that positive offset refers to forward scroll, so in a top-to-bottom list, positive offset will scroll the item further upward (taking it partly offscreen)

Members

Companion

Source set: Android
public companion object

Properties

Saver

Source set: Android
public val Saver: Saver<ScalingLazyListState, Any> =
            listSaver<ScalingLazyListState, Int>(
                save = { listOf(it.centerItemIndex, it.centerItemScrollOffset) },
                restore = {
                    val scalingLazyColumnState = ScalingLazyListState(it[0], it[1])
                    scalingLazyColumnState
                },
            )

The default Saver implementation for ScalingLazyListState.