Codelab: Membuat RRO dengan komponen car-ui-lib menggunakan sistem build Gradle

Gunakan library car-ui-lib untuk meluncurkan infotainmen yang konsisten mandiri di dalam kendaraan (IVI). Codelab ini memperkenalkan car-ui-lib dan cara Anda dapat menggunakannya menggunakan overlay resource runtime (RRO) untuk menyesuaikan komponen dalam library.

Yang akan Anda pelajari

Caranya:

  • Sertakan komponen car-ui-lib di aplikasi Android Anda.
  • Menggunakan Gradle untuk membangun aplikasi Android dan RRO.
  • Menggunakan RRO dengan car-ui-lib.

Codelab ini tidak menjelaskan cara kerja RRO. Lihat Mengubah nilai resource aplikasi saat runtime dan Memecahkan masalah overlay resource runtime untuk mempelajari lebih lanjut.

Sebelum memulai

Prasyarat

Sebelum memulai, pastikan Anda memiliki:

  • Komputer dengan baris perintah (mesin Linux, Mac, atau Windows dengan Subsistem Windows untuk Linux).

  • Android Studio.

  • Perangkat Android atau emulator yang terhubung ke komputer Anda. Lihat Download sumber Android dan Membuat Android.

  • Pengetahuan dasar tentang RRO.

Membuat aplikasi Android baru

Durasi: 15 menit

Di bagian ini, Anda akan membuat project Android Studio baru.

  1. Di Android Studio, buat aplikasi dengan EmptyActivity.

    Membuat Aktivitas Kosong
    Gambar 1.Membuat Aktivitas Kosong
  2. Beri nama aplikasi CarUiCodelab, lalu pilih bahasa Java. Anda dapat pilih juga lokasi {i>file<i} jika diinginkan. Setujui nilai default untuk setelan lainnya.

     Beri nama aplikasi Anda
    Gambar 2. Beri nama aplikasi Anda
  3. Ganti activity_main.xml dengan blok kode berikut:

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

    Blok kode ini menampilkan string sample_text, yang tidak ditentukan.

  4. Tambahkan string resource sample_text dan setel ke "Hello World!" di File strings.xml. Untuk membuka file ini, pilih app > src > utama > res > nilai > 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. Untuk membuat aplikasi, klik tombol Play berwarna hijau di kanan atas. Tindakan ini secara otomatis menginstal apk ke emulator atau perangkat Android Anda melalui Gradle.

    Tombol putar

Aplikasi baru akan terbuka secara otomatis di emulator atau perangkat Android Anda. Jika tidak, buka aplikasi CarUiCodelab dari peluncur aplikasi yang kini telah terinstal. Tampilannya akan terlihat seperti ini:

Membuka aplikasi CarUiCodelab baru
Gambar 3. Membuka aplikasi CarUiCodelab baru

Menambahkan car-ui-lib ke aplikasi Android Anda

Durasi: 15 menit

Tambahkan car-ui-lib ke aplikasi Anda:

  1. Untuk menambahkan dependensi car-ui-lib ke file build.gradle project Anda, pilih aplikasi > build.gradle. Dependensi Anda akan terlihat seperti ini:

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

Menggunakan komponen car-ui-lib di aplikasi Android

Setelah memiliki car-ui-lib, tambahkan toolbar ke aplikasi Anda.

  1. Dalam file MainActivity.java Anda, timpa metode 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. Pastikan untuk mengimpor ToolbarController:

    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.toolbar.ToolbarController;
    
  3. Untuk menggunakan tema Theme.CarUi.WithToolbar, pilih aplikasi > src > utama > AndroidManifest.xml, lalu update AndroidManifest.xml agar muncul sebagai berikut:

    <?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. Untuk membuat aplikasi, tekan tombol Play berwarna hijau seperti sebelumnya.

    Membangun aplikasi

Menambahkan RRO ke aplikasi

Durasi: 30 menit

Jika Anda sudah terbiasa dengan RRO, buka bagian ini, Tambahkan pengontrol izin ke aplikasi Anda. Jika tidak, untuk mempelajari dasar-dasar RRO, lihat Mengubah nilai resource aplikasi saat runtime.

Menambahkan pengontrol izin ke aplikasi

Untuk mengontrol sumber daya mana yang dihamparkan paket RRO, tambahkan file bernama overlayable.xml ke folder /res aplikasi Anda. File ini berfungsi sebagai izin pengontrol antara aplikasi Anda (target) dan paket RRO (overlay).

  1. Tambahkan res/values/overlayable.xml ke aplikasi Anda dan salin konten berikut ke dalam file Anda:

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

    Karena string sample_text harus dapat ditempatkan oleh RRO, sertakan atribut dalam overlayable.xml aplikasi.

    File overlayable.xml Anda HARUS berada di res/values/. Jika tidak, OverlayManagerService tidak dapat menemukannya.

    Untuk mempelajari lebih lanjut resource yang dapat di-overlay dan bagaimana resource tersebut dapat dikonfigurasi, lihat Membatasi iklan overlay resource.

Membuat paket RRO

Di bagian ini, Anda akan membuat paket RRO untuk mengubah {i>string<i} yang ditampilkan di atas dari "Hello World!" menjadi "Hello World RRO".

  1. Untuk membuat proyek baru, pilih File > Baru > Project Baru. Pastikan untuk pilih No Activity, bukan Empty Activity karena paket RRO berisi hanya sumber daya.

    Konfigurasi Anda terlihat serupa dengan yang diilustrasikan di bawah ini. Tujuan lokasi penyimpanannya mungkin berbeda:

  2. Setelah Anda membuat project CarUiRRO baru, deklarasikan project sebagai RRO dengan mengubah 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>
    

    Tindakan ini akan membuat error dengan @xml/sample_overlay. resourcesMap file memetakan nama sumber daya dari paket target ke paket RRO.

  3. Salin blok kode berikut ke …/res/xml/sample_overlay.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="string/sample_text" value="@string/sample_text"/>
    </overlay>
    
  4. Tambahkan sample_text ke …/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>
    
    Membuat build Gradle RRO
  5. Untuk membangun target RRO, tekan tombol Play berwarna hijau untuk membuat Gradle build RRO di emulator atau perangkat Android.

  6. Untuk memverifikasi bahwa RRO Anda sudah diinstal dengan benar, jalankan:

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

    Perintah ini menampilkan informasi yang berguna tentang status paket RRO pada sistem.

    • [ ] menunjukkan bahwa RRO telah diinstal dan siap diaktifkan.
    • --- menunjukkan bahwa RRO telah diinstal, tetapi berisi error.
    • [X] berarti RRO diinstal dan diaktifkan.

    Jika RRO Anda berisi {i>error<i}, lihat Memecahkan masalah overlay resource runtime sebelum melanjutkan.

  7. Untuk mengaktifkan RRO dan memastikannya telah diaktifkan:

    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
    

Aplikasi Anda menampilkan string "Hello World RRO".

Halo Dunia RRO!
Gambar 4: Halo Dunia RRO!

Selamat! Anda telah membuat RRO pertama.

Saat menggunakan RRO, Anda mungkin ingin menggunakan Android Asset Packaging Tool (AAPT2) tanda --no-resource-deduping dan --no-resource-removal dijelaskan dalam Opsi penautan. Flag tidak perlu ditambahkan dalam codelab ini, tetapi sebaiknya Anda menggunakannya dalam RRO Anda untuk menghindari penghapusan sumber daya (dan {i>debugging<i} masalah kepala). Anda dapat menambahkannya ke file build.gradle RRO Anda seperti ini:

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

Untuk mempelajari tanda ini lebih lanjut, lihat Membangun paket dan AAPT2.

Mengubah komponen car-ui-lib menggunakan RRO di aplikasi Android

Halaman ini menjelaskan cara menggunakan runtime resource overlay (RRO) untuk memodifikasi komponen dari library car-ui-lib di aplikasi Android Anda.

Menyetel warna latar belakang toolbar

Durasi: 15 menit

Untuk mengubah warna latar belakang toolbar:

  1. Tambahkan nilai berikut ke aplikasi RRO, dan setel resource ke kecerahan hijau (#0F0):

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

    Library car-ui-lib berisi resource yang bernama car_ui_toolbar_background. Ketika resource ini terdapat dalam konfigurasi RRO, {i>toolbar<i} tidak berubah karena nilai yang salah yang ditargetkan.

  2. Di AndroidManifest.xml untuk RRO, perbarui targetName agar mengarah ke car-ui-lib:

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

    Anda HARUS membuat paket RRO baru untuk setiap paket target yang ingin Anda RRO. Misalnya, saat membuat overlay untuk dua target yang berbeda, Anda harus membuat dua apk overlay.

  3. Bangun, verifikasi, instal, dan aktifkan RRO dengan cara yang sama seperti sebelumnya.

Aplikasi Anda akan tampak seperti ini:

Warna latar belakang Toolbar baru
Gambar 5: Warna latar belakang toolbar baru

Tata letak dan gaya RRO

Durasi: 15 menit

Dalam latihan ini, Anda akan membangun aplikasi baru yang mirip dengan aplikasi yang telah Anda bangun sebelumnya. Ini memungkinkan tata letak untuk di-overlay. Ikuti langkah yang sama seperti sebelumnya, atau ubah aplikasi yang sudah ada.

  1. Pastikan Anda menambahkan baris berikut ke 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. Pastikan activity_main.xml muncul seperti berikut:

    <?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. Di aplikasi RRO, buat res/layout/activity_main.xml dan tambahkan berikut ini:

    <?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. Perbarui res/values/styles.xml untuk menambahkan gaya ke 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. Ubah targetName di AndroidManifest.xml agar mengarah ke nama aplikasi baru Anda:

    …
    android:targetName="CarUiCodelab"
    …
    
  6. Tambahkan resource ke file sample_overlay.xml di RRO Anda:

    <?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. Bangun dan instal aplikasi dan RRO dengan cara yang sama seperti sebelumnya (Play berwarna hijau tombol). Pastikan untuk mengaktifkan RRO.

Aplikasi dan RRO merender sebagai berikut. Teks RRO Hello World berwarna hijau dan di tengah seperti yang ditentukan dalam tata letak RRO.

Halo Dunia RRO
Gambar 6: Hello World RRO

Menambahkan CarUiRecyclerView ke aplikasi

Durasi: 15 menit

Antarmuka CarUiRecyclerView menyediakan API untuk mengakses RecyclerView yang disesuaikan melalui resource car-ui-lib. Misalnya, CarUiRecyclerView memeriksa flag saat runtime untuk menentukan apakah scrollbar harus diaktifkan atau tidak dan memilih tata letak yang sesuai.

CarUiRecyclerViewContainer
Gambar 7. CarUiRecyclerViewContainer
  1. Untuk menambahkan CarUiRecyclerView, tambahkan ke activity_main.xml dan MainActivity.java file. Anda dapat membuat aplikasi baru dari awal atau memodifikasi aplikasi yang ada. Jika Anda mengubah aplikasi yang ada, pastikan untuk menghapus resource yang tidak dideklarasikan dari 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"/>
    

    Error berikut mungkin muncul, yang dapat Anda abaikan:

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

    Selama kelas Anda dieja dengan benar dan Anda telah menambahkan car-ui-lib sebagai dependensi, Anda bisa membangun dan mengompilasi apk. Untuk menghilangkan {i>error<i}, pilih File > Invalidate Caches lalu klik Invalidate and Restart.

    Tambahkan kode berikut ke 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. Bangun dan instal aplikasi Anda seperti sebelumnya.

Anda sekarang melihat CarUiRecyclerView:

MobilUiRecyclerView
Gambar 7 : CarUiRecyclerView

Menggunakan RRO untuk menghapus scrollbar

Durasi: 10 menit

Latihan ini menunjukkan cara menggunakan RRO untuk menghapus {i>scrollbar<i} dari CarUiRecyclerView.

  1. Dalam RRO Anda, tambahkan dan ubah file berikut:

    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>
    

    Resource car_ui_scrollbar_enable adalah resource boolean car-ui-lib, yang mengontrol apakah scrollbar dioptimalkan mobil dengan tombol Atas dan Bawah di CarUiRecyclerView ada atau tidak. Jika ditetapkan ke false, CarUiRecyclerView bertindak seperti RecyclerView 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>
    

Bangun dan instal aplikasi Anda seperti sebelumnya. Scrollbar kini telah dihapus dari CarUiRecyclerView:

CarUiRecyclerView tanpa scrollbar
Gambar 8. CarUiRecyclerView tanpa scrollbar

Menggunakan tata letak untuk menempatkan scrollbar CarUiRecyclerView

Durasi: 15 menit

Dalam latihan ini, Anda akan mengubah tata letak scrollbar CarUiRecyclerView.

  1. Tambahkan dan ubah file berikut di aplikasi 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>
    

    Untuk menempatkan file tata letak, Anda harus menambahkan semua ID dan namespace atribut ke overlay.xml dari RRO Anda. Lihat file di bawah.

    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>
    

    Sebaiknya periksa cara file ini berinteraksi.

    Untuk mempermudah, dimensi dan warna di-hardcode. Namun, praktiknya adalah mendeklarasikan nilai ini dalam dimens.xml dan colors.xml atau bahkan ditetapkan sebagai file warna dalam folder res/color/. Untuk mempelajari lebih lanjut, lihat Gaya kode Java AOSP untuk kontributor.

  2. Bangun dan instal aplikasi Anda seperti sebelumnya. Anda telah membuat CarUiRecyclerView dengan scrollbar biru dan kolom samping abu-abu.

Selamat! Kedua panah muncul di sepanjang bagian bawah scrollbar, Anda telah berhasil menerapkan RRO ke file resource tata letak car-ui-lib menggunakan build Gradle sistem operasi melalui Android Studio.

CarUiRecyclerView dengan scrollbar biru dengan kolom samping abu-abu
Gambar 9. CarUiRecyclerView dengan scrollbar biru dan kolom samping abu-abu

Item daftar RRO

Durasi: 15 menit

Hingga titik ini, Anda telah menerapkan RRO ke komponen car-ui-lib menggunakan framework (bukan AndroidX). Untuk menggunakan komponen AndroidX dalam RRO, Anda harus menambahkan dependensi komponen itu ke aplikasi dan ke RRO build.gradle. Anda juga harus menambahkan attrs komponen tersebut ke overlayable.xml di aplikasi Anda, serta sebagai sample_overlay.xml di RRO Anda.

Library kami (car-ui-lib) menggunakan ConstraintLayout serta AndroidX lainnya sehingga overlayable.xml-nya akan terlihat seperti ini:

<?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. Ubah tata letak item daftar di CarUiRecyclerView menggunakan ConstraintLayout. Tambahkan atau ubah file berikut di RRO Anda:

    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 merujuk beberapa referensi untuk beberapa komponen/ sumber daya yang tidak disertakan sebagai dependensi aplikasi. Berikut adalah car-ui-lib resource. Anda dapat memperbaikinya dengan menambahkan car-ui-lib sebagai dependensi untuk aplikasi RRO di 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'
    }
    

Judul dan Isi kini diratakan kanan, bukan kiri.

Judul dan Isi Rata Kanan
Gambar 10. Judul dan Isi Rata Kanan

Kami hanya menerapkan RRO ke car-ui-lib menggunakan komponen AndroidX (ConstraintLayout) saat atributnya ada di car-ui-lib file bernama overlayable.xml serta RRO sample_overlay.xml. Penting mungkin untuk melakukan hal serupa di aplikasi Anda sendiri. Cukup tambahkan semua attrs ke overlayable.xml aplikasi Anda, mirip dengan car-ui-lib.

Namun, tidak memungkinkan untuk melakukan RRO aplikasi menggunakan komponen AndroidX jika aplikasi memiliki car-ui-lib sebagai dependensi dalam build.gradle (saat aplikasi menggunakan komponen car-ui-lib). Karena pemetaan atribut sudah ditentukan di dalam overlayable.xml library car-ui-lib, yang menambahkannya ke overlayable.xml aplikasi dengan car-ui-lib sebagai dependensi akan menyebabkan mergeDebugResources error seperti di bawah ini. Hal ini karena atribut ini ada di beberapa file overlayable.xml:

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