Atelier de programmation : Créer des RRO avec des composants car-ui-lib à l'aide du système de build Gradle

Utilisez la bibliothèque car-ui-lib pour lancer des systèmes d'infodivertissement (IVI) auto-cohérents embarqués dans le véhicule. Cet atelier de programmation vous présente car-ui-lib et vous explique comment utiliser les superpositions de ressources d'exécution (RRO) pour personnaliser les composants de la bibliothèque.

Ce que vous apprendrez

Comment:

  • Incluez les composants car-ui-lib dans votre application Android.
  • Utilisez Gradle pour créer des applications Android et des RRO.
  • Utilisez les RRO avec car-ui-lib .

Cet atelier de programmation ne détaille pas le fonctionnement des RRO. Consultez Modifier la valeur des ressources d’une application au moment de l’exécution et Dépanner les superpositions de ressources d’exécution pour en savoir plus.

Avant de commencer

Conditions préalables

Avant de commencer, assurez-vous d'avoir :

Créer une nouvelle application Android

Durée : 15 minutes

Dans cette section, vous créez un nouveau projet Android Studio.

  1. Dans Android Studio, créez une application avec un EmptyActivity .

    Créer une activité vide
    Figure 1. Créer une activité vide
  2. Nommez l'application CarUiCodelab puis sélectionnez le langage Java. Vous pouvez également sélectionner un emplacement de fichier si vous le souhaitez. Acceptez les valeurs par défaut pour les paramètres restants.

    Nommez votre application
    Figure 2. Nommez votre application
  3. Remplacez activity_main.xml par le bloc de code suivant :

    <?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>
    

    Ce bloc de code affiche la chaîne sample_text , qui n'est pas définie.

  4. Ajoutez la chaîne de ressource sample_text et définissez-la sur "Hello World!" dans votre fichier strings.xml . Pour ouvrir ce fichier, sélectionnez 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>
    
  5. Pour créer votre application, cliquez sur le bouton vert Play en haut à droite. Cela installe automatiquement l'apk sur votre émulateur ou votre appareil Android via Gradle.

    Bouton jouer

La nouvelle application devrait s'ouvrir automatiquement sur votre émulateur ou votre appareil Android. Sinon, ouvrez l'application CarUiCodelab à partir du lanceur d'applications, qui est maintenant installé. Cela ressemble à ceci :

Ouvrez la nouvelle application CarUiCodelab
Figure 3. Ouvrez la nouvelle application CarUiCodelab

Ajoutez car-ui-lib à votre application Android

Durée : 15 minutes

Ajoutez car-ui-lib à votre application :

  1. Pour ajouter la dépendance car-ui-lib au fichier build.gradle de votre projet, sélectionnez app > build.gradle . Vos dépendances devraient apparaître comme ceci :

    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'
    }
    

Utilisez les composants car-ui-lib dans votre application Android

Maintenant que vous disposez car-ui-lib , ajoutez une barre d'outils à votre application.

  1. Dans votre fichier MainActivity.java , remplacez la méthode onCreate :

    @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);
    }
    
  2. Assurez-vous d'importer ToolbarController :

    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.toolbar.ToolbarController;
    
  3. Pour utiliser le thème Theme.CarUi.WithToolbar , sélectionnez app > src > main > AndroidManifest.xml , puis mettez à jour AndroidManifest.xml pour qu'il apparaisse comme suit :

    <?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>
    
  4. Pour créer l'application, appuyez sur le bouton vert Play comme avant.

    Créer l'application

Ajoutez des RRO à votre application

Durée : 30 minutes

Si vous êtes familier avec les RRO, passez à la section suivante, Ajouter un contrôleur d'autorisation à votre application . Sinon, pour découvrir les bases des RRO, consultez Modifier la valeur des ressources d'une application au moment de l'exécution .

Ajoutez un contrôleur d'autorisation à votre application

Pour contrôler les ressources qu'un package RRO superpose, ajoutez un fichier nommé overlayable.xml au dossier /res de votre application. Ce fichier sert de contrôleur d'autorisation entre votre application (la cible ) et votre package RRO (la superposition ).

  1. Ajoutez res/values/overlayable.xml à votre application et copiez le contenu suivant dans votre fichier :

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <overlayable name="CarUiCodelab">
            <policy type="public">
                <item type="string" name="sample_text"/>
            </policy>
        </overlayable>
    </resources>
    

    Étant donné que la chaîne sample_text doit pouvoir être superposée par un RRO, incluez le nom de la ressource dans le fichier overlayable.xml de l'application.

    Votre fichier overlayable.xml DOIT résider dans res/values/ . Sinon, OverlayManagerService ne peut pas le localiser.

    Pour en savoir plus sur les ressources superposables et sur la façon dont elles peuvent être configurées, consultez Restreindre les ressources superposables .

Créer un package RRO

Dans cette section, vous créez un package RRO pour modifier la chaîne affichée ci-dessus de « Hello World ! » à "Bonjour le monde RRO".

  1. Pour créer un nouveau projet, sélectionnez Fichier > Nouveau > Nouveau projet . Assurez-vous de sélectionner Aucune activité au lieu d'Activité vide, car les packages RRO ne contiennent que des ressources.

    Vos configurations apparaissent de manière similaire à celles illustrées ci-dessous. L'emplacement où ils sont enregistrés peut différer :

  2. Après avoir créé le nouveau projet CarUiRRO , déclarez le projet comme RRO en modifiant 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="CarUiCodelab"
            android:isStatic="false"
            android:resourcesMap="@xml/sample_overlay"
            />
    </manifest>
    

    Cela crée une erreur avec @xml/sample_overlay . Le fichier resourcesMap mappe les noms de ressources du package cible au package RRO.

  3. Copiez le bloc de code suivant dans …/res/xml/sample_overlay.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="string/sample_text" value="@string/sample_text"/>
    </overlay>
    
  4. Ajoutez sample_text à …/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>
    
    Création de la version Gradle de RRO
  5. Pour créer votre cible RRO, appuyez sur le bouton vert Lecture pour créer une version Gradle de votre RRO sur votre émulateur ou votre appareil Android.

  6. Pour vérifier que votre RRO est correctement installé, exécutez :

    shell:~$ adb shell cmd overlay list --user current | grep -i com.example
    com.example.caruicodelab
    [ ] com.example.caruirro
    

    Cette commande affiche des informations utiles sur l'état des packages RRO sur le système.

    • [ ] indique que le RRO est installé et prêt à être activé.
    • --- indique que le RRO est installé mais contient des erreurs.
    • [X] signifie que le RRO est installé et activé.

    Si votre RRO contient des erreurs, consultez Résoudre les superpositions de ressources d’exécution avant de continuer.

  7. Pour activer le RRO et vérifier qu'il est activé :

    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
    

Votre application affiche la chaîne « Hello World RRO ».

Bonjour tout le monde RRO !
Figure 4 : Bonjour tout le monde RRO !

Toutes nos félicitations! Vous avez créé votre premier RRO.

Lorsque vous utilisez des RRO, vous souhaiterez peut-être utiliser les indicateurs --no-resource-deduping et --no-resource-removal d'Android Asset Packaging Tool (AAPT2) décrits dans Options de lien . Il n'est pas nécessaire d'ajouter les indicateurs dans cet atelier de programmation, mais nous vous suggérons de les utiliser dans vos RRO pour éviter la suppression de ressources (et les problèmes de débogage). Vous pouvez les ajouter au fichier build.gradle de votre RRO comme ceci :

android {
    …
    aaptOptions {
        additionalParameters "--no-resource-deduping", "--no-resource-removal"
    }
}

Pour en savoir plus sur ces indicateurs, consultez Créer le package et AAPT2 .

Modifier les composants car-ui-lib à l'aide des RRO dans votre application Android

Cette page décrit comment utiliser une superposition de ressources d'exécution (RRO) pour modifier les composants de la bibliothèque car-ui-lib dans votre application Android.

Définir la couleur d'arrière-plan de la barre d'outils

Durée : 15 minutes

Pour changer la couleur d'arrière-plan de la barre d'outils :

  1. Ajoutez la valeur suivante à votre application RRO et définissez la ressource sur vert vif ( #0F0 ) :

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <drawable name="car_ui_toolbar_background">#0F0</drawable>
    </resources>
    

    La bibliothèque car-ui-lib contient une ressource nommée car_ui_toolbar_background . Lorsque cette ressource est contenue dans la configuration d'un RRO, la barre d'outils ne change pas car la mauvaise valeur est ciblée.

  2. Dans le AndroidManifest.xml de votre RRO, mettez à jour targetName pour qu'il pointe vers car-ui-lib :

    …
    android:targetName="car-ui-lib"
    …
    

    Vous DEVEZ créer un nouveau package RRO pour chaque package cible que vous souhaitez RRO. Par exemple, lors de la création de superpositions pour deux cibles différentes, vous devez créer deux apks de superposition.

  3. Créez, vérifiez, installez et activez le RRO de la même manière qu'auparavant.

Votre application apparaît comme ceci :

Nouvelle couleur d’arrière-plan de la barre d’outils
Figure 5 : Nouvelle couleur d'arrière-plan de la barre d'outils

Dispositions et styles RRO

Durée : 15 minutes

Dans cet exercice, vous allez créer une nouvelle application similaire à celle que vous avez créée précédemment. Cette application permet de superposer la mise en page. Suivez les mêmes étapes que précédemment ou modifiez votre application existante.

  1. Assurez-vous d'ajouter les lignes suivantes à 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>
    
  2. Assurez-vous que activity_main.xml apparaît comme suit :

    <?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>
    
  3. Dans votre application RRO, créez un res/layout/activity_main.xml et ajoutez ce qui suit :

    <?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>
    
  4. Mettez à jour res/values/styles.xml pour ajouter notre style au 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>
    
  5. Modifiez le targetName dans AndroidManifest.xml pour qu'il pointe vers le nom de votre nouvelle application :

    …
    android:targetName="CarUiCodelab"
    …
    
  6. Ajoutez les ressources au fichier sample_overlay.xml dans votre 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>
    
  7. Créez et installez l'application et le RRO de la même manière qu'avant (bouton vert Play ). Assurez-vous d'activer votre RRO.

L'application et le RRO s'affichent comme suit. Le texte Hello World RRO est vert et centré comme spécifié dans la mise en page RRO.

Bonjour tout le monde RRO
Figure 6 : Bonjour tout le monde RRO

Ajoutez CarUiRecyclerView à votre application

Durée : 15 minutes

L'interface CarUiRecyclerView fournit des API pour accéder à un RecyclerView personnalisé via les ressources car-ui-lib . Par exemple, CarUiRecyclerView vérifie un indicateur au moment de l'exécution pour déterminer si la barre de défilement doit être activée ou non et sélectionne la disposition correspondante.

CarUiRecyclerViewContainer
Figure 7. CarUiRecyclerViewContainer
  1. Pour ajouter un CarUiRecyclerView , ajoutez-le à vos fichiers activity_main.xml et MainActivity.java . Vous pouvez soit créer une nouvelle application à partir de zéro, soit modifier l'application existante. Si vous modifiez l'application existante, veillez à supprimer les ressources non déclarées de overlayable.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"/>
    

    L'erreur suivante peut apparaître, que vous pouvez ignorer :

    Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerView

    Tant que votre classe est correctement orthographiée et que vous avez ajouté car-ui-lib en tant que dépendance, vous pouvez créer et compiler votre apk. Pour supprimer l'erreur, sélectionnez Fichier > Invalider les caches, puis cliquez sur Invalider et redémarrer.

    Ajoutez ce qui suit à 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;
    }
    
  2. Créez et installez votre application comme avant.

Vous voyez maintenant un CarUiRecyclerView :

CarUiRecyclerView
Figure 7 : CarUiRecyclerView

Utilisez un RRO pour supprimer la barre de défilement

Durée : 10 minutes

Cet exercice vous montre comment utiliser un RRO pour supprimer la barre de défilement de CarUiRecyclerView .

  1. Dans votre RRO, ajoutez et modifiez les fichiers suivants :

    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>
    

    La ressource car_ui_scrollbar_enable est une ressource booléenne car-ui-lib , qui contrôle si la barre de défilement optimisée pour la voiture avec les boutons Haut et Bas dans CarUiRecyclerView est présente ou non. Lorsqu'il est défini sur false , CarUiRecyclerView agit comme un AndroidX RecyclerView .

    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>
    

Créez et installez votre application comme avant. La barre de défilement est désormais supprimée de CarUiRecyclerView :

CarUiRecyclerView sans barre de défilement
Figure 8. CarUiRecyclerView sans barre de défilement

Utiliser une mise en page pour superposer la barre de défilement CarUiRecyclerView

Durée : 15 minutes

Dans cet exercice, vous allez modifier la disposition de la barre de défilement CarUiRecyclerView .

  1. Ajoutez et modifiez les fichiers suivants dans votre application 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>
    

    Pour superposer un fichier de mise en page, vous devez ajouter tous les ID et attributs d'espace de noms au overlay.xml de votre RRO. Voir les fichiers ci-dessous.

    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>
    

    Il est suggéré d'examiner comment ces fichiers interagissent.

    Pour plus de simplicité, les dimensions et les couleurs sont codées en dur. Cependant, une bonne pratique consiste à déclarer ces valeurs dans dimens.xml et colors.xml ou même à les désigner comme fichiers de couleur dans le dossier res/color/ . Pour en savoir plus, consultez Style de code Java AOSP pour les contributeurs .

  2. Créez et installez votre application comme avant. Vous avez construit CarUiRecyclerView avec une barre de défilement bleue et des rails gris.

Toutes nos félicitations! Les deux flèches apparaissent en bas de la barre de défilement. Vous avez appliqué avec succès un RRO à un fichier de ressources de mise en page car-ui-lib à l'aide du système de construction Gradle via Android Studio.

CarUiRecyclerView avec une barre de défilement bleue avec des rails gris
Figure 9. CarUiRecyclerView avec une barre de défilement bleue avec des rails gris

Éléments de la liste RRO

Durée : 15 minutes

Jusqu'à présent, vous avez appliqué un RRO aux composants car-ui-lib à l'aide de composants de framework (et non d'AndroidX). Pour utiliser des composants AndroidX dans un RRO, vous devez ajouter les dépendances de ce composant à la fois à l'application et au build.gradle. Vous devez également ajouter attrs de ce composant à overlayable.xml dans votre application, ainsi qu'à sample_overlay.xml dans votre RRO.

Notre bibliothèque ( car-ui-lib ) utilise ConstraintLayout ainsi que d'autres composants AndroidX, donc son overlayable.xml pourrait ressembler à ceci :

<?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>
  1. Modifiez la disposition des éléments de liste dans CarUiRecyclerView à l’aide ConstraintLayout . Ajoutez ou modifiez les fichiers suivants dans votre 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>
    
  2. car_ui_list_item.xml fait référence à plusieurs références à plusieurs composants/ressources qui ne sont pas inclus en tant que dépendances de l'application. Ce sont des ressources car-ui-lib . Vous pouvez résoudre ce problème en ajoutant car-ui-lib en tant que dépendance à votre application RRO dans app/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'
    }
    

Le titre et le corps sont désormais alignés à droite au lieu d'être alignés à gauche.

Titre et corps alignés à droite
Figure 10. Titre et corps alignés à droite

Nous n'avons appliqué un RRO à car-ui-lib à l'aide de composants AndroidX ( ConstraintLayout ) que lorsque ses attributs étaient présents dans le fichier car-ui-lib nommé overlayable.xml ainsi que dans le RRO sample_overlay.xml . Il est possible de faire quelque chose de similaire dans votre propre application. Ajoutez simplement toutes les attrs correspondantes au overlayable.xml de votre application, similaire à car-ui-lib .

Cependant, il n'est pas possible de RRO une application utilisant des composants AndroidX lorsque l'application a car-ui-lib comme dépendance dans son build.gradle (lorsque l'application utilise des composants car-ui-lib ). Étant donné que les mappages d'attributs étaient déjà définis dans le overlayable.xml de la bibliothèque car-ui-lib , les ajouter au overlayable.xml de votre application avec car-ui-lib comme dépendance provoquerait une erreur mergeDebugResources comme celle ci-dessous. En effet, ces attributs sont présents dans plusieurs fichiers overlayable.xml :

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'