1. Introducción
Las pantallas grandes te permiten crear IUs y diseños de apps que mejoran la experiencia del usuario y aumentan su productividad. Sin embargo, si tu app se diseñó para pantallas pequeñas de teléfonos no plegables, es probable que no aproveche el espacio de pantalla adicional que ofrecen las tablets, los dispositivos plegables y los dispositivos ChromeOS.
La actualización de una app para aprovechar al máximo las pantallas grandes puede llevar tiempo y ser costoso, en especial para las apps heredadas que se basan en varias actividades.
La incorporación de actividades, que se introducen en Android 12L (nivel de API 32), permite que las apps que se basan en actividades muestren varias de ellas simultáneamente en pantallas grandes para crear diseños de dos paneles, como lista-detalles. No es necesario volver a programar Kotlin ni Java. Solo debes agregar algunas dependencias, crear un archivo de configuración XML, implementar un inicializador y agregar algunos elementos al manifiesto de tu app. O bien, si prefieres trabajar en código, agrega algunas llamadas a la API de Jetpack WindowManager al método onCreate()
de la actividad principal de tu app.
Requisitos previos
Para completar este codelab, necesitarás experiencia en lo siguiente:
- Compilación de apps para Android
- Saber trabajar con actividades
- Saber escribir en formato XML
- Saber trabajar en Android Studio, incluida la configuración de dispositivos virtuales
Qué compilarás
En este codelab, actualizarás una app que se basa en actividades para admitir un diseño dinámico de dos paneles similar a SlidingPaneLayout
. En pantallas pequeñas, la app superpone (apila) actividades una sobre otra en la ventana de tareas.
En pantallas grandes, la app muestra dos actividades simultáneamente en la pantalla, una al lado de la otra o una arriba y otra abajo, según tus especificaciones.
Qué aprenderás
Cómo implementar la incorporación de actividades de dos maneras:
- Con un archivo de configuración XML
- Con llamadas a la API de Jetpack WindowManager
Requisitos
- Versión reciente de Android Studio
- Emulador o teléfono Android
- Emulador o tablet pequeña de Android
- Emulador o tablet grande de Android
2. Configuración
Obtén la app de ejemplo
Paso 1: Clona el repositorio
Clona el repositorio de Git de codelabs de pantallas grandes:
git clone https://github.com/android/large-screen-codelabs
Otra opción es descargar y desarchivar el archivo ZIP de codelabs de pantallas grandes:
Paso 2: Inspecciona los archivos fuente del codelab
Navega a la carpeta activity-embedding
.
Paso 3: Abre el proyecto del codelab
En Android Studio, abre el proyecto de Kotlin o Java.
La carpeta activity-embedding
en el repositorio y el archivo ZIP contiene dos proyectos de Android Studio: uno en Kotlin y otro en Java. Abre el proyecto que prefieras. Los fragmentos de Codelab se proporcionan en ambos lenguajes.
Crea dispositivos virtuales
Si no tienes un teléfono Android ni una tablet pequeña ni una grande con un nivel de API 32 o superior, abre el Administrador de dispositivos en Android Studio y crea cualquiera de los siguientes dispositivos virtuales que necesites:
- Teléfono: Pixel 6, nivel de API 32 o superior
- Tablet pequeña: 7 WSVGA (tablet), nivel de API 32 o superior
- Tablet grande: Pixel C, nivel de API 32 o superior
3. Ejecuta la app
La app de ejemplo muestra una lista de elementos. Cuando el usuario selecciona un elemento, la app muestra información sobre este.
La app consta de tres actividades:
ListActivity
: Contiene una lista de elementos en unRecyclerView
.DetailActivity
: Muestra información sobre un elemento de lista cuando el elemento se selecciona de esta.SummaryActivity
: Muestra un resumen de la información cuando se selecciona el elemento de la lista de resumen.
Comportamiento sin incorporación de actividades
Ejecuta la app de ejemplo para comprobar cómo se comporta sin incorporar la actividad:
- Ejecuta la app de ejemplo en tu tablet grande o emulador de Pixel C. Aparecerá la actividad principal (lista):
- Selecciona un elemento de la lista para iniciar una actividad secundaria (detalle). La actividad de detalles se superpone a la actividad de lista:
- Rota la tablet a la orientación horizontal. La actividad secundaria aún se superpone a la actividad principal y ocupa toda la pantalla:
- Selecciona el control de retroceso (flecha hacia la izquierda en la barra de la aplicación) para regresar a la lista.
- Selecciona el último elemento de la lista, Resumen, para iniciar una actividad de resumen como actividad secundaria. La actividad de resumen se superpone a la actividad de lista:
- Rota la tablet a la orientación horizontal. La actividad secundaria aún se superpone a la actividad principal y ocupa toda la pantalla:
Comportamiento con incorporación de actividades
Cuando completes este codelab, la orientación horizontal mostrará las actividades de lista y de detalles una al lado de la otra, en un diseño de lista-detalles:
Sin embargo, configurarás que el resumen se muestre en pantalla completa, aunque la actividad se inicie dentro de una división. El resumen se superpondrá a la división:
4. Fondo
La incorporación de actividades divide la ventana de tareas de la app en dos contenedores: uno principal y otro secundario. Cualquier actividad puede iniciar una división con el inicio de otra actividad. La actividad de inicio ocupa el contenedor principal; la actividad iniciada, el secundario.
La actividad principal puede iniciar actividades adicionales en el contenedor secundario. Luego, las actividades en ambos contenedores pueden iniciar actividades en sus respectivos contenedores. Cada contenedor puede contener una pila de actividades. Si deseas obtener más información, consulta la guía para desarrolladores sobre Incorporación de actividades.
Para configurar que tu app admita la incorporación de actividades, crea un archivo de configuración XML o realiza llamadas a la API de Jetpack WindowManager. Comenzaremos con el enfoque de configuración XML.
5. Configuración XML
La biblioteca de WindowManager de Jetpack crea y administra contenedores y divisiones para la incorporación de actividades en función de las reglas de división que crees en un archivo de configuración XML.
Agrega la dependencia WindowManager
Habilita la app de ejemplo para acceder a la biblioteca de WindowManager. Para ello, agrega la dependencia de la biblioteca al archivo build.gradle
de nivel de módulo de la app, por ejemplo:
build.gradle
implementation 'androidx.window:window:1.2.0'
Informa al sistema
Infórmale al sistema que tu app implementó la incorporación de actividades.
Agrega la propiedad android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
al elemento <application>
del archivo de manifiesto de la app y establece el valor en "true":
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
android:value="true" />
</application>
</manifest>
Los fabricantes de dispositivos (OEMs) usan el parámetro de configuración para habilitar capacidades personalizadas para las apps que admiten la incorporación de actividades. Por ejemplo, los dispositivos pueden aplicar el formato letterbox a actividades solo en orientación vertical (consulta android:screenOrientation
) en pantallas horizontales para orientar las actividades para una transición fluida a un diseño de dos paneles para incorporar actividades:
Crea un archivo de configuración
Crea un archivo de recursos XML con el nombre main_split_config.xml
en la carpeta res/xml
de la app con resources
como elemento raíz.
Cambia el espacio de nombres XML a:
main_split_config.xml
xmlns:window="http://schemas.android.com/apk/res-auto"
Regla de par dividido
Agrega la siguiente regla de divisiones al archivo de configuración:
main_split_config.xml
<!-- Define a split for the named activity pair. -->
<SplitPairRule
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithSecondary="never"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
La regla hace lo siguiente:
- Configura las opciones de división para actividades que comparten una:
splitRatio
: Especifica qué porcentaje de la ventana de tareas ocupa la actividad principal (33%) y deja el espacio restante para la actividad secundaria.splitMinWidthDp
: Especifica el ancho de pantalla mínimo (840) necesario para que ambas actividades aparezcan en pantalla de manera simultánea. Las unidades son píxeles independientes de la pantalla (dp).
finishPrimaryWithSecondary
: Especifica si las actividades del contenedor dividido principal finalizan (nunca) cuando terminan todas las actividades del contenedor secundario.finishSecondaryWithPrimary
: Especifica si las actividades del contenedor secundario finalizan (siempre) cuando terminan todas las actividades del contenedor principal.- Incluye un filtro de división que define las actividades que comparten una división de la ventana de tareas. La actividad principal es
ListActivity
; la secundaria esDetailActivity
.
Regla de marcador de posición
Una actividad de marcador de posición ocupa el contenedor secundario de una división de actividad cuando no hay contenido disponible para ese contenedor, por ejemplo, cuando se abre una división de lista-detalles, pero aún no se seleccionó un elemento de la lista (para obtener más información, consulta Marcadores de posición en la guía para desarrolladores sobre Incorporación de actividad).
Agrega la siguiente regla de marcador de posición al archivo de configuración:
main_split_config.xml
<!-- Automatically launch a placeholder for the detail activity. -->
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity"
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithPlaceholder="always"
window:stickyPlaceholder="false">
<ActivityFilter
window:activityName=".ListActivity"/>
</SplitPlaceholderRule>
La regla hace lo siguiente:
- Identifica la actividad de marcador de posición,
PlaceholderActivity
(crearemos esta actividad en el siguiente paso). - Configura las opciones del marcador de posición:
splitRatio
: Especifica qué porcentaje de la ventana de tareas ocupa la actividad principal (33%) y deja el espacio restante para el marcador de posición. Por lo general, este valor debe coincidir con la proporción de división de la regla de par dividido con la que está asociado el marcador de posición.splitMinWidthDp
: Especifica el ancho de pantalla mínimo (840) necesario para que el marcador de posición aparezca en pantalla con la actividad principal. Por lo general, este valor debe coincidir con el ancho mínimo de la regla de par dividido con la que está asociado el marcador de posición. Las unidades son píxeles independientes de la pantalla (dp).finishPrimaryWithPlaceholder
: Especifica si las actividades del contenedor del contenedor principal dividido finalizan (siempre) cuando lo hace el marcador de posición.stickyPlaceholder
: Indica si el marcador de posición debe permanecer en la pantalla (falso) como actividad en la parte superior cuando se cambia el tamaño de la pantalla de dos paneles a una de uno solo, por ejemplo, cuando se pliega un dispositivo plegable.- Incluye un filtro de actividad que especifica la actividad (
ListActivity
) con la que el marcador de posición comparte la división de una ventana de tareas.
El marcador de posición representa la actividad secundaria de la regla de par dividido cuya actividad principal es la misma que la actividad en el filtro de actividad del marcador de posición (consulta "Regla de par dividido" en la sección "Configuración XML" de este codelab).
Regla de actividad
Las reglas de actividad son de uso general. Las actividades que deseas que ocupen toda la ventana de tareas (es decir, que nunca formen parte de una división) se pueden especificar con una regla de actividad (para obtener más información, consulta Ventana modal completa en la guía para desarrolladores sobre la Incorporación de actividades).
Haremos que la actividad de resumen ocupe toda la ventana de la tarea y se superponga a la división. La navegación hacia atrás regresará a la división.
Agrega la siguiente regla de actividad al archivo de configuración:
main_split_config.xml
<!-- Activities that should never be in a split. -->
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".SummaryActivity"/>
</ActivityRule>
La regla hace lo siguiente:
- Identifica la actividad que se debe mostrar en la ventana completa (
SummaryActivity).
) - Configura las opciones para la actividad:
alwaysExpand
: Especifica si se debe expandir la actividad para que ocupe todo el espacio disponible de la pantalla.
Archivo de origen
El archivo de configuración XML finalizado debería verse de la siguiente manera:
main_split_config.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:window="http://schemas.android.com/apk/res-auto">
<!-- Define a split for the named activity pair. -->
<SplitPairRule
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithSecondary="never"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
<!-- Automatically launch a placeholder for the detail activity. -->
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity"
window:splitRatio="0.33"
window:splitMinWidthDp="840"
window:finishPrimaryWithPlaceholder="always"
window:stickyPlaceholder="false">
<ActivityFilter
window:activityName=".ListActivity"/>
</SplitPlaceholderRule>
<!-- Activities that should never be in a split. -->
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".SummaryActivity"/>
</ActivityRule>
</resources>
Crea una actividad de marcador de posición
Debes crear una actividad nueva para que funcione como el marcador de posición que se especifica en el archivo de configuración XML. La actividad puede ser muy sencilla: solo una para indicarles a los usuarios que el contenido aparecerá aquí más adelante.
Crea la actividad en la carpeta de origen principal de la app de ejemplo.
En Android Studio, haz lo siguiente:
- Haz clic con el botón derecho (clic con el botón secundario) en la carpeta de origen de la app de ejemplo,
com.example.activity_embedding
. - Selecciona New > Activity > Empty Views Activity.
- Asígnele el nombre PlaceholderActivity a la actividad.
- Selecciona Finish.
Android Studio crea la actividad en el paquete de la app de ejemplo, la agrega al archivo de manifiesto de la app y crea un archivo de recursos de diseño con el nombre activity_placeholder.xm
l en la carpeta res/layout
.
- En el archivo
AndroidManifest.xml
de la app de ejemplo, establece la etiqueta para la actividad del marcador de posición en una cadena vacía:
AndroidManifest.xml
<activity
android:name=".PlaceholderActivity"
android:exported="false"
android:label="" />
- Reemplaza el contenido del archivo de diseño
activity_placeholder.xml
en la carpetares/layout
por lo siguiente:
activity_placeholder.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/gray"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".PlaceholderActivity">
<TextView
android:id="@+id/textViewPlaceholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/placeholder_text"
android:textSize="36sp"
android:textColor="@color/obsidian"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- Por último, agrega el siguiente recurso de cadenas al archivo de recursos
strings.xml
en la carpetares/values
:
strings.xml
<string name="placeholder_text">Placeholder</string>
Crea un inicializador
El componente RuleController
de WindowManager analiza las reglas que se definen el archivo de configuración XML y las pone a disposición del sistema.
Un inicializador de la bibliotecaStartup de Jetpack le permite a RuleController
acceder al archivo de configuración.
La biblioteca Startup realiza la inicialización de componentes cuando se inicia la app. La inicialización debe ocurrir antes de que comiencen las actividades para que RuleController
tenga acceso a las reglas de división y pueda aplicarlas si es necesario.
Agrega la dependencia de la biblioteca Startup
Para habilitar la funcionalidad de inicio, agrega la dependencia de la biblioteca Startup al archivo build.gradle
de nivel de módulo de la app de ejemplo, por ejemplo:
build.gradle
implementation 'androidx.startup:startup-runtime:1.1.1'
Implementa un inicializador para RuleController
Crea una implementación de la interfaz del inicializador de Startup.
En Android Studio, haz lo siguiente:
- Haz clic con el botón derecho (clic con el botón secundario) en la carpeta de origen de la app de ejemplo,
com.example.activity_embedding
. - Selecciona New > Kotlin Class/File o New > Java Class.
- Asígnele el nombre SplitInitializer a la clase.
- Presiona Intro: Android Studio creará la clase en el paquete de la app de ejemplo.
- Reemplaza el contenido del archivo de la clase por lo siguiente:
SplitInitializer.kt
package com.example.activity_embedding
import android.content.Context
import androidx.startup.Initializer
import androidx.window.embedding.RuleController
class SplitInitializer : Initializer<RuleController> {
override fun create(context: Context): RuleController {
return RuleController.getInstance(context).apply {
setRules(RuleController.parseRules(context, R.xml.main_split_config))
}
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
SplitInitializer.java
package com.example.activity_embedding;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.startup.Initializer;
import androidx.window.embedding.RuleController;
import java.util.Collections;
import java.util.List;
public class SplitInitializer implements Initializer<RuleController> {
@NonNull
@Override
public RuleController create(@NonNull Context context) {
RuleController ruleController = RuleController.getInstance(context);
ruleController.setRules(
RuleController.parseRules(context, R.xml.main_split_config)
);
return ruleController;
}
@NonNull
@Override
public List<Class<? extends Initializer<?>>> dependencies() {
return Collections.emptyList();
}
}
El inicializador pone a disposición las reglas de división para el componente RuleController
pasando el ID del archivo de recursos XML que contiene las definiciones ((main_split_config
) al método parseRules()
del componente. El método setRules()
agrega las reglas analizadas a RuleController
.
Crea un proveedor de inicialización
Un proveedor invoca el proceso de inicialización de las reglas de división.
Agrega androidx.startup.InitializationProvider
al elemento <application>
del archivo de manifiesto de la app de ejemplo como proveedor y haz referencia a SplitInitializer
:
AndroidManifest.xml
<provider android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- Make SplitInitializer discoverable by InitializationProvider. -->
<meta-data android:name="${applicationId}.SplitInitializer"
android:value="androidx.startup" />
</provider>
InitializationProvider
inicializa SplitInitializer
, que a su vez invoca los métodos RuleController
que analizan el archivo de configuración XML (main_split_config.xml
) y agrega las reglas a RuleController
(consulta "Implementa un inicializador para RuleController" más arriba).
InitializationProvider
detecta y luego inicializa SplitInitializer
antes de que se ejecute el método onCreate()
de la app; de esta manera, las reglas de división estarán vigentes cuando comience la actividad principal de la app.
Archivo de origen
Este es el manifiesto completo de la app:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activity_Embedding"
tools:targetApi="32">
<activity
android:name=".ListActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailActivity"
android:exported="false"
android:label="" />
<activity
android:name=".SummaryActivity"
android:exported="false"
android:label="" />
<activity
android:name=".PlaceholderActivity"
android:exported="false"
android:label="" />
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
android:value="true" />
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- Make SplitInitializer discoverable by InitializationProvider. -->
<meta-data
android:name="${applicationId}.SplitInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>
Acceso directo de inicialización
Si deseas integrar la configuración XML con las APIs de WindowManager, puedes eliminar el inicializador de la biblioteca Startup y el proveedor de manifiestos para lograr una implementación mucho más sencilla.
Una vez que hayas creado tu archivo de configuración XML, haz lo siguiente:
Paso 1: Crea una subclase de Application
La subclase de tu aplicación será la primera instancia de clase que se genera cuando se crea el proceso de tu app. Agregarás las reglas de división a RuleController
en el método onCreate()
de tu subclase para garantizar que las reglas estén vigentes antes de que se inicien las actividades.
En Android Studio, haz lo siguiente:
- Haz clic con el botón derecho (clic con el botón secundario) en la carpeta de origen de la app de ejemplo,
com.example.activity_embedding
. - Selecciona New > Kotlin Class/File o New > Java Class.
- Asígnale el nombre SampleApplication a la clase.
- Presiona Intro: Android Studio creará la clase en el paquete de la app de ejemplo.
- Extiende la clase del supertipo
Application
.
SampleApplication.kt
package com.example.activity_embedding
import android.app.Application
/**
* Initializer for activity embedding split rules.
*/
class SampleApplication : Application() {
}
SampleApplication.java
package com.example.activity_embedding;
import android.app.Application;
/**
* Initializer for activity embedding split rules.
*/
public class SampleApplication extends Application {
}
Paso 2: Inicializa RuleController
Agrega las reglas de división del archivo de configuración XML a RuleController
en el método onCreate()
de la subclase de tu aplicación.
Para agregar reglas a RuleController
, haz lo siguiente:
- Obtén una instancia singleton de
RuleController
- Usa el método
parseRules()
estático de Java o complementario de Kotlin deRuleController
para analizar el archivo en formato XML. - Agrega las reglas analizadas a
RuleController
con el métodosetRules()
.
SampleApplication.kt
override fun onCreate() {
super.onCreate()
RuleController.getInstance(this)
.setRules(RuleController.parseRules(this, R.xml.main_split_config))
}
SampleApplication.java
@Override
public void onCreate() {
super.onCreate();
RuleController.getInstance(this)
.setRules(RuleController.parseRules(this, R.xml.main_split_config));
}
Paso 3: Agrega el nombre de tu subclase al manifiesto
Agrega el nombre de tu subclase al elemento <application>
del manifiesto de la app:
AndroidManifest.xml
<application
android:name=".SampleApplication"
. . .
¡Ejecútalo!
Compila y ejecuta la app de ejemplo.
En un teléfono no plegable, las actividades siempre se apilan, incluso en orientación horizontal:
En Android 13 (nivel de API 33) y versiones anteriores, la incorporación de actividades no está habilitada en teléfonos no plegables, independientemente de las especificaciones de ancho mínimo de la división.
La compatibilidad con la incorporación de actividades en teléfonos no plegables en niveles superiores de API depende de si el fabricante del dispositivo habilitó esta incorporación.
En una tablet pequeña o en el emulador de 7 WSVGA (tablet), las dos actividades se apilan en orientación vertical, pero aparecen una al lado de la otra en orientación horizontal:
En una tablet grande o en el emulador de Pixel C, las actividades se apilan en orientación vertical (consulta la sección "Relación de aspecto" más abajo), pero aparecen una al lado de la otra en orientación horizontal:
El resumen se muestra en pantalla completa en orientación horizontal aunque se haya iniciado dentro de una división:
Relación de aspecto
Las divisiones de actividad se controlan mediante la relación de aspecto de la pantalla, además del ancho mínimo de la división. Los atributos splitMaxAspectRatioInPortrait
y splitMaxAspectRatioInLandscape
especifican la relación de aspecto máxima de la pantalla (altura:ancho) para la que se muestran las divisiones de actividad. Los atributos representan las propiedades maxAspectRatioInPortrait
y maxAspectRatioInLandscape
de SplitRule
.
Si la relación de aspecto de una pantalla supera el valor en cualquiera de las orientaciones, se inhabilitan las divisiones, independientemente del ancho de la pantalla. El valor predeterminado para la orientación vertical es 1.4 (consulta SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
), lo que evita que las pantallas altas y angostas incluyan divisiones. De forma predeterminada, las divisiones siempre se permiten en orientación horizontal (consulta SPLIT_MAX_ASPECT_RATIO_LANDSCAPE_DEFAULT
).
El emulador de Pixel C tiene un ancho de pantalla vertical de 900 dp, que es más ancho que la configuración de splitMinWidthDp
del archivo de configuración XML de la app de ejemplo, por lo que el emulador debería mostrar una división de actividad. Sin embargo, la relación de aspecto del Pixel C en posición vertical es superior a 1.4, por lo que no se muestran divisiones de actividad en orientación vertical.
Puedes establecer la relación de aspecto máxima para las pantallas verticales y horizontales en el archivo de configuración XML en los elementos SplitPairRule
y SplitPlaceholderRule
, por ejemplo:
main_split_config.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:window="http://schemas.android.com/apk/res/android">
<!-- Define a split for the named activity pair. -->
<SplitPairRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow"
window:splitMaxAspectRatioInLandscape="alwaysDisallow"
. . .
</SplitPairRule>
<SplitPlaceholderRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow"
window:splitMaxAspectRatioInLandscape="alwaysDisallow"
. . .
</SplitPlaceholderRule>
</resources>
En una tablet grande con un ancho de pantalla vertical superior o igual a 840 dp o en el emulador de Pixel C, las actividades están una al lado de la otra en orientación vertical, pero se apilan en orientación horizontal:
Crédito extra
Intenta configurar la relación de aspecto en la app de ejemplo, como se muestra más arriba para las orientaciones vertical y horizontal. Prueba la configuración con tu tablet grande (si el ancho vertical es de 840 dp o superior) o con el emulador de Pixel C. Deberías ver una actividad dividida en orientación vertical, pero no en orientación horizontal.
Determina la relación de aspecto vertical de tu tablet grande (la relación de aspecto del Pixel C es ligeramente superior a 1.4). Establece splitMaxAspectRatioInPortrait
en valores superior e inferiores a la relación de aspecto. Ejecuta la app y observa los resultados que obtienes.
6. API de WindowManager
Puedes habilitar la incorporación de actividades por completo en el código con un solo método que se llame desde el método onCreate()
de la actividad que inicia la división. Si prefieres trabajar en el código en lugar de XML, esta es la manera de hacerlo.
Agrega la dependencia WindowManager
Tu app necesita acceso a la biblioteca de WindowManager, ya sea que crees una implementación basada en XML o uses llamadas a la API. Consulta la sección "Configuración XML" de este codelab para obtener información sobre cómo agregar la dependencia WindowManager a tu app.
Informa al sistema
Independientemente de que uses un archivo de configuración XML o llamadas a la API de WindowManager, tu app debe notificar al sistema que se implementó la incorporación de actividades. Consulta la sección "Configuración XML" de este codelab para descubrir cómo informar al sistema sobre tu implementación.
Crea una clase para administrar las divisiones
En esta sección del codelab, implementarás una actividad dividida completamente dentro de un solo método de objeto estático o complementario al que llamarás desde la actividad principal de la app de ejemplo, ListActivity
.
Crea una clase llamada SplitManager
con un método llamado createSplit
que incluya un parámetro context
(algunas de las llamadas a la API requieren este parámetro):
SplitManager.kt
class SplitManager {
companion object {
fun createSplit(context: Context) {
}
}
SplitManager.java
class SplitManager {
static void createSplit(Context context) {
}
}
Llama al método en onCreate()
de una subclase de Application
.
Para obtener detalles sobre por qué y cómo crear una subclase de Application
, consulta "Acceso directo de inicialización" en la sección "Configuración XML" de este codelab.
SampleApplication.kt
package com.example.activity_embedding
import android.app.Application
/**
* Initializer for activity embedding split rules.
*/
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
SplitManager.createSplit(this)
}
}
SampleApplication.java
package com.example.activity_embedding;
import android.app.Application;
/**
* Initializer for activity embedding split rules.
*/
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SplitManager.createSplit(this);
}
}
Crea una regla de división
APIs requeridas:
SplitPairRule
define una regla de división para un par de actividades.
SplitPairRule.Builder
crea un SplitPairRule
. El compilador toma un conjunto de objetos SplitPairFilter
como argumento. Los filtros especifican cuándo aplicar la regla.
Registras la regla con una instancia singleton del componente RuleController
, que pone las reglas de división a disposición del sistema.
Para crear una regla de división, haz lo siguiente:
- Crea un filtro de par dividido que identifique
ListActivity
yDetailActivity
como las actividades que comparten una división:
SplitManager.kt / createSplit()
val splitPairFilter = SplitPairFilter(
ComponentName(context, ListActivity::class.java),
ComponentName(context, DetailActivity::class.java),
null
)
SplitManager.java / createSplit()
SplitPairFilter splitPairFilter = new SplitPairFilter(
new ComponentName(context, ListActivity.class),
new ComponentName(context, DetailActivity.class),
null
);
El filtro puede incluir una acción de intent (tercer parámetro) para el inicio de la actividad secundaria. Si incluyes una acción de intent, el filtro verifica la acción junto con el nombre de la actividad. Para las actividades de tu propia app, es probable que no filtres la acción de intent, por lo que el argumento puede ser nulo.
- Agrega el filtro a un conjunto de filtros:
SplitManager.kt / createSplit()
val filterSet = setOf(splitPairFilter)
SplitManager.java / createSplit()
Set<SplitPairFilter> filterSet = new HashSet<>();
filterSet.add(splitPairFilter);
- Crea atributos de diseño para la división:
SplitManager.kt / createSplit()
val splitAttributes: SplitAttributes = SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.33f))
.setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
.build()
SplitManager.java / createSplit()
SplitAttributes splitAttributes = new SplitAttributes.Builder()
.setSplitType(SplitAttributes.SplitType.ratio(0.33f))
.setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
.build();
SplitAttributes.Builder
crea un objeto que contiene atributos de diseño:
setSplitType
: Define cómo se asigna el área de visualización disponible a cada contenedor de actividades. El tipo de división de proporción especifica la proporción de visualización que ocupa el contenedor principal; el contenedor secundario ocupa el resto del área de visualización.setLayoutDirection
: Especifica cómo se distribuyen los contenedores de actividades uno respecto del otro (el contenedor principal se distribuye primero).
- Compila una regla de par dividido:
SplitManager.kt / createSplit()
val splitPairRule = SplitPairRule.Builder(filterSet)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
.setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
.setClearTop(false)
.build()
SplitManager.java / createSplit()
SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
.setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
.setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
.setClearTop(false)
.build();
SplitPairRule.Builder
crea y configura la regla:
filterSet
: Contiene filtros de par dividido que determinan cuándo aplicar la regla mediante la identificación de actividades que comparten una división. En la app de ejemplo,ListActivity
yDetailActivity
se especifican en un filtro de par dividido (consulta los pasos anteriores).setDefaultSplitAttributes
: Aplica los atributos de diseño a la regla.setMinWidthDp
: Establece el ancho de pantalla mínimo (en píxeles independientes de la densidad, dp) que permite una división.setMinSmallestWidthDp
: Establece el valor mínimo (en dp) que debe tener la menor de las dos dimensiones de pantalla para permitir una división, independientemente de la orientación del dispositivo.setFinishPrimaryWithSecondary
: Indica cómo el hecho de finalizar las actividades del contenedor secundario afecta las actividades del contenedor principal.NEVER
indica que el sistema no debe finalizar las actividades principales cuando terminan todas las actividades del contenedor secundario (consulta Finalizar actividades).setFinishSecondaryWithPrimary
: Indica cómo el hecho de finalizar las actividades del contenedor principal afecta las actividades del contenedor secundario.ALWAYS
indica que el sistema siempre debe finalizar las actividades del contenedor secundario cuando terminan todas las actividades del contenedor principal (consulta Finalizar actividades).setClearTop
: Determina si todas las actividades del contenedor secundario finalizan cuando se inicia una nueva actividad en el contenedor. "False" especifica que las actividades nuevas se apilan sobre las que ya se encuentran en el contenedor secundario.
- Obtén la instancia singleton de WindowManager
RuleController
y agrega la regla:
SplitManager.kt / createSplit()
val ruleController = RuleController.getInstance(context)
ruleController.addRule(splitPairRule)
SplitManager.java / createSplit()
RuleController ruleController = RuleController.getInstance(context);
ruleController.addRule(splitPairRule);
Crea una regla de marcador de posición
APIs requeridas:
SplitPlaceholderRule
define una regla para una actividad que ocupa el contenedor secundario cuando no hay contenido disponible para ese contenedor. Para crear una actividad de marcador de posición, consulta "Crea una actividad de marcador de posición" en la sección "Configuración XML" de este codelab (para obtener más información, consulta Marcadores de posición en la guía para desarrolladores sobre Incorporación de actividad).
SplitPlaceholderRule.Builder
crea un SplitPlaceholderRule
. El compilador toma un conjunto de objetos ActivityFilter
como argumento. Los objetos especifican actividades con las que está asociada la regla de marcador de posición. Si el filtro coincide con una actividad iniciada, el sistema aplica la regla de marcador de posición.
Registras la regla con el componente RuleController
.
Para crear una regla de marcador de posición dividida, haz lo siguiente:
- Crea un
ActivityFilter
:
SplitManager.kt / createSplit()
val placeholderActivityFilter = ActivityFilter(
ComponentName(context, ListActivity::class.java),
null
)
SplitManager.java / createSplit()
ActivityFilter placeholderActivityFilter = new ActivityFilter(
new ComponentName(context, ListActivity.class),
null
);
El filtro asocia la regla con la actividad principal de la app de ejemplo, ListActivity
. Por lo tanto, cuando no hay contenido de detalles disponible en el diseño de lista-detalles, el marcador de posición ocupa el área de detalles.
El filtro puede incluir una acción de intent (segundo parámetro) para el inicio de la actividad asociada (inicio de ListActivity
). Si incluyes una acción de intent, el filtro verifica la acción junto con el nombre de la actividad. Para las actividades de tu propia app, es probable que no filtres la acción de intent, por lo que el argumento puede ser nulo.
- Agrega el filtro a un conjunto de filtros:
SplitManager.kt / createSplit()
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
SplitManager.java / createSplit()
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
placeholderActivityFilterSet.add(placeholderActivityFilter);
- Crear un
SplitPlaceholderRule
:
SplitManager.kt / createSplit()
val splitPlaceholderRule = SplitPlaceholderRule.Builder(
placeholderActivityFilterSet,
Intent(context, PlaceholderActivity::class.java)
).setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
.build()
SplitManager.java / createSplit()
SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
placeholderActivityFilterSet,
new Intent(context, PlaceholderActivity.class)
).setDefaultSplitAttributes(splitAttributes)
.setMinWidthDp(840)
.setMinSmallestWidthDp(600)
.setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
.build();
SplitPlaceholderRule.Builder
crea y configura la regla:
placeholderActivityFilterSet
: Contiene filtros de actividad que determinan cuándo aplicar la regla mediante la identificación de actividades con las que se asocia la actividad del marcador de posición.Intent
: Especifica el inicio de la actividad de marcador de posición.setDefaultSplitAttributes
: Aplica los atributos de diseño a la regla.setMinWidthDp
: Establece el ancho de pantalla mínimo (en píxeles independientes de la densidad, dp) que permite una división.setMinSmallestWidthDp
: Establece el valor mínimo (en dp) que debe tener la menor de las dos dimensiones de pantalla para permitir una división, independientemente de la orientación del dispositivo.setFinishPrimaryWithPlaceholder
: Establece cómo el hecho de finalizar la actividad del marcador de posición afecta a las actividades del contenedor principalALWAYS
indica que el sistema siempre debe finalizar las actividades del contenedor principal cuando termina el marcador de posición (consulta Finalizar actividades).
- Agrega la regla a
RuleController
de WindowManager:
SplitManager.kt / createSplit()
ruleController.addRule(splitPlaceholderRule)
SplitManager.java / createSplit()
ruleController.addRule(splitPlaceholderRule);
Crea una regla de actividad
APIs requeridas:
Se puede usar ActivityRule
para definir una regla para una actividad que ocupa toda la ventana de tareas, como un diálogo modal (para obtener más información, consulta Ventana modal completa en la guía para desarrolladores sobre la Incorporación de actividades).
SplitPlaceholderRule.Builder
crea un SplitPlaceholderRule
. El compilador toma un conjunto de objetos ActivityFilter
como argumento. Los objetos especifican actividades con las que está asociada la regla de marcador de posición. Si el filtro coincide con una actividad iniciada, el sistema aplica la regla de marcador de posición.
Registras la regla con el componente RuleController
.
Para crear una regla de actividad haz lo siguiente:
- Crea un
ActivityFilter
:
SplitManager.kt / createSplit()
val summaryActivityFilter = ActivityFilter(
ComponentName(context, SummaryActivity::class.java),
null
)
SplitManager.java / createSplit()
ActivityFilter summaryActivityFilter = new ActivityFilter(
new ComponentName(context, SummaryActivity.class),
null
);
El filtro especifica la actividad para la que se aplica la regla, SummaryActivity
.
El filtro puede incluir una acción de intent (segundo parámetro) para el inicio de la actividad asociada (inicio de SummaryActivity
). Si incluyes una acción de intent, el filtro verifica la acción junto con el nombre de la actividad. Para las actividades de tu propia app, es probable que no filtres la acción de intent, por lo que el argumento puede ser nulo.
- Agrega el filtro a un conjunto de filtros:
SplitManager.kt / createSplit()
val summaryActivityFilterSet = setOf(summaryActivityFilter)
SplitManager.java / createSplit()
Set<ActivityFilter> summaryActivityFilterSet = new HashSet<>();
summaryActivityFilterSet.add(summaryActivityFilter);
- Crea un
ActivityRule
:
SplitManager.kt / createSplit()
val activityRule = ActivityRule.Builder(summaryActivityFilterSet)
.setAlwaysExpand(true)
.build()
SplitManager.java / createSplit()
ActivityRule activityRule = new ActivityRule.Builder(
summaryActivityFilterSet
).setAlwaysExpand(true)
.build();
ActivityRule.Builder
crea y configura la regla:
summaryActivityFilterSet
: Contiene filtros de actividad que determinan cuándo aplicar la regla mediante la identificación de actividades que deseas excluir de las divisiones.setAlwaysExpand
: Especifica si se debe expandir la actividad para que ocupe todo el espacio disponible de la pantalla.
- Agrega la regla a
RuleController
de WindowManager:
SplitManager.kt / createSplit()
ruleController.addRule(activityRule)
SplitManager.java / createSplit()
ruleController.addRule(activityRule);
¡Ejecútalo!
Compila y ejecuta la app de ejemplo.
La app debe comportarse de la misma manera que cuando se personaliza con un archivo de configuración XML.
Consulta "¡Ejecútalo!" en la sección "Configuración XML" de este codelab.
Crédito extra
Intenta configurar la relación de aspecto en la app de ejemplo con los métodos setMaxAspectRatioInPortrait
y setMaxAspectRatioInLandscape
de SplitPairRule.Builder
y SplitPlaceholderRule.Builder
. Especifica valores con las propiedades y los métodos de la clase EmbeddingAspectRatio
, por ejemplo:
SplitPairRule.Builder(filterSet)
. . .
.setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
. . .
.build()
Prueba la configuración con tu tablet grande o con el emulador de Pixel C.
Determina la relación de aspecto vertical de tu tablet grande (la relación de aspecto del Pixel C es un poco superior a 1.4). Establece la relación de aspecto máxima en orientación vertical para valores superiores e inferiores a la relación de aspecto de tu tablet o Pixel C. Prueba las propiedades ALWAYS_ALLOW
y ALWAYS_DISALLOW
.
Ejecuta la app y observa los resultados que obtienes.
Para obtener más información, consulta "Relación de aspecto" en la sección "Configuración XML" de este codelab.
7. Navegación de Material Design
Los lineamientos de Material Design especifican diferentes componentes de navegación para distintos tamaños de pantalla: un riel de navegación para pantallas de 840 dp o más de ancho, y una barra de navegación inferior para pantallas de menos de 840 dp.
Con la incorporación de actividades, no puedes usar los métodos WindowManager
getCurrentWindowMetrics()
y getMaximumWindowMetrics()
para determinar el ancho de pantalla porque las métricas de ventana que muestran los métodos describen el panel de visualización que contiene la actividad incorporada que llamó a los métodos.
Para obtener las dimensiones precisas de tu app de incorporación de actividades, utiliza una calculadora de atributos de división y SplitAttributesCalculatorParams.
Borra las siguientes líneas si las habías agregado en una sección anterior.
main_split_config.xml
<SplitPairRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow" // Delete this line.
window:splitMaxAspectRatioInLandscape="alwaysDisallow" // Delete this line.
. . .>
</SplitPairRule>
<SplitPlaceholderRule
. . .
window:splitMaxAspectRatioInPortrait="alwaysAllow" // Delete this line.
window:splitMaxAspectRatioInLandscape="alwaysDisallow" // Delete this line.
. . .>
<SplitPlaceholderRule/>
Navegación flexible
Para cambiar dinámicamente los componentes de navegación en función del tamaño de la pantalla, usa una calculadora de SplitAttributes
. Esta calculadora detecta los cambios en la orientación del dispositivo y el tamaño de la ventana, y recalcula las dimensiones de la pantalla de manera acorde. Integraremos una calculadora con SplitController
para activar los cambios de componentes de navegación en respuesta a las actualizaciones del tamaño de la pantalla.
Cómo crear un diseño de navegación
Primero, crea un menú que usaremos para completar el riel de navegación y la barra de navegación.
En la carpeta res/menu
, crea un nuevo archivo de recursos de menú llamado nav_menu.xml
. Reemplaza el contenido del archivo del menú por lo siguiente:
nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/navigation_home"
android:title="Home" />
<item
android:id="@+id/navigation_dashboard"
android:title="Dashboard" />
<item
android:id="@+id/navigation_settings"
android:title="Settings" />
</menu>
A continuación, agrega una barra de navegación y un riel de navegación al diseño. Establece la visibilidad en gone
para que estén ocultos al principio. Más adelante, los haremos visibles en función de las dimensiones del diseño.
activity_list.xml
<com.google.android.material.navigationrail.NavigationRailView
android:id="@+id/navigationRailView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/nav_menu"
android:visibility="gone" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:menu="@menu/nav_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="gone" />
Escribe una función que controle el cambio entre la barra y el riel de navegación.
ListActivity.kt / setWiderScreenNavigation()
private fun setWiderScreenNavigation(useNavRail: Boolean) {
val navRail: NavigationRailView = findViewById(R.id.navigationRailView)
val bottomNav: BottomNavigationView = findViewById(R.id.bottomNavigationView)
if (useNavRail) {
navRail.visibility = View.VISIBLE
bottomNav.visibility = View.GONE
} else {
navRail.visibility = View.GONE
bottomNav.visibility = View.VISIBLE
}
}
ListActivity.java / setWiderScreenNavigation()
private void setWiderScreenNavigation(boolean useNavRail) {
NavigationRailView navRail = findViewById(R.id.navigationRailView);
BottomNavigationView bottomNav = findViewById(R.id.bottomNavigationView);
if (useNavRail) {
navRail.setVisibility(View.VISIBLE);
bottomNav.setVisibility(View.GONE);
} else {
navRail.setVisibility(View.GONE);
bottomNav.setVisibility(View.VISIBLE);
}
}
Calculadora de atributos de división
SplitController
obtiene información sobre las divisiones de actividades activas en el momento y proporciona puntos de interacción para personalizar las divisiones y formar nuevas.
En secciones anteriores, establecimos los atributos predeterminados para las divisiones especificando splitRatio
y otros atributos en las etiquetas <SplitPairRule>
y <SplitPlaceHolderRule>
en los archivos XML, o bien usando las APIs de SplitPairRule.Builder#setDefaultSplitAttributes()
y SplitPlaceholderRule.Builder#setDefaultSplitAttributes()
.
Los atributos de división predeterminados se aplican si el elemento WindowMetrics del contenedor superior cumple con los requisitos de dimensión de SplitRule, que son minWidthDp, minHeightDp y minSmallestWidthDp.
Vamos a establecer una calculadora de atributos de división para reemplazar los atributos predeterminados. La calculadora actualiza los pares de división existentes después de un cambio en la ventana o en el estado del dispositivo, por ejemplo, cambios de orientación o estado de plegado.
Esto permite que los desarrolladores conozcan los estados del dispositivo o la ventana, y configuren diferentes atributos de división en distintos casos, incluidas las orientaciones vertical y horizontal, y la posición de mesa.
Cuando se crea una calculadora de atributos de división, la plataforma pasa un objeto SplitAttributesCalculatorParams
a la función setSplitAttributesCalculator()
. La propiedad parentWindowMetrics
brinda métricas de la ventana de la aplicación.
En el siguiente código, la actividad comprueba si se cumplió con las limitaciones predeterminadas: ancho > 840 dp y menor ancho > 600 dp. Si se cumplió con las condiciones, las actividades se incorporan en un diseño de panel doble y la app utiliza un riel de navegación en lugar de una barra de navegación inferior. De lo contrario, las actividades se muestran en pantalla completa con una barra de navegación inferior.
ListActivity.kt / onCreate()
SplitController.getInstance(this).setSplitAttributesCalculator {
params ->
if (params.areDefaultConstraintsSatisfied) {
// When default constraints are satisfied, use the navigation rail.
setWiderScreenNavigation(true)
return@setSplitAttributesCalculator params.defaultSplitAttributes
} else {
// Use the bottom navigation bar in other cases.
setWiderScreenNavigation(false)
// Expand containers if the device is in portrait or the width is less than 840 dp.
SplitAttributes.Builder()
.setSplitType(SPLIT_TYPE_EXPAND)
.build()
}
}
ListActivity.java / onCreate()
SplitController.getInstance(this).setSplitAttributesCalculator(params -> {
if (params.areDefaultConstraintsSatisfied()) {
// When default constraints are satisfied, use the navigation rail.
setWiderScreenNavigation(true);
return params.getDefaultSplitAttributes();
} else {
// Use the bottom navigation bar in other cases.
setWiderScreenNavigation(false);
// Expand containers if the device is in portrait or the width is less than 600 dp.
return new SplitAttributes.Builder()
.setSplitType(SplitType.SPLIT_TYPE_EXPAND)
.build();
}
});
¡Buen trabajo! Tu app de incorporación de actividades ahora sigue los lineamientos de navegación de Material Design.
8. ¡Felicitaciones!
¡Buen trabajo! Optimizaste una app que se basa en actividades para que tenga un diseño de lista-detalles en pantallas grandes y agregaste navegación de Material Design.
Aprendiste dos formas de implementar la incorporación de actividades:
- Con un archivo de configuración XML
- Con llamadas a la API de Jetpack
- Implementación de navegación flexible con la incorporación de actividades
Y no volviste a escribir el código fuente de Kotlin ni Java de la app.
Ya puedes optimizar tus apps de producción para pantallas grandes con incorporación de actividades.
9. Más información
- Guía para desarrolladores: Incorporación de actividades
- Documentación de referencia: androidx.window.embedding
- Codelab: Incorporación de actividades avanzada
- Código de muestra: Incorporación de actividades