Scorri

Modificatori di scorrimento

I modificatori verticalScroll e horizontalScroll offrono il modo più semplice per consentire all'utente di scorrere un elemento quando i limiti dei relativi contenuti sono superiori ai vincoli di dimensioni massime. Con i modificatori verticalScroll e horizontalScroll non è necessario tradurre o compensare i contenuti.

@Composable
private fun ScrollBoxes() {
    Column(
        modifier = Modifier
            .background(Color.LightGray)
            .size(100.dp)
            .verticalScroll(rememberScrollState())
    ) {
        repeat(10) {
            Text("Item $it", modifier = Modifier.padding(2.dp))
        }
    }
}

Un semplice elenco verticale che risponde ai gesti di scorrimento

ScrollState consente di modificare la posizione di scorrimento o di recuperarne lo stato corrente. Per crearlo con i parametri predefiniti, utilizza rememberScrollState().

@Composable
private fun ScrollBoxesSmooth() {
    // Smoothly scroll 100px on first composition
    val state = rememberScrollState()
    LaunchedEffect(Unit) { state.animateScrollTo(100) }

    Column(
        modifier = Modifier
            .background(Color.LightGray)
            .size(100.dp)
            .padding(horizontal = 8.dp)
            .verticalScroll(state)
    ) {
        repeat(10) {
            Text("Item $it", modifier = Modifier.padding(2.dp))
        }
    }
}

Modificatore scorrevole

Il modificatore scrollable è diverso dai modificatori di scorrimento in quanto scrollable rileva i gesti di scorrimento e acquisisce i delta, ma non compensa automaticamente i contenuti. Questa operazione viene invece delegata all'utente tramite ScrollableState , che è necessaria per il corretto funzionamento di questo modificatore.

Quando crei ScrollableState, devi fornire una funzione consumeScrollDelta che verrà invocata a ogni passaggio di scorrimento (tramite input di gesti, scorrimento scorrevole o scorrimento rapido) con il delta in pixel. Questa funzione deve restituire la distanza di scorrimento utilizzata per assicurarsi che l'evento venga propagato correttamente nei casi in cui sono presenti elementi nidificati con il modificatore scrollable.

Lo snippet seguente rileva i gesti e mostra un valore numerico per un offset, ma non compensa alcun elemento:

@Composable
private fun ScrollableSample() {
    // actual composable state
    var offset by remember { mutableStateOf(0f) }
    Box(
        Modifier
            .size(150.dp)
            .scrollable(
                orientation = Orientation.Vertical,
                // Scrollable state: describes how to consume
                // scrolling delta and update offset
                state = rememberScrollableState { delta ->
                    offset += delta
                    delta
                }
            )
            .background(Color.LightGray),
        contentAlignment = Alignment.Center
    ) {
        Text(offset.toString())
    }
}

Un elemento dell'interfaccia utente che rileva la pressione del dito e mostra il valore numerico per la posizione del dito

Scorrimento nidificato

Lo scorrimento nidificato è un sistema in cui più componenti di scorrimento contenuti uno all'interno dell'altro lavorano insieme reagendo a un singolo gesto di scorrimento e comunicando i relativi delta (modifiche).

Il sistema di scorrimento nidificato consente la coordinazione tra componenti scorrevoli e collegati in modo gerarchico (spesso condividendo lo stesso elemento principale). Questo sistema collega i contenitori con scorrimento e consente l'interazione con le differenze di scorrimento che vengono propagate e condivise tra i contenitori.

Compose offre più modi per gestire lo scorrimento nidificato tra i composable. Un tipico esempio di scorrimento nidificato è un elenco all'interno di un altro elenco, mentre un caso più complesso è una barra degli strumenti comprimibile.

Scorrimento nidificato automatico

Lo scorrimento nidificato semplice non richiede alcuna azione da parte tua. I gesti che avviano un'azione di scorrimento vengono propagati automaticamente dagli elementi secondari a quelli principali, in modo che, quando l'elemento secondario non può più scorrere, il gesto venga gestito dall'elemento principale.

Lo scorrimento nidificato automatico è supportato e fornito immediatamente da alcuni dei componenti e dei modificatori di Compose: verticalScroll, horizontalScroll, scrollable, API Lazy e TextField. Ciò significa che quando l'utente scorre un elemento figlio interno di componenti nidificati, i modificatori precedenti propagano i delta di scorrimento ai componenti principali che supportano lo scorrimento nidificato.

L'esempio seguente mostra elementi a cui è stato applicato un modificatore verticalScroll all'interno di un contenitore a cui è stato applicato anche un modificatore verticalScroll.

@Composable
private fun AutomaticNestedScroll() {
    val gradient = Brush.verticalGradient(0f to Color.Gray, 1000f to Color.White)
    Box(
        modifier = Modifier
            .background(Color.LightGray)
            .verticalScroll(rememberScrollState())
            .padding(32.dp)
    ) {
        Column {
            repeat(6) {
                Box(
                    modifier = Modifier
                        .height(128.dp)
                        .verticalScroll(rememberScrollState())
                ) {
                    Text(
                        "Scroll here",
                        modifier = Modifier
                            .border(12.dp, Color.DarkGray)
                            .background(brush = gradient)
                            .padding(24.dp)
                            .height(150.dp)
                    )
                }
            }
        }
    }
}

Due elementi dell'interfaccia utente con scorrimento verticale nidificati, che rispondono ai gesti all'interno e all'esterno dell'elemento interno

Utilizzo del modificatore nestedScroll

Se devi creare uno scorrimento coordinato avanzato tra più elementi, il modificatore nestedScroll ti offre maggiore flessibilità definendo una gerarchia di scorrimento nidificata. Come accennato nella sezione precedente, alcuni componenti supportano la funzionalità di scorrimento nidificato integrata. Tuttavia, per i composabili che non sono scorrevoli automaticamente, come Box o Column, i delta di scorrimento su questi componenti non verranno propagati nel sistema di scorrimento nidificato e i delta non raggiungeranno NestedScrollConnection né il componente principale. Per risolvere il problema, puoi utilizzare nestedScroll per estendere questo supporto ad altri componenti, inclusi quelli personalizzati.

Ciclo di scorrimento nidificato

Il ciclo di scorrimento nidificato è il flusso di delta di scorrimento che vengono inviati verso l'alto e verso il basso nella struttura ad albero della gerarchia attraverso tutti i componenti (o nodi) che fanno parte del sistema di scorrimento nidificato, ad esempio utilizzando componenti e modificatori scorrevoli o nestedScroll.

Fasi del ciclo di scorrimento nidificato

Quando un evento di attivazione (ad esempio un gesto) viene rilevato da un componente scorrevole, prima che venga attivata l'azione di scorrimento effettiva, i delta generati vengono inviati al sistema di scorrimento nidificato e attraversano tre fasi: pre-scorrimento, utilizzo dei nodi e post-scorrimento.

Fasi del

ciclo di scorrimento nidificato

Nella prima fase, precedente allo scorrimento, il componente che ha ricevuto i delta degli eventi di attivazione invierà questi eventi verso l'elemento principale più alto tramite l'albero della gerarchia. Gli eventi delta verranno quindi trasmessi verso il basso, il che significa che i delta verranno propagati dall'elemento principale più vicino alla radice verso l'elemento secondario che ha avviato il ciclo di scorrimento nidificato.

Fase di pre-scorrimento - invio
in alto

In questo modo, i componenti principali con scorrimento nidificati (composabili che utilizzano nestedScroll o modi di scorrimento) hanno la possibilità di fare qualcosa con il delta prima che il nodo stesso possa utilizzarlo.

Fase precedente allo scorrimento: risalita
in su

Nella fase di consumo del nodo, il nodo stesso utilizzerà il delta non utilizzato dai nodi principali. Questo è il momento in cui il movimento di scorrimento è effettivamente completato ed è visibile.

Fase di consumo del nodo

Durante questa fase, il bambino può scegliere di consumare tutto o parte dello scorrimento rimanente. Gli elementi rimanenti verranno inviati di nuovo per essere sottoposti alla fase successiva allo scorrimento.

Infine, nella fase post-scorrimento, tutto ciò che il nodo stesso non ha consumato verrà inviato di nuovo ai suoi antenati per il consumo.

Fase post-scorrimento: invio
in alto

La fase post-scorrimento funziona in modo simile alla fase pre-scorrimento, in cui qualsiasi annuncio principale può scegliere di essere visualizzato o meno.

Fase post-scorrimento: risalita
in modo ricorsivo

Analogamente allo scorrimento, al termine di un gesto di trascinamento, l'intenzione dell'utente può essere tradotta in una velocità utilizzata per far scorrere (scorrere utilizzando un'animazione) il contenitore scorrevole. Anche il movimento brusco fa parte del ciclo di scorrimento nidificato e le velocità generate dall'evento di trascinamento attraversano fasi simili: pre-movimento brusco, utilizzo del nodo e post-movimento brusco. Tieni presente che l'animazione con movimento brusco è associata solo al gesto tocco e non verrà attivata da altri eventi, come a11y o scorrimento hardware.

Partecipare al ciclo di scorrimento nidificato

La partecipazione al ciclo significa intercettare, consumare e segnalare il consumo dei delta lungo la gerarchia. Compose fornisce un insieme di strumenti per influenzare il funzionamento del sistema di scorrimento nidificato e per interagire direttamente con esso, ad esempio quando devi fare qualcosa con i delta di scorrimento prima che un componente scorrevole inizi a scorrere.

Se il ciclo di scorrimento nidificato è un sistema che agisce su una catena di nodi, il modificatore nestedScroll è un modo per intercettare e inserire queste modifiche e influire sui dati (delta di scorrimento) che vengono propagati nella catena. Questo modificatore può essere inserito in qualsiasi punto della gerarchia e comunica con le istanze di modificatore di scorrimento nidificate nell'albero per poter condividere informazioni tramite questo canale. Gli elementi costitutivi di questo modificatore sono NestedScrollConnection e NestedScrollDispatcher.

NestedScrollConnection offre un modo per rispondere alle fasi del ciclo di scorrimento nidificato e influenzare il sistema di scorrimento nidificato. È composto da quattro metodi di callback, ciascuno rappresentante una delle fasi di consumo: pre/post-scorrimento e pre/post-lancio:

val nestedScrollConnection = object : NestedScrollConnection {
    override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
        println("Received onPreScroll callback.")
        return Offset.Zero
    }

    override fun onPostScroll(
        consumed: Offset,
        available: Offset,
        source: NestedScrollSource
    ): Offset {
        println("Received onPostScroll callback.")
        return Offset.Zero
    }
}

Ogni callback fornisce anche informazioni sul delta propagato: available delta per la fase in questione e consumed delta consumato nelle le fasi precedenti. Se in qualsiasi momento vuoi interrompere la propagazione dei delta nella gerarchia, puoi utilizzare la connessione di scorrimento nidificata:

val disabledNestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPostScroll(
            consumed: Offset,
            available: Offset,
            source: NestedScrollSource
        ): Offset {
            return if (source == NestedScrollSource.SideEffect) {
                available
            } else {
                Offset.Zero
            }
        }
    }
}

Tutti i call-back forniscono informazioni sul tipo NestedScrollSource.

NestedScrollDispatcher inizializza il ciclo di scorrimento nidificato. L'utilizzo di un gestore e la chiamata dei relativi metodi attivano il ciclo. I contenitori scorrevoli hanno un gestore integrato che invia al sistema le differenze acquisite durante i gesti. Per questo motivo, la maggior parte dei casi d'uso per la personalizzazione dello scorrimento nidificato prevede l'utilizzo di NestedScrollConnection anziché di un dispatcher, per reagire ai delta già esistenti anziché inviarne di nuovi. Per altri utilizzi, consulta NestedScrollDispatcherSample.

Ridimensionare un'immagine durante lo scorrimento

Mentre l'utente scorre, puoi creare un effetto visivo dinamico in cui l'immagine cambia dimensione in base alla posizione di scorrimento.

Ridimensionare un'immagine in base alla posizione di scorrimento

Questo snippet mostra come ridimensionare un'immagine all'interno di un LazyColumn in base alla posizione di scorrimento verticale. L'immagine si restringe quando l'utente scorre verso il basso e si espande quando scorre verso l'alto, rimanendo entro i limiti di dimensioni minime e massime definiti:

@Composable
fun ImageResizeOnScrollExample(
    modifier: Modifier = Modifier,
    maxImageSize: Dp = 300.dp,
    minImageSize: Dp = 100.dp
) {
    var currentImageSize by remember { mutableStateOf(maxImageSize) }
    var imageScale by remember { mutableFloatStateOf(1f) }

    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                // Calculate the change in image size based on scroll delta
                val delta = available.y
                val newImageSize = currentImageSize + delta.dp
                val previousImageSize = currentImageSize

                // Constrain the image size within the allowed bounds
                currentImageSize = newImageSize.coerceIn(minImageSize, maxImageSize)
                val consumed = currentImageSize - previousImageSize

                // Calculate the scale for the image
                imageScale = currentImageSize / maxImageSize

                // Return the consumed scroll amount
                return Offset(0f, consumed.value)
            }
        }
    }

    Box(Modifier.nestedScroll(nestedScrollConnection)) {
        LazyColumn(
            Modifier
                .fillMaxWidth()
                .padding(15.dp)
                .offset {
                    IntOffset(0, currentImageSize.roundToPx())
                }
        ) {
            // Placeholder list items
            items(100, key = { it }) {
                Text(
                    text = "Item: $it",
                    style = MaterialTheme.typography.bodyLarge
                )
            }
        }

        Image(
            painter = ColorPainter(Color.Red),
            contentDescription = "Red color image",
            Modifier
                .size(maxImageSize)
                .align(Alignment.TopCenter)
                .graphicsLayer {
                    scaleX = imageScale
                    scaleY = imageScale
                    // Center the image vertically as it scales
                    translationY = -(maxImageSize.toPx() - currentImageSize.toPx()) / 2f
                }
        )
    }
}

Punti chiave del codice

  • Questo codice utilizza un NestedScrollConnection per intercettare gli eventi di scorrimento.
  • onPreScroll calcola la variazione delle dimensioni dell'immagine in base alla variazione della scorrimento.
  • La variabile di stato currentImageSize memorizza le dimensioni correnti dell'immagine, costrette tra minImageSize e maxImageSize. imageScale, derivate da currentImageSize.
  • Gli offset LazyColumn in base al currentImageSize.
  • Image utilizza un modificatore graphicsLayer per applicare la scala calcolata.
  • Il translationY all'interno del graphicsLayer garantisce che l'immagine rimanga centrata verticalmente durante la scalatura.

Risultato

Lo snippet precedente genera un effetto di ridimensionamento delle immagini durante lo scorrimento:

Figura 1. Un effetto di ridimensionamento delle immagini durante lo scorrimento.

Interoperabilità di scorrimento nidificato

Quando provi ad nidificare elementi View scorrevoli in composabili scorrevoli o viceversa, potresti riscontrare problemi. I più evidenti si verificano quando scorri il componente figlio e raggiungi i relativi limiti di inizio o fine e prevedi che il componente principale assuma il controllo dello scorrimento. Tuttavia, questo comportamento previsto potrebbe non verificarsi o non funzionare come previsto.

Questo problema è dovuto alle aspettative incorporate nei componenti componibili scorrevoli. I composabili scorrevoli hanno una regola "scrolling-nidificato-per-impostazione-predefinita", il che significa che qualsiasi contenitore scorrevole deve partecipare alla catena di scorrimento nidificata, sia come elemento principale tramite NestedScrollConnection sia come elemento secondario tramite NestedScrollDispatcher. Il componente secondario attiverà quindi uno scorrimento nidificato per il componente principale quando si trova al confine. Ad esempio, questa regola consente a Componi Pager e Componi LazyRow di lavorare bene insieme. Tuttavia, quando viene eseguito lo scorrimento di interoperabilità con ViewPager2 o RecyclerView, poiché questi elementi non implementano NestedScrollingParent3, lo scorrimento continuo da un elemento secondario a quello principale non è possibile.

Per abilitare l'API di interoperabilità con scorrimento nidificato tra elementi View scorrevoli e composabili scorrevoli, nidificati in entrambe le direzioni, puoi utilizzare l'API di interoperabilità con scorrimento nidificato per attenuare questi problemi nei seguenti scenari.

Un account principale collaborativo View contenente un account secondario ComposeView

Un elemento principale collaborativo View è un elemento che implementa già NestedScrollingParent3 e quindi è in grado di ricevere delta di scorrimento da un composable figlio nidificato collaborativo. ComposeView in questo caso agirebbe come publisher secondario e dovrebbe implementare (indirettamente) NestedScrollingChild3. Un esempio di genitore collaborativo è androidx.coordinatorlayout.widget.CoordinatorLayout.

Se hai bisogno di interoperabilità di scorrimento nidificato tra contenitori principali View scorrevoli e composabili secondari scorrevoli nidificati, puoi utilizzare rememberNestedScrollInteropConnection().

rememberNestedScrollInteropConnection() consente e memorizza il valore NestedScrollConnection che consente l'interoperabilità dello scorrimento nidificato tra un elemento principale View che implementa NestedScrollingParent3 e un elemento secondario di composizione. Da utilizzare insieme a un modificatore nestedScroll. Poiché lo scorrimento nidificato è abilitato per impostazione predefinita lato Compose, puoi utilizzare questa connessione per attivare sia lo scorrimento nidificato lato View sia aggiungere la logica di collegamento necessaria tra View e i composabili.Views

Un caso d'uso frequente è l'utilizzo di CoordinatorLayout, CollapsingToolbarLayout e un composable secondario, mostrato in questo esempio:

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <!--...-->

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

Nell'attività o nel frammento, devi configurare il composable secondario e i NestedScrollConnection obbligatori:

open class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<ComposeView>(R.id.compose_view).apply {
            setContent {
                val nestedScrollInterop = rememberNestedScrollInteropConnection()
                // Add the nested scroll connection to your top level @Composable element
                // using the nestedScroll modifier.
                LazyColumn(modifier = Modifier.nestedScroll(nestedScrollInterop)) {
                    items(20) { item ->
                        Box(
                            modifier = Modifier
                                .padding(16.dp)
                                .height(56.dp)
                                .fillMaxWidth()
                                .background(Color.Gray),
                            contentAlignment = Alignment.Center
                        ) {
                            Text(item.toString())
                        }
                    }
                }
            }
        }
    }
}

Un composable principale contenente un AndroidView secondario

Questo scenario riguarda l'implementazione dell'API di interoperabilità di scorrimento nidificato lato Compose, quando hai un composable principale contenente un composable secondarioAndroidView. AndroidView implementa NestedScrollDispatcher, poiché funge da elemento secondario di un elemento principale di composizione scorrevole, nonché NestedScrollingParent3 , poiché funge da elemento principale di un elemento secondario scorrevole View. La composizione principale potrà quindi ricevere delta di scorrimento nidificati da un elemento secondario scorrevole nidificatoView.

L'esempio seguente mostra come ottenere l'interoperabilità con scorrimento nidificato in questo scenario, insieme a una barra degli strumenti comprimibile di Scrivi:

@Composable
private fun NestedScrollInteropComposeParentWithAndroidChildExample() {
    val toolbarHeightPx = with(LocalDensity.current) { ToolbarHeight.roundToPx().toFloat() }
    val toolbarOffsetHeightPx = remember { mutableStateOf(0f) }

    // Sets up the nested scroll connection between the Box composable parent
    // and the child AndroidView containing the RecyclerView
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                // Updates the toolbar offset based on the scroll to enable
                // collapsible behaviour
                val delta = available.y
                val newOffset = toolbarOffsetHeightPx.value + delta
                toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f)
                return Offset.Zero
            }
        }
    }

    Box(
        Modifier
            .fillMaxSize()
            .nestedScroll(nestedScrollConnection)
    ) {
        TopAppBar(
            modifier = Modifier
                .height(ToolbarHeight)
                .offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) }
        )

        AndroidView(
            { context ->
                LayoutInflater.from(context)
                    .inflate(R.layout.view_in_compose_nested_scroll_interop, null).apply {
                        with(findViewById<RecyclerView>(R.id.main_list)) {
                            layoutManager = LinearLayoutManager(context, VERTICAL, false)
                            adapter = NestedScrollInteropAdapter()
                        }
                    }.also {
                        // Nested scrolling interop is enabled when
                        // nested scroll is enabled for the root View
                        ViewCompat.setNestedScrollingEnabled(it, true)
                    }
            },
            // ...
        )
    }
}

private class NestedScrollInteropAdapter :
    Adapter<NestedScrollInteropAdapter.NestedScrollInteropViewHolder>() {
    val items = (1..10).map { it.toString() }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): NestedScrollInteropViewHolder {
        return NestedScrollInteropViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.list_item, parent, false)
        )
    }

    override fun onBindViewHolder(holder: NestedScrollInteropViewHolder, position: Int) {
        // ...
    }

    class NestedScrollInteropViewHolder(view: View) : ViewHolder(view) {
        fun bind(item: String) {
            // ...
        }
    }
    // ...
}

Questo esempio mostra come utilizzare l'API con un modificatore scrollable:

@Composable
fun ViewInComposeNestedScrollInteropExample() {
    Box(
        Modifier
            .fillMaxSize()
            .scrollable(rememberScrollableState {
                // View component deltas should be reflected in Compose
                // components that participate in nested scrolling
                it
            }, Orientation.Vertical)
    ) {
        AndroidView(
            { context ->
                LayoutInflater.from(context)
                    .inflate(android.R.layout.list_item, null)
                    .apply {
                        // Nested scrolling interop is enabled when
                        // nested scroll is enabled for the root View
                        ViewCompat.setNestedScrollingEnabled(this, true)
                    }
            }
        )
    }
}

Infine, questo esempio mostra come viene utilizzata l'API di interoperabilità di scorrimento nidificato con BottomSheetDialogFragment per ottenere un comportamento di trascinamento e chiusura efficace:

class BottomSheetFragment : BottomSheetDialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val rootView: View = inflater.inflate(R.layout.fragment_bottom_sheet, container, false)

        rootView.findViewById<ComposeView>(R.id.compose_view).apply {
            setContent {
                val nestedScrollInterop = rememberNestedScrollInteropConnection()
                LazyColumn(
                    Modifier
                        .nestedScroll(nestedScrollInterop)
                        .fillMaxSize()
                ) {
                    item {
                        Text(text = "Bottom sheet title")
                    }
                    items(10) {
                        Text(
                            text = "List item number $it",
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                }
            }
            return rootView
        }
    }
}

Tieni presente che rememberNestedScrollInteropConnection() installerà un NestedScrollConnection nell'elemento a cui lo colleghi. NestedScrollConnection è responsabile della trasmissione dei delta dal livello Componi al livello View. In questo modo, l'elemento può partecipare allo scorrimento nidificato, ma non attiva automaticamente lo scorrimento degli elementi. Per i composabili non scorrevoli automaticamente, come Box o Column, i delta di scorrimento su questi componenti non si propagheranno nel sistema di scorrimento nidificato e non raggiungeranno il NestedScrollConnection fornito da rememberNestedScrollInteropConnection(), pertanto non raggiungeranno il componente principale View. Per risolvere il problema, assicurati di impostare anche i modificatori scorrevoli su questi tipi di composabili nidificati. Per informazioni più dettagliate, consulta la sezione precedente sullo scorrimento nidificato.

Un account principale non collaborativo View contenente un account secondario ComposeView

Una visualizzazione non collaborativa è una visualizzazione che non implementa le interfacce NestedScrolling necessarie sul lato View. Tieni presente che questo significa che l'interoperabilità con lo scorrimento nidificato con questi Views non funziona subito. I Views non collaborativi sono RecyclerView e ViewPager2.