Usa la biblioteca car-ui-lib
para iniciar infoentretenimiento autocoherente en el vehículo y con coherencia
(IVI). En este codelab, se presenta car-ui-lib
y cómo puedes
Usar superposiciones de recursos en tiempo de ejecución (RRO) para personalizar componentes de la biblioteca
Qué aprenderás
Aprenderás a hacer lo siguiente:
- Incluye componentes de
car-ui-lib
en tu app para Android. - Usa Gradle a fin de compilar apps para Android y RRO.
- Usa RRO con
car-ui-lib
.
En este codelab, no se detalla el funcionamiento de las RRO. Consulta Cambiar el valor de los recursos de una app en el tiempo de ejecución Soluciona problemas de superposiciones de recursos de tiempo de ejecución para obtener más información.
Antes de comenzar
Requisitos previos
Antes de comenzar, asegúrate de tener lo siguiente:
Computadora con línea de comandos (máquina Linux, Mac o Windows con Subsistema de Windows para Linux).
Emulador o dispositivo Android conectado a tu equipo Consulta Descarga el código fuente de Android y Compila Android.
Conocimientos básicos de RRO
Cómo crear una app para Android nueva
Duración: 15 minutos
En esta sección, crearás un nuevo proyecto de Android Studio.
En Android Studio, crea una app con un
EmptyActivity
.Figura 1: Crea una actividad vacía Asígnale el nombre
CarUiCodelab
a la app y, luego, selecciona el lenguaje Java. Puedes también selecciona una ubicación de archivo si lo deseas. Acepta los valores predeterminados de parámetros de configuración restantes.Figura 2: Asígnale un nombre a tu app Reemplaza
activity_main.xml
por el siguiente bloque de código:<?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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sample_text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Este bloque de código muestra la cadena
sample_text
, que no está definida.Agrega la cadena de recurso
sample_text
y establécela en “Hello World!”. en tu archivostrings.xml
. Para abrir este archivo, selecciona aplicación > src > principal > res > valores > strings.xml<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CarUiCodelab</string> <string name="sample_text">Hello World!</string> </resources>
Para compilar tu app, haz clic en el botón verde Play ubicado en la parte superior derecha. Hacerlo instala automáticamente el apk en tu emulador o dispositivo Android a través de Gradle
La app nueva debería abrirse automáticamente en el emulador o dispositivo Android. Si
no, abre la app de CarUiCodelab
desde el selector de aplicaciones, que ahora está instalado.
Se ve así:
![Abrir nueva app de CarUiCodelab](https://source.android.com/static/docs/automotive/images/codelab_04.png?hl=es-419)
Agrega car-ui-lib a tu app para Android
Duración: 15 minutos
Agrega car-ui-lib
a tu app:
Para agregar la dependencia
car-ui-lib
al archivobuild.gradle
de tu proyecto, haz lo siguiente: selecciona Aplicación > build.gradle. Tus dependencias deberían aparecer así:dependencies { implementation 'com.android.car.ui:car-ui-lib:2.0.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' }
Cómo usar componentes car-ui-lib en tu app para Android
Ahora que tienes car-ui-lib
, agrega una barra de herramientas a tu app.
En tu archivo
MainActivity.java
, reemplaza el métodoonCreate
:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get the toolbar controller instance. ToolbarController toolbar = CarUi.getToolbar(this); // Set the title on toolbar. toolbar.setTitle(getTitle()); // Set the logo to be shown with the title. toolbar.setLogo(R.mipmap.ic_launcher_round); }
Asegúrate de importar
ToolbarController
:import com.android.car.ui.core.CarUi; import com.android.car.ui.toolbar.ToolbarController;
Para usar el tema
Theme.CarUi.WithToolbar
, selecciona app > src > principal > AndroidManifest.xml y, luego, actualizaAndroidManifest.xml
se muestre de la siguiente manera:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.caruicodelab"> <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.CarUi.WithToolbar" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Para compilar la app, presiona el botón verde Play, igual que antes.
Agrega RRO a tu app
Duración: 30 minutos
Si ya conoces las RRO, ve a la siguiente sección, Agrega un controlador de permisos a tu app. De lo contrario, para conocer los conceptos básicos de las RRO, consulta Cambia el valor de los recursos de una app en el tiempo de ejecución.
Cómo agregar un controlador de permisos a tu app
Para controlar a qué recursos se superpone un paquete RRO, agrega un archivo llamado
overlayable.xml
a la carpeta /res
de tu app. Este archivo funciona como un permiso
entre tu app (el objetivo) y tu paquete de RRO (la superposición).
Agrega
res/values/overlayable.xml
a tu app y copia el siguiente contenido en tu archivo:<?xml version="1.0" encoding="utf-8"?> <resources> <overlayable name="CarUiCodelab"> <policy type="public"> <item type="string" name="sample_text"/> </policy> </overlayable> </resources>
Dado que una RRO debe poder superponer la cadena
sample_text
, incluye el elemento nombre del recurso en el archivo Overlayable.xml de la app.Tu archivo
overlayable.xml
DEBE residir enres/values/
. Si no es así, elOverlayManagerService
no puede localizarlo.Para obtener más información sobre los recursos superpuestos y cómo se pueden consulta Cómo restringir el contenido recursos.
Crea un paquete RRO
En esta sección, crearás un paquete RRO para cambiar la cadena que se muestra arriba. de "Hello World!" por “Hello World RRO”.
Para crear un proyecto nuevo, selecciona Archivo > Nuevo > Nuevo proyecto. Asegúrate de selecciona No Activity en lugar de Empty Activity, ya que los paquetes de RRO contienen solo recursos.
Tus configuraciones tienen un aspecto similar a las que se muestran a continuación. El la ubicación en la que se guardan puede diferir:
Después de crear el proyecto
CarUiRRO
nuevo, decláralo como un ModificaAndroidManifest.xml
para la RRO.<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.caruirro"> <application android:hasCode="false" /> <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/> <overlay android:targetPackage="com.example.caruicodelab" android:targetName="CarUiCodelab" android:isStatic="false" android:resourcesMap="@xml/sample_overlay" /> </manifest>
Esto crea un error con
@xml/sample_overlay
. ElresourcesMap
asigna nombres de recursos del paquete de destino al paquete RRO.Copia el siguiente bloque de código en
…/res/xml/sample_overlay.xml
:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> </overlay>
Agrega
sample_text
a…/res/values/strings.xml
:<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CarUiRRO</string> <string name="sample_text">Hello World RRO</string> </resources>
Para compilar tu objetivo de RRO, presiona el botón verde Play para crear un Gradle. compilación de tu RRO en tu emulador o dispositivo Android.
Para verificar que la RRO esté instalada correctamente, ejecuta el siguiente comando:
shell:~$ adb shell cmd overlay list --user current | grep -i com.example com.example.caruicodelab [ ] com.example.caruirro
Este comando muestra información útil sobre el estado de los paquetes RRO en el sistema.
[ ]
indica que la RRO está instalada y lista para activarse.---
indica que la RRO está instalada, pero contiene errores.[X]
significa que la RRO está instalada y activada.
Si tu RRO tiene errores, consulta Soluciona problemas de superposiciones de recursos de tiempo de ejecución antes de continuar.
Para habilitar la RRO y verificar que esté habilitada, haz lo siguiente:
shell:~$ adb shell cmd overlay enable --user current com.example.caruirro shell:~$ adb shell cmd overlay list --user current | grep -i com.example com.example.caruicodelab [x] com.example.caruirro
Tu app muestra la string “Hello World RRO”.
![Hola mundo RRO:](https://source.android.com/static/docs/automotive/images/codelab_09.png?hl=es-419)
¡Felicitaciones! Creaste tu primera RRO.
Cuando uses RRO, te recomendamos que uses Android Asset Packaging Tool (AAPT2)
las marcas --no-resource-deduping
y --no-resource-removal
, descritas en
Opciones de vinculación.
No es necesario agregar las marcas de este codelab, pero te sugerimos que las uses
en tus RRO para evitar la eliminación de recursos (y problemas de depuración). Tú
puedes agregarlas al archivo build.gradle
de tu RRO de la siguiente manera:
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
Para obtener más información sobre estas marcas, consulta Compila el paquete y AAPT2.
Modifica los componentes de car-ui-lib
usando RRO en tu app para Android
En esta página, se describe cómo puedes usar una superposición de recursos de entorno de ejecución (RRO) para
modificar componentes de la biblioteca car-ui-lib
en tu app para Android
Cómo establecer el color de fondo de la barra de herramientas
Duración: 15 minutos
Para cambiar el color de fondo de la barra de herramientas:
Agrega el siguiente valor a tu app de RRO y establece el recurso en Bright verde (
#0F0
):<?xml version="1.0" encoding="utf-8"?> <resources> <drawable name="car_ui_toolbar_background">#0F0</drawable> </resources>
La biblioteca
car-ui-lib
contiene un recurso llamadocar_ui_toolbar_background
Cuando este recurso esté contenido en el de un RRO, la barra de herramientas no cambia porque el valor está orientado.En el
AndroidManifest.xml
de tu RRO, actualizatargetName
para que apunte acar-ui-lib
:… android:targetName="car-ui-lib" …
DEBES crear un paquete RRO nuevo para cada paquete de destino que desees RRO. Por ejemplo, al crear superposiciones para dos objetivos diferentes, debes crear dos APK superpuestos.
Compila, verifica, instala y habilita la RRO de la misma manera que antes.
Tu app se ve de la siguiente manera:
![Nuevo color de fondo de la barra de herramientas](https://source.android.com/static/docs/automotive/images/codelab_10.png?hl=es-419)
Diseños y estilos de RRO
Duración: 15 minutos
En este ejercicio, compilarás una app nueva similar a la que creaste anteriormente. Esta permite superponer el diseño. Sigue los mismos pasos que antes o modifica tu app existente.
Asegúrate de agregar las siguientes líneas a
overlayable.xml
:<?xml version="1.0" encoding="utf-8"?> <resources> <overlayable name="CarUiCodelab"> <policy type="public"> <item type="string" name="sample_text"/> <item type="layout" name="activity_main"/> <item type="id" name="textView"/> </policy> </overlayable> </resources>
Asegúrate de que
activity_main.xml
se muestre de la siguiente manera:<?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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sample_text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
En tu app de RRO, crea un
res/layout/activity_main.xml
y agrega el lo siguiente:<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/sample_text" android:textAppearance="@style/TextAppearance.CarUi" android:layout_gravity="center_vertical|center_horizontal"/> </FrameLayout>
Actualiza
res/values/styles.xml
para agregar nuestro estilo a la RRO:<?xml version="1.0" encoding="utf-8"?> <resources> <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault"> <item name="android:textColor">#0f0</item> <item name="android:textSize">100sp</item> </style> </resources>
Cambia la
targetName
deAndroidManifest.xml
para que apunte al nombre de tu nueva app:… android:targetName="CarUiCodelab" …
Agrega los recursos al archivo
sample_overlay.xml
en tu RRO:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> <item target="id/textView" value="@id/textView"/> <item target="layout/activity_main" value="@layout/activity_main"/> </overlay>
Compila e instala la app y la RRO de la misma manera que antes (Play verde de color verde). ). Asegúrate de habilitar tu RRO.
La app y la RRO se renderizan de la siguiente manera. El texto de la RRO de Hello World es verde y es centrado, como se especifica en la RRO de diseño.
![RRO de Hello World](https://source.android.com/static/docs/automotive/images/codelab_11.png?hl=es-419)
Cómo agregar CarUiRecyclerView a tu app
Duración: 15 minutos
La interfaz de CarUiRecyclerView
proporciona APIs para acceder a un RecyclerView
que se personaliza a través de los recursos de car-ui-lib
. Por ejemplo, CarUiRecyclerView
.
Verifica una marca en el tiempo de ejecución para determinar si la barra de desplazamiento debe estar habilitada o no.
y selecciona el diseño correspondiente.
![CarUiRecyclerViewContainer](https://source.android.com/static/docs/automotive/images/codelab_12.png?hl=es-419)
Para agregar un
CarUiRecyclerView
, agrégalo a tuactivity_main.xml
yMainActivity.java
. Puedes crear una app nueva desde cero modificar la app existente. Si modificas la app existente, asegúrate de quitarla recursos no declarados enoverlayable.xml
.activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <com.android.car.ui.recyclerview.CarUiRecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent"/>
Es posible que aparezca el siguiente error, que puedes ignorar:
Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerView
Siempre y cuando la clase esté escrita correctamente y hayas agregado
car-ui-lib
una dependencia, puedes crear y compilar tu APK. Para quitar el error, Selecciona Archivo > Invalida cachés y, luego, haz clic en Invalidar y reiniciar.Agrega lo siguiente a
MainActivity.java
package com.example.caruicodelab; import android.app.Activity; import android.os.Bundle; import com.android.car.ui.core.CarUi; import com.android.car.ui.recyclerview.CarUiContentListItem; import com.android.car.ui.recyclerview.CarUiListItem; import com.android.car.ui.recyclerview.CarUiListItemAdapter; import com.android.car.ui.recyclerview.CarUiRecyclerView; import com.android.car.ui.toolbar.ToolbarController; import java.util.ArrayList; /** Activity with a simple car-ui layout. */ public class MainActivity extends Activity { private final ArrayList<CarUiListItem> mData = new ArrayList<>(); private CarUiListItemAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ToolbarController toolbar = CarUi.getToolbar(this); toolbar.setTitle(getTitle()); toolbar.setLogo(R.mipmap.ic_launcher_round); CarUiRecyclerView recyclerView = findViewById(R.id.list); mAdapter = new CarUiListItemAdapter(generateSampleData()); recyclerView.setAdapter(mAdapter); } private ArrayList<CarUiListItem> generateSampleData() { for (int i = 0; i < 20; i++) { CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.ICON); item.setTitle("Title " + i); item.setPrimaryIconType(CarUiContentListItem.IconType.CONTENT); item.setIcon(getDrawable(R.drawable.ic_launcher_foreground)); item.setBody("body " + i); mData.add(item); } return mData; }
Compila e instala tu app como lo hiciste antes.
Ahora ves un CarUiRecyclerView
:
![CarUiRecyclerView](https://source.android.com/static/docs/automotive/images/codelab_13.png?hl=es-419)
Cómo usar un RRO para quitar la barra de desplazamiento
Duración: 10 minutos
En este ejercicio, se muestra cómo usar una RRO para quitar la barra de desplazamiento de
CarUiRecyclerView
En tu RRO, agrega y modifica los siguientes archivos:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.caruirro"> <application android:hasCode="false" /> <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/> <overlay android:targetPackage="com.example.caruicodelab" android:targetName="car-ui-lib" android:isStatic="false" android:resourcesMap="@xml/sample_overlay" /> </manifest>
res/values/bools.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <bool name="car_ui_scrollbar_enable">false</bool> </resources>
El recurso
car_ui_scrollbar_enable
es un recurso booleanocar-ui-lib
, que controla si la barra de desplazamiento optimizó el vehículo con los botones Arriba y Abajo enCarUiRecyclerView
está presente o no. Cuando se establece enfalse
,CarUiRecyclerView
funciona como unRecyclerView
de AndroidX.res/xml/sample_overlay.xml
<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="bool/car_ui_scrollbar_enable" value="@bool/car_ui_scrollbar_enable"/> </overlay>
Compila e instala tu app como lo hiciste antes. La barra de desplazamiento ya no está disponible
CarUiRecyclerView
:
![CarUiRecyclerView sin barra de desplazamiento](https://source.android.com/static/docs/automotive/images/codelab_14.png?hl=es-419)
Cómo usar un diseño para superponer la barra de desplazamiento de CarUiRecyclerView
Duración: 15 minutos
En este ejercicio, modificarás el diseño de la barra de desplazamiento CarUiRecyclerView
.
Agrega y modifica los siguientes archivos en tu app de RRO.
res/layout/car_ui_recycler_view_scrollbar.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="112dp" android:layout_height="match_parent" android:id="@+id/car_ui_scroll_bar"> <!-- View height is dynamically calculated during layout. --> <View android:id="@+id/car_ui_scrollbar_thumb" android:layout_width="6dp" android:layout_height="20dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:background="@drawable/car_ui_recyclerview_scrollbar_thumb"/> <View android:id="@+id/car_ui_scrollbar_track" android:layout_width="10dp" android:layout_height="match_parent" android:layout_marginTop="10dp" android:layout_centerHorizontal="true" android:layout_above="@+id/car_ui_scrollbar_page_up"/> <View android:layout_width="2dp" android:layout_height="match_parent" android:layout_marginTop="10dp" android:background="#323232" android:layout_toLeftOf="@+id/car_ui_scrollbar_thumb" android:layout_above="@+id/car_ui_scrollbar_page_up" android:layout_marginRight="5dp"/> <View android:layout_width="2dp" android:layout_height="match_parent" android:layout_marginTop="10dp" android:background="#323232" android:layout_toRightOf="@+id/car_ui_scrollbar_thumb" android:layout_above="@+id/car_ui_scrollbar_page_up" android:layout_marginLeft="5dp"/> <ImageView android:id="@+id/car_ui_scrollbar_page_up" android:layout_width="75dp" android:layout_height="75dp" android:focusable="false" android:hapticFeedbackEnabled="false" android:src="@drawable/car_ui_recyclerview_ic_up" android:scaleType="centerInside" android:background="?android:attr/selectableItemBackgroundBorderless" android:layout_centerHorizontal="true" android:layout_above="@+id/car_ui_scrollbar_page_down"/> <ImageView android:id="@+id/car_ui_scrollbar_page_down" android:layout_width="75dp" android:layout_height="75dp" android:focusable="false" android:hapticFeedbackEnabled="false" android:src="@drawable/car_ui_recyclerview_ic_down" android:scaleType="centerInside" android:background="?android:attr/selectableItemBackgroundBorderless" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true"/> </RelativeLayout>
Para superponer un archivo de diseño, debes agregar todos los IDs y el espacio de nombres a la
overlay.xml
de tu RRO. Consulta los archivos que aparecen a continuación.res/xml/sample_overlay.xml
<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="drawable/car_ui_recyclerview_ic_down" value="@drawable/car_ui_recyclerview_ic_down"/> <item target="drawable/car_ui_recyclerview_ic_up" value="@drawable/car_ui_recyclerview_ic_up"/> <item target="drawable/car_ui_recyclerview_scrollbar_thumb" value="@drawable/car_ui_recyclerview_scrollbar_thumb"/> <item target="id/car_ui_scroll_bar" value="@id/car_ui_scroll_bar"/> <item target="id/car_ui_scrollbar_thumb" value="@id/car_ui_scrollbar_thumb"/> <item target="id/car_ui_scrollbar_track" value="@id/car_ui_scrollbar_track"/> <item target="id/car_ui_scrollbar_page_up" value="@id/car_ui_scrollbar_page_up"/> <item target="id/car_ui_scrollbar_page_down" value="@id/car_ui_scrollbar_page_down"/> <item target="layout/car_ui_recyclerview_scrollbar" value="@layout/car_ui_recyclerview_scrollbar"/> </overlay>
res/drawable/car_ui_recyclerview_ic_up.xml
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> <path android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z" android:fillColor="#0000FF"/> </vector>
res/drawable/car_ui_recyclerview_ic_down.xml
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> <path android:pathData="M14.83,16.42L24,25.59l9.17,-9.17L36,19.25l-12,12 -12,-12z" android:fillColor="#0000FF"/> </vector>
res/drawable/car_ui_recyclerview_scrollbar_thumb.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#0000FF" /> <corners android:radius="100dp"/> </shape>
Se sugiere examinar cómo interactúan estos archivos.
Para simplificar, las dimensiones y los colores están codificados. Sin embargo, una mejor la práctica es declarar estos valores en
dimens.xml
ycolors.xml
, o designados como archivos de color en la carpetares/color/
. Para obtener más información, ver Estilo de código Java del AOSP para colaboradores.Compila e instala tu app como lo hiciste antes. Compilaste
CarUiRecyclerView
con una barra de desplazamiento azul y rieles grises.
¡Felicitaciones! Ambas flechas aparecen en la parte inferior de la barra de desplazamiento,
aplicó correctamente un RRO a un archivo de recursos de diseño car-ui-lib
con la compilación de Gradle
del sistema con Android Studio.
![CarUiRecyclerView con una barra de desplazamiento azul con rieles grises](https://source.android.com/static/docs/automotive/images/codelab_15.png?hl=es-419)
Elementos de la lista de RRO
Duración: 15 minutos
Hasta ahora, aplicaste una RRO a los componentes de car-ui-lib
usando un framework
(no de AndroidX). Para usar componentes de AndroidX en una RRO, debes agregar
las dependencias de ese componente a la app y a la RRO. build.gradle.
También debes agregar el attrs
de ese componente a overlayable.xml
en tu app.
como sample_overlay.xml
en tu RRO.
Nuestra biblioteca (car-ui-lib
) usa ConstraintLayout
y otros formatos de AndroidX
por lo que su overlayable.xml
podría verse de la siguiente manera:
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<overlayable name="car-ui-lib">
…
<item type="attr" name="layout_constraintBottom_toBottomOf"/>
<item type="attr" name="layout_constraintBottom_toTopOf"/>
<item type="attr" name="layout_constraintCircle"/>
<item type="attr" name="layout_constraintCircleAngle"/>
<item type="attr" name="layout_constraintCircleRadius"/>
<item type="attr" name="layout_constraintDimensionRatio"/>
<item type="attr" name="layout_constraintEnd_toEndOf"/>
<item type="attr" name="layout_constraintEnd_toStartOf"/>
<item type="attr" name="layout_constraintGuide_begin"/>
<item type="attr" name="layout_constraintGuide_end"/>
<item type="attr" name="layout_constraintGuide_percent"/>
<item type="attr" name="layout_constraintHeight_default"/>
<item type="attr" name="layout_constraintHeight_max"/>
<item type="attr" name="layout_constraintHeight_min"/>
<item type="attr" name="layout_constraintHeight_percent"/>
<item type="attr" name="layout_constraintHorizontal_bias"/>
<item type="attr" name="layout_constraintHorizontal_chainStyle"/>
<item type="attr" name="layout_constraintHorizontal_weight"/>
<item type="attr" name="layout_constraintLeft_creator"/>
<item type="attr" name="layout_constraintLeft_toLeftOf"/>
<item type="attr" name="layout_constraintLeft_toRightOf"/>
<item type="attr" name="layout_constraintRight_creator"/>
<item type="attr" name="layout_constraintRight_toLeftOf"/>
<item type="attr" name="layout_constraintRight_toRightOf"/>
<item type="attr" name="layout_constraintStart_toEndOf"/>
<item type="attr" name="layout_constraintStart_toStartOf"/>
<item type="attr" name="layout_constraintTag"/>
<item type="attr" name="layout_constraintTop_creator"/>
<item type="attr" name="layout_constraintTop_toBottomOf"/>
<item type="attr" name="layout_constraintTop_toTopOf"/>
<item type="attr" name="layout_constraintVertical_bias"/>
<item type="attr" name="layout_constraintVertical_chainStyle"/>
…
</overlayable>
</resources>
Cambia el diseño de los elementos de lista en el
CarUiRecyclerView
conConstraintLayout
Agrega o modifica los siguientes archivos en tu RRO:res/xml/sample_overlay.xml
<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="id/car_ui_list_item_touch_interceptor" value="@id/car_ui_list_item_touch_interceptor"/> <item target="id/car_ui_list_item_reduced_touch_interceptor" value="@id/car_ui_list_item_reduced_touch_interceptor"/> <item target="id/car_ui_list_item_start_guideline" value="@id/car_ui_list_item_start_guideline"/> <item target="id/car_ui_list_item_icon_container" value="@id/car_ui_list_item_icon_container"/> <item target="id/car_ui_list_item_icon" value="@id/car_ui_list_item_icon"/> <item target="id/car_ui_list_item_content_icon" value="@id/car_ui_list_item_content_icon"/> <item target="id/car_ui_list_item_avatar_icon" value="@id/car_ui_list_item_avatar_icon"/> <item target="id/car_ui_list_item_title" value="@id/car_ui_list_item_title"/> <item target="id/car_ui_list_item_body" value="@id/car_ui_list_item_body"/> <item target="id/car_ui_list_item_action_container_touch_interceptor" value="@id/car_ui_list_item_action_container_touch_interceptor"/> <item target="id/car_ui_list_item_action_container" value="@id/car_ui_list_item_action_container"/> <item target="id/car_ui_list_item_action_divider" value="@id/car_ui_list_item_action_divider"/> <item target="id/car_ui_list_item_switch_widget" value="@id/car_ui_list_item_switch_widget"/> <item target="id/car_ui_list_item_checkbox_widget" value="@id/car_ui_list_item_checkbox_widget"/> <item target="id/car_ui_list_item_radio_button_widget" value="@id/car_ui_list_item_radio_button_widget"/> <item target="id/car_ui_list_item_supplemental_icon" value="@id/car_ui_list_item_supplemental_icon"/> <item target="id/car_ui_list_item_end_guideline" value="@id/car_ui_list_item_end_guideline"/> <item target="attr/layout_constraintBottom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/> <item target="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintBottom_toTopOf"/> <item target="attr/layout_constraintEnd_toEndOf" value="@attr/layout_constraintEnd_toEndOf"/> <item target="attr/layout_constraintEnd_toStartOf" value="@attr/layout_constraintEnd_toStartOf"/> <item target="attr/layout_constraintGuide_begin" value="@attr/layout_constraintGuide_begin"/> <item target="attr/layout_constraintGuide_end" value="@attr/layout_constraintGuide_end"/> <item target="attr/layout_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/> <item target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_toLeftOf"/> <item target="attr/layout_constraintLeft_toRightOf" value="@attr/layout_constraintLeft_toRightOf"/> <item target="attr/layout_constraintRight_toLeftOf" value="@attr/layout_constraintRight_toLeftOf"/> <item target="attr/layout_constraintRight_toRightOf" value="@attr/layout_constraintRight_toRightOf"/> <item target="attr/layout_constraintStart_toEndOf" value="@attr/layout_constraintStart_toEndOf"/> <item target="attr/layout_constraintStart_toStartOf" value="@attr/layout_constraintStart_toStartOf"/> <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf"/> <item target="attr/layout_constraintTop_toTopOf" value="@attr/layout_constraintTop_toTopOf"/> <item target="attr/layout_goneMarginBottom" value="@attr/layout_goneMarginBottom"/> <item target="attr/layout_goneMarginEnd" value="@attr/layout_goneMarginEnd"/> <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginLeft"/> <item target="attr/layout_goneMarginRight" value="@attr/layout_goneMarginRight"/> <item target="attr/layout_goneMarginStart" value="@attr/layout_goneMarginStart"/> <item target="attr/layout_goneMarginTop" value="@attr/layout_goneMarginTop"/> <item target="attr/layout_constraintVertical_chainStyle" value="@attr/layout_constraintVertical_chainStyle"/> <item target="layout/car_ui_list_item" value="@layout/car_ui_list_item"/> </overlay>
res/layout/car_ui_list_item.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" android:layout_width="match_parent" android:layout_height="wrap_content" android:tag="carUiListItem" android:minHeight="@dimen/car_ui_list_item_height"> <!-- The following touch interceptor views are sized to encompass the specific sub-sections of the list item view to easily control the bounds of a background ripple effects. --> <com.android.car.ui.SecureView android:id="@+id/car_ui_list_item_touch_interceptor" android:layout_width="0dp" android:layout_height="0dp" android:background="@drawable/car_ui_list_item_background" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- This touch interceptor does not include the action container --> <com.android.car.ui.SecureView android:id="@+id/car_ui_list_item_reduced_touch_interceptor" android:layout_width="0dp" android:layout_height="0dp" android:background="@drawable/car_ui_list_item_background" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/car_ui_list_item_action_container" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/car_ui_list_item_start_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_begin="@dimen/car_ui_list_item_start_inset" /> <FrameLayout android:id="@+id/car_ui_list_item_icon_container" android:layout_width="@dimen/car_ui_list_item_icon_container_width" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="@+id/car_ui_list_item_start_guideline" app:layout_constraintTop_toTopOf="parent"> <ImageView android:id="@+id/car_ui_list_item_icon" android:layout_width="@dimen/car_ui_list_item_icon_size" android:layout_height="@dimen/car_ui_list_item_icon_size" android:layout_gravity="center" android:visibility="gone" android:scaleType="fitCenter" /> <ImageView android:id="@+id/car_ui_list_item_content_icon" android:layout_width="@dimen/car_ui_list_item_content_icon_width" android:layout_height="@dimen/car_ui_list_item_content_icon_height" android:layout_gravity="center" android:visibility="gone" android:scaleType="fitCenter" /> <ImageView android:id="@+id/car_ui_list_item_avatar_icon" android:background="@drawable/car_ui_list_item_avatar_icon_outline" android:layout_width="@dimen/car_ui_list_item_avatar_icon_width" android:layout_height="@dimen/car_ui_list_item_avatar_icon_height" android:layout_gravity="center" android:visibility="gone" android:scaleType="fitCenter" /> </FrameLayout> <CarUiTextView android:id="@+id/car_ui_list_item_title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin" android:singleLine="@bool/car_ui_list_item_single_line_title" android:textAppearance="@style/TextAppearance.CarUi.ListItem" android:layout_gravity="right" android:gravity="right" android:textAlignment="viewEnd" app:layout_constraintBottom_toTopOf="@+id/car_ui_list_item_body" app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container" app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" /> <CarUiTextView android:id="@+id/car_ui_list_item_body" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin" android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body" android:layout_gravity="right" android:gravity="right" android:textAlignment="viewEnd" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container" app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container" app:layout_constraintTop_toBottomOf="@+id/car_ui_list_item_title" app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" /> <!-- This touch interceptor is sized and positioned to encompass the action container --> <com.android.car.ui.SecureView android:id="@+id/car_ui_list_item_action_container_touch_interceptor" android:layout_width="0dp" android:layout_height="0dp" android:background="@drawable/car_ui_list_item_background" android:visibility="gone" app:layout_constraintBottom_toBottomOf="@id/car_ui_list_item_action_container" app:layout_constraintEnd_toEndOf="@id/car_ui_list_item_action_container" app:layout_constraintStart_toStartOf="@id/car_ui_list_item_action_container" app:layout_constraintTop_toTopOf="@id/car_ui_list_item_action_container" /> <FrameLayout android:id="@+id/car_ui_list_item_action_container" android:layout_width="wrap_content" android:minWidth="@dimen/car_ui_list_item_icon_container_width" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/car_ui_list_item_end_guideline" app:layout_constraintTop_toTopOf="parent"> <View android:id="@+id/car_ui_list_item_action_divider" android:layout_width="@dimen/car_ui_list_item_action_divider_width" android:layout_height="@dimen/car_ui_list_item_action_divider_height" android:layout_gravity="start|center_vertical" android:background="@drawable/car_ui_list_item_divider" /> <Switch android:id="@+id/car_ui_list_item_switch_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:clickable="false" android:focusable="false" /> <CheckBox android:id="@+id/car_ui_list_item_checkbox_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:clickable="false" android:focusable="false" /> <RadioButton android:id="@+id/car_ui_list_item_radio_button_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:clickable="false" android:focusable="false" /> <ImageView android:id="@+id/car_ui_list_item_supplemental_icon" android:layout_width="@dimen/car_ui_list_item_supplemental_icon_size" android:layout_height="@dimen/car_ui_list_item_supplemental_icon_size" android:layout_gravity="center" android:scaleType="fitCenter" /> </FrameLayout> <androidx.constraintlayout.widget.Guideline android:id="@+id/car_ui_list_item_end_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" /> </androidx.constraintlayout.widget.ConstraintLayout>
car_ui_list_item.xml
hace referencia a varias referencias de varios componentes/ que no se incluyen como dependencias de la app. Estos soncar-ui-lib
recursos. Puedes solucionar este problema agregandocar-ui-lib
como una dependencia a tu app de RRO enapp/build.gradle
:dependencies { implementation 'com.android.car.ui:car-ui-lib:2.0.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.4.0' }
El título y el cuerpo ahora están alineados a la derecha en lugar de a la izquierda.
![Título y cuerpo alineados a la derecha](https://source.android.com/static/docs/automotive/images/codelab_16.png?hl=es-419)
Solo aplicamos un RRO a car-ui-lib
con componentes de AndroidX
(ConstraintLayout
) cuando sus atributos estaban presentes en el car-ui-lib
llamado overlayable.xml
, así como la RRO sample_overlay.xml
. Es
hacer algo similar en tu propia aplicación. Simplemente agrega todas las
attrs
al overlayable.xml
de tu app, de manera similar a car-ui-lib
Sin embargo, no es posible RRO una app que use componentes de AndroidX cuando
la app tiene car-ui-lib
como dependencia en su build.gradle
(cuando la app usa
car-ui-lib
). Dado que las asignaciones de atributos ya se definieron en
el archivo overlayable.xml
de la biblioteca de car-ui-lib
y los agregarás a tu
overlayable.xml
de la app con car-ui-lib
como dependencia generaría una
mergeDebugResources
error como el siguiente. Esto se debe a que estos atributos
están presentes en varios archivos overlayable.xml
:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'