Use a biblioteca car-ui-lib
para iniciar sistemas de infoentretenimento
(IVI) autoconsistentes no veículo. Este codelab apresenta o car-ui-lib
e como
usar sobreposições de recursos de execução (RROs, na sigla em inglês) para personalizar componentes na biblioteca.
O que você vai aprender
Como:
- Inclua componentes
car-ui-lib
no app Android. - Use o Gradle para criar apps Android e RROs.
- Use RROs com
car-ui-lib
.
Este codelab não detalha como os RROs funcionam. Consulte Mudar o valor dos recursos de um app durante a execução e Resolver problemas de sobreposições de recursos de execução para saber mais.
Antes de começar
Pré-requisitos
Antes de começar, verifique se você tem:
Computador com linha de comando (máquina Linux, Mac ou Windows com o Subsystem para Linux).
Dispositivo ou emulador Android conectado à máquina. Consulte Fazer o download da origem do Android e Criar o Android.
Conhecimento básico de RROs.
Criar um novo app Android
Duração:15 minutos
Nesta seção, você vai criar um novo projeto do Android Studio.
No Android Studio, crie um app com um
EmptyActivity
.Figura 1.Criar uma atividade vazia Dê o nome
CarUiCodelab
ao app e selecione a linguagem Java. Você também pode selecionar um local de arquivo, se quiser. Aceite os valores padrão para as demais configurações.Figura 2. Nomear o app Substitua
activity_main.xml
pelo seguinte bloco 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>
Esse bloco de código mostra a string
sample_text
, que não está definida.Adicione a string de recurso
sample_text
e defina-a como "Hello World!" no arquivostrings.xml
. Para abrir esse arquivo, selecione app > src > main > res > values > 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 criar o app, clique no botão verde Play no canto superior direito. Isso instala automaticamente o APK no emulador ou dispositivo Android pelo Gradle.
O novo app será aberto automaticamente no emulador ou dispositivo Android. Caso
não, abra o app CarUiCodelab
no Acesso rápido aos apps, que agora está instalado.
Ela é assim:

Adicionar a car-ui-lib ao seu app Android
Duração:15 minutos
Adicione car-ui-lib
ao app:
Para adicionar a dependência
car-ui-lib
ao arquivobuild.gradle
do projeto, selecione app > build.gradle. As dependências vão aparecer assim: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' }
Usar componentes da car-ui-lib no seu app Android
Agora que você tem car-ui-lib
, adicione uma barra de ferramentas ao app.
No arquivo
MainActivity.java
, substitua o 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); }
Importe
ToolbarController
:import com.android.car.ui.core.CarUi; import com.android.car.ui.toolbar.ToolbarController;
Para usar o tema
Theme.CarUi.WithToolbar
, selecione app > src > main > AndroidManifest.xml e atualizeAndroidManifest.xml
para que apareça da seguinte maneira:<?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 criar o app, pressione o botão verde Play como antes.
Adicionar RROs ao app
Duração:30 minutos
Se você já conhece as RROs, acesse a próxima seção, Adicionar um controlador de permissão ao app. Caso contrário, para aprender o básico sobre RROs, consulte Mudar o valor dos recursos de um app durante a execução.
Adicionar um controlador de permissões ao app
Para controlar quais recursos um pacote RRO sobrepõe, adicione um arquivo chamado
overlayable.xml
à pasta /res
do app. Esse arquivo serve como um controlador
de permissão entre o app (o destino) e o pacote RRO (a sobreposição).
Adicione
res/values/overlayable.xml
ao app e copie o conteúdo a seguir no arquivo:<?xml version="1.0" encoding="utf-8"?> <resources> <overlayable name="CarUiCodelab"> <policy type="public"> <item type="string" name="sample_text"/> </policy> </overlayable> </resources>
Como a string
sample_text
precisa ser sobreposta por um RRO, inclua o nome do recurso no overlayable.xml do app.O arquivo
overlayable.xml
PRECISA estar emres/values/
. Caso contrário, oOverlayManagerService
não vai conseguir localizá-lo.Para saber mais sobre recursos sobrepostos e como eles podem ser configurados, consulte Restringir recursos sobrepostos.
Criar um pacote de RRO
Nesta seção, você vai criar um pacote RRO para mudar a string exibida acima de "Hello World!" para "Hello World RRO".
Para criar um novo projeto, selecione File > New > New Project. Selecione No Activity em vez de Empty Activity, porque os pacotes RRO contêm apenas recursos.
Suas configurações vão aparecer de forma semelhante às ilustradas abaixo. O local em que eles são salvos pode ser diferente:
Depois de criar o novo projeto
CarUiRRO
, declare-o como um RRO modificandoAndroidManifest.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="CarUiCodelab" android:isStatic="false" android:resourcesMap="@xml/sample_overlay" /> </manifest>
Isso cria um erro com
@xml/sample_overlay
. O arquivoresourcesMap
mapeia os nomes de recursos do pacote de destino para o pacote RRO. Definir a flaghasCode
comofalse
é obrigatório para pacotes RRO. Além disso, os pacotes RRO não podem conter arquivos DEX.Copie o seguinte bloco de código para
…/res/xml/sample_overlay.xml
:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> </overlay>
Adicione
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 criar o destino RRO, pressione o botão verde Play para criar um build do Gradle do RRO no emulador ou dispositivo Android.
Para verificar se o RRO está instalado corretamente, execute:
shell:~$ adb shell cmd overlay list --user current | grep -i com.example com.example.caruicodelab [ ] com.example.caruirro
Esse comando mostra informações úteis sobre o estado dos pacotes RRO no sistema.
[ ]
indica que o RRO está instalado e pronto para ser ativado.---
indica que o RRO está instalado, mas contém erros.[X]
significa que o RRO está instalado e ativado.
Se a RRO tiver erros, consulte Resolver problemas de sobreposições de recursos de execução antes de continuar.
Para ativar o RRO e verificar se ele está ativado:
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
O app mostra a string "Hello World RRO".

Parabéns! Você criou sua primeira RRO.
Ao usar RROs, use as flags --no-resource-deduping
e --no-resource-removal
da
Android Asset Packaging Tool (AAPT2) descritas em
Opções de link.
Não é necessário adicionar as flags neste codelab, mas sugerimos que você as use
nos RROs para evitar a remoção de recursos (e dores de cabeça de depuração). Você
pode adicioná-los ao arquivo build.gradle
do RRO desta forma:
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
Para saber mais sobre essas flags, consulte Criar o pacote e AAPT2.
Modificar componentes car-ui-lib
usando RROs no app Android
Esta página descreve como usar uma sobreposição de recursos de execução (RRO, na sigla em inglês) para
modificar componentes da biblioteca car-ui-lib
no seu app Android.
Definir a cor do plano de fundo da barra de ferramentas
Duração:15 minutos
Para mudar a cor de fundo da barra de ferramentas:
Adicione o valor abaixo ao app RRO e defina o recurso como verde claro (
#0F0
):<?xml version="1.0" encoding="utf-8"?> <resources> <drawable name="car_ui_toolbar_background">#0F0</drawable> </resources>
A biblioteca
car-ui-lib
contém um recurso chamadocar_ui_toolbar_background
. Quando esse recurso está contido na configuração de um RRO, a barra de ferramentas não muda porque o valor errado é direcionado.No
AndroidManifest.xml
do RRO, atualizetargetName
para apontar paracar-ui-lib
:… android:targetName="car-ui-lib" …
É PRECISO criar um novo pacote de RRO para cada pacote de destino que você quer RRO. Por exemplo, ao criar sobreposições para dois destinos diferentes, é necessário criar dois APKs de sobreposição.
Crie, verifique, instale e ative o RRO da mesma forma.
O app vai aparecer assim:

Layouts e estilos de RRO
Duração:15 minutos
Neste exercício, você vai criar um novo app semelhante ao que criou anteriormente. Esse app permite que o layout seja sobreposto. Siga as mesmas etapas anteriores ou modifique o app atual.
Adicione as seguintes linhas 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>
Verifique se
activity_main.xml
aparece da seguinte maneira:<?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>
No app RRO, crie um
res/layout/activity_main.xml
e adicione o seguinte:<?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>
Atualize
res/values/styles.xml
para adicionar nosso estilo ao 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>
Mude a
targetName
emAndroidManifest.xml
para apontar para o nome do seu novo app:… android:targetName="CarUiCodelab" …
Adicione os recursos ao arquivo
sample_overlay.xml
no 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>
Crie e instale o app e o RRO da mesma forma que antes (botão verde Play). Ative o RRO.
O app e a RRO são renderizados da seguinte maneira. O texto Hello World RRO é verde e está centralizado, conforme especificado no layout RRO.

Adicionar a CarUiRecyclerView ao app
Duração:15 minutos
A interface CarUiRecyclerView
fornece APIs para acessar um RecyclerView
personalizado por recursos car-ui-lib
. Por exemplo, CarUiRecyclerView
verifica uma flag no momento da execução para determinar se a barra de rolagem precisa ser ativada ou não
e seleciona o layout correspondente.

Para adicionar um
CarUiRecyclerView
, adicione-o aos arquivosactivity_main.xml
eMainActivity.java
. Você pode criar um novo app do zero ou modificar o app atual. Se você modificar o app atual, remova os recursos não declarados deoverlayable.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"/>
O seguinte erro pode aparecer, mas pode ser ignorado:
Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerView
Desde que a classe esteja escrita corretamente e que você tenha adicionado
car-ui-lib
como uma dependência, é possível criar e compilar o APK. Para remover o erro, selecione File > Invalidate Caches e clique em Invalidate and Restart.Adicione o seguinte 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; }
Crie e instale o app como antes.
Agora você vai ver um CarUiRecyclerView
:

Usar um RRO para remover a barra de rolagem
Duração:10 minutos
Este exercício mostra como usar um RRO para remover a barra de rolagem de
CarUiRecyclerView
.
No RRO, adicione e modifique os seguintes arquivos:
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>
O recurso
car_ui_scrollbar_enable
é um recurso booleanocar-ui-lib
, que controla se a barra de rolagem otimizada para carros com botões para cima e para baixo emCarUiRecyclerView
está presente ou não. Quando definido comofalse
,CarUiRecyclerView
funciona como umRecyclerView
do 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>
Crie e instale o app como antes. A barra de rolagem foi removida de
CarUiRecyclerView
:

Usar um layout para sobrepor a barra de rolagem da CarUiRecyclerView
Duração:15 minutos
Neste exercício, você vai modificar o layout da barra de rolagem CarUiRecyclerView
.
Adicione e modifique os seguintes arquivos no app 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 sobrepor um arquivo de layout, é necessário adicionar todos os IDs e atributos de namespace ao
overlay.xml
do RRO. Confira os arquivos abaixo.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>
É recomendável examinar como esses arquivos interagem.
Para simplificar, as dimensões e cores são fixadas no código. No entanto, uma prática recomendada é declarar esses valores em
dimens.xml
ecolors.xml
ou até mesmo designados como arquivos de cores na pastares/color/
. Para saber mais, consulte Estilo de código Java do AOSP para colaboradores.Crie e instale o app como antes. Você criou
CarUiRecyclerView
com uma barra de rolagem azul e trilhos cinza.
Parabéns! As duas setas aparecem na parte de baixo da barra de rolagem. Você aplicou
com sucesso um RRO a um arquivo de recurso de layout car-ui-lib
usando o sistema de build do Gradle
no Android Studio.

Itens da lista de RRO
Duração:15 minutos
Até agora, você aplicou um RRO a componentes car-ui-lib
usando componentes
de framework (não o AndroidX). Para usar componentes do AndroidX em uma RRO, é necessário adicionar
as dependências do componente ao app e à build.gradle.
da RRO. Também
é necessário adicionar o attrs
do componente à overlayable.xml
no app, bem como
o sample_overlay.xml
na RRO.
Nossa biblioteca (car-ui-lib
) usa ConstraintLayout
, bem como outros componentes do
AndroidX. Portanto, o overlayable.xml
dela pode ser parecido com este:
<?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>
Mude o layout dos itens da lista no
CarUiRecyclerView
usandoConstraintLayout
. Adicione ou modifique os seguintes arquivos no 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
faz referência a vários componentes/ recursos que não estão incluídos como dependências do app. Esses são recursoscar-ui-lib
. Para corrigir isso, adicionecar-ui-lib
como uma dependência ao app RRO emapp/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' }
O título e o corpo agora estão alinhados à direita em vez de à esquerda.

Só aplicamos uma RRO a car-ui-lib
usando componentes do AndroidX
(ConstraintLayout
) quando os atributos estavam presentes no arquivo car-ui-lib
chamado overlayable.xml
, bem como a RRO sample_overlay.xml
. É
possível fazer algo semelhante no seu app. Basta adicionar todos os
attrs
correspondentes ao overlayable.xml
do app, semelhante ao car-ui-lib
.
No entanto, não é possível usar a RRO em um app que usa componentes do AndroidX quando
o app tem car-ui-lib
como dependência no build.gradle
(quando o app usa
componentes car-ui-lib
). Como os mapeamentos de atributos já foram definidos no
overlayable.xml
da biblioteca car-ui-lib
, adicioná-los ao
overlayable.xml
do app com car-ui-lib
como uma dependência causaria um
erro mergeDebugResources
como o abaixo. Isso ocorre porque esses atributos
estão presentes em vários arquivos overlayable.xml
:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'