Modyfikatory przewijania
Modyfikatory
verticalScroll
i
horizontalScroll
to najprostszy sposób, aby umożliwić użytkownikowi przewijanie elementu, gdy jego zawartość jest większa niż maksymalne ograniczenia rozmiaru. W przypadku modyfikatorów verticalScroll i horizontalScroll nie musisz tłumaczyć ani przesuwać treści.
@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)) } } }
Element ScrollState umożliwia zmianę pozycji przewijania lub uzyskanie jej bieżącego stanu. Aby utworzyć go z parametrami domyślnymi, użyj 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)) } } }
Modyfikator przewijania
Modyfikator
scrollable
różni się od modyfikatorów przewijania tym, że scrollable wykrywa gesty przewijania i rejestruje zmiany, ale nie przesuwa automatycznie zawartości. Zamiast tego uprawnienia są delegowane na użytkownika za pomocą parametru
ScrollableState
, który jest wymagany do prawidłowego działania tego modyfikatora.
Podczas tworzenia funkcji ScrollableState musisz podać funkcję consumeScrollDelta, która będzie wywoływana przy każdym kroku przewijania (za pomocą gestu, płynnego przewijania lub szybkiego przewijania) z wartością delta w pikselach. Ta funkcja musi zwracać ilość przewiniętej odległości, aby zdarzenie było prawidłowo propagowane w przypadku zagnieżdżonych elementów, które mają modyfikator scrollable.
Poniższy fragment kodu wykrywa gesty i wyświetla wartość liczbową przesunięcia, ale nie przesuwa żadnych elementów:
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(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()) } }
Przewijanie zagnieżdżone
Zagnieżdżone przewijanie to system, w którym wiele komponentów przewijania zawartych w sobie nawzajem współpracuje ze sobą, reagując na jeden gest przewijania i przekazując sobie informacje o zmianach przewijania.
System zagnieżdżonego przewijania umożliwia koordynację między komponentami, które można przewijać i które są połączone hierarchicznie (najczęściej przez wspólny element nadrzędny). Ten system łączy kontenery przewijane i umożliwia interakcję z różnicami przewijania, które są propagowane i udostępniane między nimi.
Compose udostępnia kilka sposobów obsługi zagnieżdżonego przewijania między komponentami. Typowym przykładem zagnieżdżonego przewijania jest lista w innej liście, a bardziej złożonym przypadkiem jest zwijany pasek narzędzi.
Automatyczne zagnieżdżone przewijanie
Proste zagnieżdżone przewijanie nie wymaga żadnych działań z Twojej strony. Gesty, które inicjują przewijanie, są automatycznie przekazywane z elementów podrzędnych do nadrzędnych. Dzięki temu, gdy element podrzędny nie może już przewijać, gest jest obsługiwany przez element nadrzędny.
Automatyczne zagnieżdżone przewijanie jest obsługiwane i dostępne od razu w niektórych komponentach i modyfikatorach Compose: verticalScroll, horizontalScroll, scrollable, interfejsy API Lazy i TextField. Oznacza to, że gdy użytkownik przewija wewnętrzny element podrzędny zagnieżdżonych komponentów, poprzednie modyfikatory propagują delty przewijania do elementów nadrzędnych, które obsługują zagnieżdżone przewijanie.
Poniższy przykład przedstawia elementy z zastosowanym modyfikatorem
verticalScroll
w kontenerze, do którego również zastosowano modyfikator 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) ) } } } } }
Używanie modyfikatora nestedScroll
Jeśli chcesz utworzyć zaawansowane skoordynowane przewijanie między wieloma elementami, modyfikator nestedScroll
zapewni Ci większą elastyczność dzięki zdefiniowaniu zagnieżdżonej hierarchii przewijania. Jak wspomnieliśmy w poprzedniej sekcji, niektóre komponenty mają wbudowaną obsługę zagnieżdżonego przewijania. W przypadku komponentów kompozycyjnych, które nie są automatycznie przewijane, np. Box lub Column, delty przewijania w takich komponentach nie będą propagowane w zagnieżdżonym systemie przewijania i nie dotrą do komponentu NestedScrollConnection ani do komponentu nadrzędnego. Aby rozwiązać ten problem, możesz użyć nestedScroll, aby zapewnić obsługę innych komponentów, w tym komponentów niestandardowych.
Cykl zagnieżdżonego przewijania
Zagnieżdżony cykl przewijania to przepływ zmian przewijania, które są wysyłane w górę i w dół drzewa hierarchii przez wszystkie komponenty (lub węzły) należące do zagnieżdżonego systemu przewijania, np. za pomocą komponentów i modyfikatorów z możliwością przewijania lub nestedScroll.
Fazy cyklu zagnieżdżonego przewijania
Gdy komponent z możliwością przewijania wykryje zdarzenie wywołujące (np. gest), zanim jeszcze zostanie wywołana rzeczywista czynność przewijania, wygenerowane wartości delta są wysyłane do zagnieżdżonego systemu przewijania i przechodzą przez 3 fazy: przed przewijaniem, wykorzystanie węzła i po przewijaniu.
W pierwszej fazie przed przewinięciem komponent, który otrzymał zdarzenie wywołujące, będzie wysyłać te zdarzenia w górę drzewa hierarchii do najwyższego elementu nadrzędnego. Zdarzenia delta będą się wtedy rozprzestrzeniać w dół, co oznacza, że będą przekazywane od nadrzędnego elementu głównego do elementu podrzędnego, który rozpoczął zagnieżdżony cykl przewijania.
Dzięki temu zagnieżdżone elementy przewijane (kompozycje korzystające z modyfikatorów nestedScroll lub scrollable) mogą coś zrobić z wartością delta, zanim węzeł będzie mógł ją wykorzystać.
W fazie zużycia węzła sam węzeł wykorzysta wszystkie różnice, które nie zostały wykorzystane przez jego węzły nadrzędne. Wtedy następuje faktyczne przewijanie i jest ono widoczne.
W tym czasie dziecko może przewinąć pozostałą część strony lub tylko jej fragment. Pozostałe elementy zostaną przesłane z powrotem do góry, aby przejść fazę po przewinięciu.
W fazie po przewinięciu wszystko, czego węzeł nie wykorzystał, zostanie ponownie wysłane do jego elementów nadrzędnych.
Faza po przewinięciu działa podobnie jak faza przed przewinięciem, w której każdy z elementów nadrzędnych może zdecydować, czy chce wykorzystać zdarzenie, czy nie.
Podobnie jak w przypadku przewijania, po zakończeniu gestu przeciągnięcia intencje użytkownika mogą zostać przełożone na prędkość, która jest używana do szybkiego przewijania (przewijania za pomocą animacji) kontenera z możliwością przewijania. Szybkie przesunięcie jest też częścią zagnieżdżonego cyklu przewijania, a prędkości generowane przez zdarzenie przeciągania przechodzą przez podobne fazy: przed szybkim przesunięciem, zużycie węzła i po szybkim przesunięciu. Pamiętaj, że animacja przesunięcia jest powiązana tylko z gestem dotykowym i nie jest wywoływana przez inne zdarzenia, takie jak przewijanie za pomocą funkcji ułatwień dostępu lub sprzętu.
Uczestniczenie w cyklu zagnieżdżonego przewijania
Uczestnictwo w cyklu oznacza przechwytywanie, wykorzystywanie i raportowanie wykorzystania różnic w hierarchii. Compose udostępnia zestaw narzędzi, które pozwalają wpływać na działanie zagnieżdżonego systemu przewijania i bezpośrednio z nim wchodzić w interakcję, np. gdy musisz coś zrobić z różnicami przewijania, zanim komponent z możliwością przewijania zacznie się przewijać.
Jeśli zagnieżdżony cykl przewijania jest systemem działającym na łańcuchu węzłów, modyfikator nestedScroll umożliwia przechwytywanie i wstawianie zmian oraz wpływanie na dane (przyrosty przewijania) propagowane w łańcuchu. Ten modyfikator może być umieszczony w dowolnym miejscu w hierarchii i komunikuje się z zagnieżdżonymi instancjami modyfikatora przewijania w górę drzewa, dzięki czemu może udostępniać informacje za pomocą tego kanału. Podstawowymi elementami tego modyfikatora są NestedScrollConnection i NestedScrollDispatcher.
NestedScrollConnection
umożliwia reagowanie na fazy zagnieżdżonego cyklu przewijania i wpływanie na
zagnieżdżony system przewijania. Składa się z 4 metod wywołania zwrotnego, z których każda reprezentuje jedną z faz konsumpcji: przed i po przewinięciu oraz przed i po przesunięciu:
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 } }
Każde wywołanie zwrotne zawiera też informacje o propagowanej zmianie:available zmianę w danej fazie i consumed zmianę wykorzystaną w poprzednich fazach. Jeśli w dowolnym momencie chcesz przestać propagować zmiany w górę hierarchii, możesz użyć do tego zagnieżdżonego połączenia przewijania:
val disabledNestedScrollConnection = remember { object : NestedScrollConnection { override fun onPostScroll( consumed: Offset, available: Offset, source: NestedScrollSource ): Offset { return if (source == NestedScrollSource.SideEffect) { available } else { Offset.Zero } } } }
Wszystkie wywołania zwrotne zawierają informacje o NestedScrollSource.
NestedScrollDispatcher
inicjuje zagnieżdżony cykl przewijania. Użycie dyspozytora i wywołanie jego metod
uruchamia cykl. Kontenery z możliwością przewijania mają wbudowany moduł wysyłający, który przesyła do systemu różnice zarejestrowane podczas gestów. Z tego powodu większość przypadków użycia dostosowywania zagnieżdżonego przewijania polega na używaniu NestedScrollConnection zamiast dyspozytora, aby reagować na już istniejące delty, a nie wysyłać nowych.
Więcej informacji znajdziesz w sekcji NestedScrollDispatcherSample.
Zmienianie rozmiaru obrazu podczas przewijania
Podczas przewijania przez użytkownika możesz utworzyć dynamiczny efekt wizualny, w którym rozmiar obrazu zmienia się w zależności od pozycji przewijania.
Zmienianie rozmiaru obrazu na podstawie pozycji przewijania
Ten fragment kodu pokazuje, jak zmienić rozmiar obrazu w elemencie LazyColumn na podstawie pozycji przewijania w pionie. Obraz zmniejsza się, gdy użytkownik przewija w dół, i powiększa, gdy przewija w górę, pozostając w określonych granicach minimalnego i maksymalnego rozmiaru:
@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 } ) } }
Najważniejsze informacje o kodzie
- Ten kod używa
NestedScrollConnectiondo przechwytywania zdarzeń przewijania. onPreScrolloblicza zmianę rozmiaru obrazu na podstawie wartości delta przewijania.- Zmienna stanu
currentImageSizeprzechowuje bieżący rozmiar obrazu, który mieści się w zakresie odminImageSizedomaxImageSize. imageScalei jest obliczany na podstawie zmiennejcurrentImageSize. - Wartości przesunięcia
LazyColumnsą oparte na wartościcurrentImageSize. - W przypadku
Imageużywany jest modyfikatorgraphicsLayer, aby zastosować obliczoną skalę. - Symbol
translationYw ramachgraphicsLayerzapewnia, że obraz pozostanie wyśrodkowany w pionie podczas skalowania.
Wynik
Powyższy fragment kodu powoduje efekt skalowania obrazu podczas przewijania:
Współdziałanie zagnieżdżonego przewijania
Jeśli spróbujesz zagnieździć elementy z możliwością przewijania View w komponentach z możliwością przewijania lub odwrotnie, możesz napotkać problemy. Najbardziej zauważalne będą sytuacje, w których przewijasz element podrzędny i docierasz do jego początku lub końca, a oczekujesz, że przewijanie przejmie element nadrzędny. Jednak to oczekiwane zachowanie może nie wystąpić lub może nie działać zgodnie z oczekiwaniami.
Ten problem wynika z oczekiwań wbudowanych w komponenty kompozycyjne z możliwością przewijania.
Komponenty z możliwością przewijania mają regułę „nested-scroll-by-default”, co oznacza, że każdy kontener z możliwością przewijania musi uczestniczyć w łańcuchu przewijania zagnieżdżonego zarówno jako element nadrzędny za pomocą NestedScrollConnection, jak i jako element podrzędny za pomocą NestedScrollDispatcher.
W takim przypadku element podrzędny będzie powodować zagnieżdżone przewijanie elementu nadrzędnego, gdy osiągnie granicę. Na przykład ta reguła umożliwia prawidłowe współdziałanie funkcji Twórz Pager i Twórz LazyRow. Jednak w przypadku przewijania w ramach interoperacyjności za pomocą ViewPager2 lub RecyclerView, ponieważ nie implementują one NestedScrollingParent3, ciągłe przewijanie z elementu podrzędnego do nadrzędnego nie jest możliwe.
Aby włączyć interfejs API współdziałania z zagnieżdżonym przewijaniem między elementami View z możliwością przewijania a komponentami z możliwością przewijania, zagnieżdżonymi w obu kierunkach, możesz użyć interfejsu API współdziałania z zagnieżdżonym przewijaniem, aby rozwiązać te problemy w tych scenariuszach.
Współpracujący rodzic View zawierający dziecko ComposeView
Współpracujący element nadrzędny View to element, który implementuje już
NestedScrollingParent3
i dlatego może otrzymywać delty przewijania ze współpracującego zagnieżdżonego elementu podrzędnego
kompozycji. ComposeView zachowywałby się w tym przypadku jak dziecko i musiałby (pośrednio) zaimplementować NestedScrollingChild3.
Przykładem współpracującego rodzica jest
androidx.coordinatorlayout.widget.CoordinatorLayout.
Jeśli potrzebujesz interoperacyjności zagnieżdżonego przewijania między przewijanymi Viewkontenerami nadrzędnymi
a zagnieżdżonymi przewijanymi komponentami podrzędnymi, możesz użyć rememberNestedScrollInteropConnection().
rememberNestedScrollInteropConnection()
umożliwia i zapamiętuje
NestedScrollConnection
umożliwiające zagnieżdżone przewijanie między elementem nadrzędnym View, który implementuje
NestedScrollingParent3
a elementem podrzędnym Compose. Należy go używać w połączeniu z modyfikatorem nestedScroll. Przewijanie zagnieżdżone jest domyślnie włączone po stronie Compose, więc możesz użyć tego połączenia, aby włączyć przewijanie zagnieżdżone po stronie View i dodać niezbędną logikę łączącą Views z komponentami kompozycyjnymi.
Częstym przypadkiem użycia jest użycie CoordinatorLayout, CollapsingToolbarLayout i komponentu podrzędnego, jak w tym przykładzie:
<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>
W aktywności lub fragmencie musisz skonfigurować komponent kompozycyjny podrzędny i wymagany NestedScrollConnection:
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()) } } } } } } }
Funkcja kompozycyjna nadrzędna zawierająca funkcję kompozycyjną podrzędną AndroidView
Ten scenariusz obejmuje implementację zagnieżdżonego interfejsu API do przewijania na platformie Compose – gdy masz nadrzędną funkcję kompozycyjną zawierającą podrzędną funkcję kompozycyjną AndroidView. Element AndroidView implementuje interfejs NestedScrollDispatcher, ponieważ jest elementem podrzędnym elementu przewijanego Compose, a także interfejs NestedScrollingParent3, ponieważ jest elementem nadrzędnym elementu przewijanego View. Komponent nadrzędny będzie wtedy mógł otrzymywać zagnieżdżone delty przewijania z zagnieżdżonego komponentu podrzędnego z możliwością przewijaniaView.
Poniższy przykład pokazuje, jak w tym scenariuszu można osiągnąć współdziałanie zagnieżdżonego przewijania, a także zwijany pasek narzędzi Compose:
@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) {
// ...
}
}
// ...
}
Ten przykład pokazuje, jak używać interfejsu API z modyfikatorem 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)
}
}
)
}
}
Ten przykład pokazuje, jak interfejs API do współdziałania z zagnieżdżonym przewijaniem jest używany z BottomSheetDialogFragment, aby uzyskać prawidłowe działanie funkcji przeciągania i zamykania:
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
}
}
}
Pamiętaj, że
rememberNestedScrollInteropConnection()
zainstaluje
NestedScrollConnection
w elemencie, do którego go dołączysz. NestedScrollConnection odpowiada za przesyłanie zmian z poziomu Compose na poziom View. Umożliwia to elementowi uczestniczenie w przewijaniu zagnieżdżonym, ale nie włącza automatycznie przewijania elementów. W przypadku komponentów kompozycyjnych, które nie są przewijane automatycznie, np. Box lub Column, różnice przewijania w takich komponentach nie będą propagowane w systemie przewijania zagnieżdżonego, a różnice nie dotrą do elementu NestedScrollConnection dostarczonego przez rememberNestedScrollInteropConnection(), dlatego nie dotrą też do nadrzędnego komponentu View. Aby rozwiązać ten problem, upewnij się, że w przypadku tych typów zagnieżdżonych funkcji kompozycyjnych ustawiasz też modyfikatory z możliwością przewijania. Więcej informacji znajdziesz w poprzedniej sekcji dotyczącej zagnieżdżonego przewijania.
Rodzic nie współpracuje View z dzieckiem ComposeView
Widok nieobsługujący to taki, który nie implementuje niezbędnych interfejsów po stronie View.NestedScrolling Pamiętaj, że oznacza to, że zagnieżdżone przewijanie nie działa od razu z tymi Views. Nie współpracujące Views to RecyclerView i ViewPager2.
Dodatkowe materiały
- Tworzenie przycisku umożliwiającego przewijanie z przyciąganiem
- Tworzenie efektu przewijania z paralaksą
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Omówienie gestów
- Migracja z
CoordinatorLayoutdo Compose - Korzystanie z widoków w Compose