Cómo compilar el diseño de un panel complementario

El diseño canónico del panel complementario centra la atención del usuario en el contenido principal de tu app y, al mismo tiempo, muestra contenido complementario relevante. Por ejemplo, en el panel de contenido principal, se puede mostrar información sobre una película reciente, mientras que en el panel complementario se muestra una lista de otras películas con un tema similar, el mismo director o actores protagonizados. Para obtener más información sobre el diseño canónico del panel complementario, consulta los lineamientos del panel complementario de Material 3.

Implementa un panel complementario

SupportingPaneScaffold consta de hasta tres paneles: un panel principal, un panel complementario y un panel adicional opcional. El andamiaje controla todos los cálculos para asignar espacio de ventana a los tres paneles. En pantallas grandes, el andamiaje muestra el panel principal con el panel complementario a un lado. En pantallas pequeñas, el andamiaje muestra la pantalla completa del panel principal o complementario.

Contenido principal que ocupa la mayor parte de la pantalla con contenido complementario al lado.
Figura 1: Diseño de panel complementario.

Agrega dependencias

SupportingPaneScaffold es parte de la biblioteca de diseño adaptable de Material 3.

Agrega las siguientes tres dependencias relacionadas al archivo build.gradle de tu app o módulo:

Kotlin


implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")

Groovy


implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'

  • Adaptable: Componentes básicos de bajo nivel, como HingeInfo y Posture
  • Diseño adaptable: Son los diseños adaptables, como SupportingPaneScaffold.
  • adaptive-navigation: Elementos componibles para navegar dentro y entre paneles

Crea un navegador y un andamiaje

En ventanas pequeñas, solo se muestra un panel a la vez, por lo que debes usar un ThreePaneScaffoldNavigator para moverte hacia y desde los paneles. Crea una instancia del navegador con rememberSupportingPaneScaffoldNavigator. Para controlar los gestos de retroceso, usa un BackHandler que verifique canNavigateBack() y llame a navigateBack():

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

El andamiaje requiere un PaneScaffoldDirective, que controla cómo dividir la pantalla y cuánto espaciado usar, y un ThreePaneScaffoldValue, que proporciona el estado actual de los paneles (por ejemplo, si están ocultos o expandidos). Para el comportamiento predeterminado, usa scaffoldDirective y scaffoldValue del navegador, respectivamente:

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = { /*...*/ },
    supportingPane = { /*...*/ },
)

El panel principal y el complementario son elementos componibles que incluyen tu contenido. Usa AnimatedPane para aplicar las animaciones de paneles predeterminadas durante la navegación. Usa el valor de Scaffold para verificar si el panel complementario está oculto. De ser así, muestra un botón que llame a navigateTo(ThreePaneScaffoldRole.Secondary) a fin de mostrar el panel complementario.

A continuación, se muestra una implementación completa de la estructura:

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Main pane content
            if (navigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) {
                Button(
                    modifier = Modifier.wrapContentSize(),
                    onClick = {
                        navigator.navigateTo(SupportingPaneScaffoldRole.Supporting)
                    }
                ) {
                    Text("Show supporting pane")
                }
            } else {
                Text("Supporting pane is shown")
            }
        }
    },
    supportingPane = {
        AnimatedPane(modifier = Modifier.safeContentPadding()) {
            // Supporting pane content
            Text("Supporting pane")
        }
    },
)

Cómo extraer elementos componibles de panel

Extrae los paneles individuales de un SupportingPaneScaffold en sus propios elementos componibles para que se puedan volver a usar y probar. Usa ThreePaneScaffoldScope para acceder a AnimatedPane si quieres las animaciones predeterminadas:

@Composable
fun ThreePaneScaffoldScope.MainPane(
    shouldShowSupportingPaneButton: Boolean,
    onNavigateToSupportingPane: () -> Unit,
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Main pane content
        if (shouldShowSupportingPaneButton) {
            Button(onClick = onNavigateToSupportingPane) {
                Text("Show supporting pane")
            }
        } else {
            Text("Supporting pane is shown")
        }
    }
}

@Composable
fun ThreePaneScaffoldScope.SupportingPane(
    modifier: Modifier = Modifier,
) {
    AnimatedPane(modifier = modifier.safeContentPadding()) {
        // Supporting pane content
        Text("This is the supporting pane")
    }
}

La extracción de los paneles en elementos componibles simplifica el uso de SupportingPaneScaffold (compara lo siguiente con la implementación completa de la estructura de la sección anterior):

val navigator = rememberSupportingPaneScaffoldNavigator()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

SupportingPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    mainPane = {
        MainPane(
            shouldShowSupportingPaneButton = navigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
            onNavigateToSupportingPane = { navigator.navigateTo(ThreePaneScaffoldRole.Secondary) }
        )
    },
    supportingPane = { SupportingPane() },
)