{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

LazyGridState

public final class LazyGridState implements ScrollableState


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

In most cases, this will be created via rememberLazyGridState.

Summary

Nested types

public static class LazyGridState.Companion

Public constructors

LazyGridState(
    int firstVisibleItemIndex,
    int firstVisibleItemScrollOffset
)

Public methods

final void
animateScrollToItem(int index, int scrollOffset)

Animate (smooth scroll) to the given item.

float
dispatchRawDelta(float delta)

Dispatch scroll delta in pixels avoiding all scroll related mechanisms.

boolean

Whether this ScrollableState can scroll backward (consume a negative delta).

boolean

Whether this ScrollableState can scroll forward (consume a positive delta).

final int

The index of the first item that is visible.

final int

The scroll offset of the first visible item.

final @NonNull InteractionSource

InteractionSource that will be used to dispatch drag events when this grid is being dragged.

final @NonNull LazyGridLayoutInfo

The object of LazyGridLayoutInfo calculated during the last layout pass.

boolean

Whether this ScrollableState is currently scrolling by gesture, fling or programmatically or not.

void
scroll(
    @NonNull MutatePriority scrollPriority,
    @ExtensionFunctionType @NonNull SuspendFunction1<@NonNull ScrollScopeUnit> block
)

Call this function to take control of scrolling and gain the ability to send scroll events via ScrollScope.scrollBy.

final void
scrollToItem(int index, int scrollOffset)

Instantly brings the item at index to the top of the viewport, offset by scrollOffset pixels.

Public constructors

LazyGridState

public LazyGridState(
    int firstVisibleItemIndex,
    int firstVisibleItemScrollOffset
)
Parameters
int firstVisibleItemIndex

the initial value for LazyGridState.firstVisibleItemIndex

int firstVisibleItemScrollOffset

the initial value for LazyGridState.firstVisibleItemScrollOffset

Public methods

animateScrollToItem

public final void animateScrollToItem(int index, int scrollOffset)

Animate (smooth scroll) to the given item.

Parameters
int index

the index to which to scroll. Must be non-negative.

int 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).

dispatchRawDelta

public float dispatchRawDelta(float delta)

Dispatch scroll delta in pixels avoiding all scroll related mechanisms.

NOTE: unlike scroll, dispatching any delta with this method won't trigger nested scroll, won't stop ongoing scroll/drag animation and will bypass scrolling of any priority. This method will also ignore reverseDirection and other parameters set in scrollable.

This method is used internally for nested scrolling dispatch and other low level operations, allowing implementers of ScrollableState influence the consumption as suits them. Manually dispatching delta via this method will likely result in a bad user experience, you must prefer scroll method over this one.

Parameters
float delta

amount of scroll dispatched in the nested scroll process

Returns
float

the amount of delta consumed

getCanScrollBackward

public boolean getCanScrollBackward()

Whether this ScrollableState can scroll backward (consume a negative delta). This is typically false if the scroll position is equal to its minimum value, and true otherwise.

Note that true here does not imply that delta will be consumed - the ScrollableState may decide not to handle the incoming delta (such as if it is already being scrolled separately). Additionally, for backwards compatibility with previous versions of ScrollableState this value defaults to true.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer

val state = rememberLazyListState()
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
    Icon(
        Icons.Filled.KeyboardArrowUp,
        null,
        Modifier.graphicsLayer {
            // Hide the icon if we cannot scroll backward (we are the start of the list)
            // We use graphicsLayer here to control the alpha so that we only redraw when this
            // value changes, instead of recomposing
            alpha = if (state.canScrollBackward) 1f else 0f
        },
        Color.Red
    )
    val items = (1..100).toList()
    LazyColumn(
        Modifier
            .weight(1f)
            .fillMaxWidth(), state
    ) {
        items(items) {
            Text("Item is $it")
        }
    }
    Icon(
        Icons.Filled.KeyboardArrowDown,
        null,
        Modifier.graphicsLayer {
            // Hide the icon if we cannot scroll forward (we are the end of the list)
            // We use graphicsLayer here to control the alpha so that we only redraw when this
            // value changes, instead of recomposing
            alpha = if (state.canScrollForward) 1f else 0f
        },
        Color.Red
    )
}

getCanScrollForward

public boolean getCanScrollForward()

Whether this ScrollableState can scroll forward (consume a positive delta). This is typically false if the scroll position is equal to its maximum value, and true otherwise.

Note that true here does not imply that delta will be consumed - the ScrollableState may decide not to handle the incoming delta (such as if it is already being scrolled separately). Additionally, for backwards compatibility with previous versions of ScrollableState this value defaults to true.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer

val state = rememberLazyListState()
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
    Icon(
        Icons.Filled.KeyboardArrowUp,
        null,
        Modifier.graphicsLayer {
            // Hide the icon if we cannot scroll backward (we are the start of the list)
            // We use graphicsLayer here to control the alpha so that we only redraw when this
            // value changes, instead of recomposing
            alpha = if (state.canScrollBackward) 1f else 0f
        },
        Color.Red
    )
    val items = (1..100).toList()
    LazyColumn(
        Modifier
            .weight(1f)
            .fillMaxWidth(), state
    ) {
        items(items) {
            Text("Item is $it")
        }
    }
    Icon(
        Icons.Filled.KeyboardArrowDown,
        null,
        Modifier.graphicsLayer {
            // Hide the icon if we cannot scroll forward (we are the end of the list)
            // We use graphicsLayer here to control the alpha so that we only redraw when this
            // value changes, instead of recomposing
            alpha = if (state.canScrollForward) 1f else 0f
        },
        Color.Red
    )
}

getFirstVisibleItemIndex

public final int getFirstVisibleItemIndex()

The index of the first item that is visible.

Note that this property is observable and if you use it in the composable function it will be recomposed on every change causing potential performance issues.

If you want to run some side effects like sending an analytics event or updating a state based on this value consider using "snapshotFlow":

import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow

val gridState = rememberLazyGridState()
LaunchedEffect(gridState) {
    snapshotFlow { gridState.firstVisibleItemIndex }
        .collect {
            // use the new index
        }
}

If you need to use it in the composition then consider wrapping the calculation into a derived state in order to only have recompositions when the derived value changes:

import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember

val gridState = rememberLazyGridState()
val isAtTop by remember {
    derivedStateOf {
        gridState.firstVisibleItemIndex == 0 && gridState.firstVisibleItemScrollOffset == 0
    }
}
if (!isAtTop) {
    ScrollToTopButton(gridState)
}

getFirstVisibleItemScrollOffset

public final int getFirstVisibleItemScrollOffset()

The scroll offset of the first visible item. Scrolling forward is positive - i.e., the amount that the item is offset backwards

getInteractionSource

public final @NonNull InteractionSource getInteractionSource()

InteractionSource that will be used to dispatch drag events when this grid is being dragged. If you want to know whether the fling (or animated scroll) is in progress, use isScrollInProgress.

getLayoutInfo

public final @NonNull LazyGridLayoutInfo getLayoutInfo()

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

Note that this property is observable and is updated after every scroll or remeasure. If you use it in the composable function it will be recomposed on every change causing potential performance issues including infinity recomposition loop. Therefore, avoid using it in the composition.

If you want to run some side effects like sending an analytics event or updating a state based on this value consider using "snapshotFlow":

import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow

val gridState = rememberLazyGridState()
LaunchedEffect(gridState) {
    snapshotFlow { gridState.layoutInfo.totalItemsCount }
        .collect {
            // use the new items count
        }
}

isScrollInProgress

public boolean isScrollInProgress()

Whether this ScrollableState is currently scrolling by gesture, fling or programmatically or not.

scroll

public void scroll(
    @NonNull MutatePriority scrollPriority,
    @ExtensionFunctionType @NonNull SuspendFunction1<@NonNull ScrollScopeUnit> block
)

Call this function to take control of scrolling and gain the ability to send scroll events via ScrollScope.scrollBy. All actions that change the logical scroll position must be performed within a scroll block (even if they don't call any other methods on this object) in order to guarantee that mutual exclusion is enforced.

If scroll is called from elsewhere, this will be canceled.

scrollToItem

public final void scrollToItem(int index, int scrollOffset)

Instantly brings the item at index to the top of the viewport, offset by scrollOffset pixels.

Parameters
int index

the index to which to scroll. Must be non-negative.

int 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).