CoordinatorLayout zu Compose migrieren

CoordinatorLayout ist ein ViewGroup, das komplexe, sich überschneidende und verschachtelte Layouts ermöglicht. Er dient als Container, um bestimmte Material Design-Elemente zu ermöglichen, Interaktionen, wie Symbolleisten zum Maximieren und Minimieren, und Ansichten am unteren Rand für Ansichten die in ihr enthalten sind.

In Compose entspricht ein Scaffold am ehesten einem CoordinatorLayout. Ein Scaffold bietet Inhaltsbereiche zum Kombinieren von Material. Komponenten zu gängigen Bildschirmmustern und Interaktionen. Auf dieser Seite wird beschrieben, wie Sie Ihre CoordinatorLayout-Implementierung migrieren, um Scaffold in Compose zu verwenden.

Migrationsschritte

So migrieren Sie CoordinatorLayout zu Scaffold:

  1. Im folgenden Snippet enthält CoordinatorLayout ein AppBarLayout, das eine ToolBar, eine ViewPager und eine FloatingActionButton enthält. Kommentieren das CoordinatorLayout und seine untergeordneten Elemente aus der UI-Hierarchie aus und fügen Sie ein ComposeView, um ihn zu ersetzen.

    <!--  <androidx.coordinatorlayout.widget.CoordinatorLayout-->
    <!--      android:id="@+id/coordinator_layout"-->
    <!--      android:layout_width="match_parent"-->
    <!--      android:layout_height="match_parent"-->
    <!--      android:fitsSystemWindows="true">-->
    
    <!--    <androidx.compose.ui.platform.ComposeView-->
    <!--        android:id="@+id/compose_view"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="match_parent"-->
    <!--        app:layout_behavior="@string/appbar_scrolling_view_behavior" />-->
    
    <!--    <com.google.android.material.appbar.AppBarLayout-->
    <!--        android:id="@+id/app_bar_layout"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="wrap_content"-->
    <!--        android:fitsSystemWindows="true"-->
    <!--        android:theme="@style/Theme.Sunflower.AppBarOverlay">-->
    
        <!-- AppBarLayout contents here -->
    
    <!--    </com.google.android.material.appbar.AppBarLayout>-->
    
    <!--  </androidx.coordinatorlayout.widget.CoordinatorLayout>-->
    
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  2. Ermitteln Sie in Ihrem Fragment oder Ihrer Aktivität einen Verweis auf das ComposeView, das Sie und die setContent-Methode dafür aufrufen. Im Hauptteil der Methode Scaffold als Inhalt festlegen:

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. Füge im Inhalt deiner Scaffold den Hauptinhalt deines Bildschirms in . Da der Hauptinhalt in der obigen XML-Datei ein ViewPager2 ist, verwenden wir ein HorizontalPager, das Compose-Äquivalent dafür. Lambda von content der Scaffold erhält auch eine Instanz von PaddingValues, die auf das Inhaltsstammverzeichnis angewendet wird. Mit Modifier.padding können Sie PaddingValues zu HorizontalPager.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. Andere von Scaffold bereitgestellte Inhaltsbereiche verwenden, um weitere Bildschirmelemente hinzuzufügen und die verbleibenden untergeordneten Ansichten migrieren. Über die Anzeigenfläche topBar können Sie eine TopAppBar und dem Slot floatingActionButton, um eine FloatingActionButton

    composeView.setContent {
        Scaffold(
            Modifier.fillMaxSize(),
            topBar = {
                TopAppBar(
                    title = {
                        Text("My App")
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(
                    onClick = { /* Handle click */ }
                ) {
                    Icon(
                        Icons.Filled.Add,
                        contentDescription = "Add Button"
                    )
                }
            }
        ) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

Gängige Anwendungsfälle

Symbolleisten minimieren und maximieren

Wenn Sie im Ansichtssystem die Symbolleiste mit CoordinatorLayout minimieren und maximieren möchten, verwenden Sie einen AppBarLayout als Container für die Symbolleiste. Sie können dann eine Behavior bis layout_behavior in XML auf dem zugehörigen scrollbaren Element Ansicht (wie RecyclerView oder NestedScrollView), um zu erklären, wie die Symbolleiste wird beim Scrollen minimiert/maximiert.

Einen ähnlichen Effekt erzielen Sie in der Funktion „Schreiben“ TopAppBarScrollBehavior Um beispielsweise eine Anzeige zum Minimieren oder Maximieren sodass die Symbolleiste angezeigt wird, wenn Sie nach oben scrollen:

  1. Rufen Sie TopAppBarDefaults.enterAlwaysScrollBehavior() auf, um ein TopAppBarScrollBehavior.
  2. Geben Sie die erstellte TopAppBarScrollBehavior an die TopAppBar weiter.
  3. Verbinden Sie NestedScrollConnection über Modifier.nestedScroll auf der Scaffold festlegen, damit das Scaffold verschachtelte Scroll-Ereignisse empfangen kann, scrollbarer Inhalt nach oben/unten. So kann die App-Leiste beim Scrollen der Inhalte entsprechend minimiert oder maximiert werden.

    // 1. Create the TopAppBarScrollBehavior
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text("My App")
                },
                // 2. Provide scrollBehavior to TopAppBar
                scrollBehavior = scrollBehavior
            )
        },
        // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
    ) { contentPadding ->
        /* Contents */
        // ...
    }

Minimieren/Maximieren des Scrolleffekts anpassen

Sie können mehrere Parameter für enterAlwaysScrollBehavior angeben, um den Animationseffekt für das Zusammen- und Auseinanderfalten anzupassen. TopAppBarDefaults bietet auch andere TopAppBarScrollBehavior wie exitUntilCollapsedScrollBehavior, mit dem sich die App-Leiste nur maximiert, wenn der Inhalt ganz nach unten gescrollt wird.

Um einen vollständig benutzerdefinierten Effekt zu erstellen (z. B. einen Parallaxe-Effekt), kannst du Sie können auch Ihr eigenes NestedScrollConnection erstellen und die Symbolleiste manuell verschieben als der Inhalt scrollt. Ein Codebeispiel finden Sie im Beispiel für verschachtelte Scrollansicht in AOSP.

Schubladen

Mithilfe von Ansichten können Sie eine Navigationsleiste implementieren, indem Sie DrawerLayout als Stammansicht verwenden. Die CoordinatorLayout ist wiederum eine untergeordnete Ansicht der DrawerLayout. DrawerLayout enthält auch ein weiteres untergeordnetes Element wie zum Beispiel NavigationView, um die Navigationsoptionen in der Ansicht Leiste.

In Compose können Sie eine Navigationsleiste mit dem ModalNavigationDrawer-Komponent implementieren. ModalNavigationDrawer bietet ein drawerContent Slot für die Leiste und content-Slot für den Inhalte.

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

Weitere Informationen finden Sie unter Schubladen.

Snackbars

Scaffold stellt einen snackbarHost-Slot bereit, der einen SnackbarHost akzeptieren kann zusammensetzbar ist, um eine Snackbar anzuzeigen.

val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show snackbar") },
            icon = { Icon(Icons.Filled.Image, contentDescription = "") },
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("Snackbar")
                }
            }
        )
    }
) { contentPadding ->
    // Screen content
    // ...
}

Weitere Informationen finden Sie unter Snackbars.

Weitere Informationen

Weitere Informationen zur Migration einer CoordinatorLayout zu Compose finden Sie in den folgenden Ressourcen: