CODELAB: Gradle Build Sistemini kullanarak CAR-UI-LIB bileşenleri ile RRO'lar oluşturun

Kendi kendine tutarlı, araç içi bilgi-eğlence (IVI) sistemlerini başlatmak için car-ui-lib kitaplığını kullanın. Bu codelab size car-ui-lib ve kitaplıktaki bileşenleri özelleştirmek için çalışma zamanı kaynak katmanlarını (RRO'lar) nasıl kullanabileceğinizi tanıtır.

Ne öğreneceksin

Nasıl:

  • Android uygulamanıza car-ui-lib bileşenlerini ekleyin.
  • Android uygulamaları ve RRO'lar oluşturmak için Gradle'ı kullanın.
  • RRO'ları car-ui-lib ile kullanın.

Bu codelab, RRO'ların nasıl çalıştığını ayrıntılarıyla anlatmıyor. Daha fazla bilgi edinmek için Uygulama kaynaklarının değerini çalışma zamanında değiştirme ve Çalışma zamanı kaynak katmanlarında sorun giderme bölümlerine bakın.

Başlamadan önce

Önkoşullar

Başlamadan önce aşağıdakilere sahip olduğunuzdan emin olun:

Yeni bir Android uygulaması oluşturun

Süre: 15 dakika

Bu bölümde yeni bir Android Studio projesi oluşturacaksınız.

  1. Android Studio'da EmptyActivity içeren bir uygulama oluşturun.

    Boş Bir Etkinlik Oluşturun
    Şekil 1. Boş Bir Etkinlik Oluşturun
  2. Uygulamaya CarUiCodelab adını verin ve ardından Java dilini seçin. İsterseniz bir dosya konumu da seçebilirsiniz. Geri kalan ayarlar için varsayılan değerleri kabul edin.

    Uygulamanıza ad verin
    Şekil 2. Uygulamanıza bir ad verin
  3. activity_main.xml dosyasını aşağıdaki kod bloğuyla değiştirin:

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

    Bu kod bloğu, tanımlanmamış olan sample_text dizesini görüntüler.

  4. sample_text kaynak dizesini ekleyin ve "Merhaba Dünya!" olarak ayarlayın. strings.xml dosyanızda. Bu dosyayı açmak için app > src > main > res > değerler > strings.xml öğesini seçin.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiCodelab</string>
        <string name="sample_text">Hello World!</string>
    </resources>
    
  5. Uygulamanızı oluşturmak için sağ üstteki yeşil Oynat düğmesini tıklayın. Bunu yapmak, apk'yi Gradle aracılığıyla emülatörünüze veya Android cihazınıza otomatik olarak yükler.

    Oynatma düğmesi

Yeni uygulama emülatörünüzde veya Android cihazınızda otomatik olarak açılmalıdır. Değilse, şu anda yüklü olan uygulama başlatıcıdan CarUiCodelab uygulamasını açın. Şunun gibi görünüyor:

Yeni CarUiCodelab uygulamasını açın
Şekil 3. Yeni CarUiCodelab uygulamasını açın

Android uygulamanıza car-ui-lib ekleyin

Süre: 15 dakika

Uygulamanıza car-ui-lib ekleyin:

  1. car-ui-lib bağımlılığını projenizin build.gradle dosyasına eklemek için app > build.gradle öğesini seçin. Bağımlılıklarınız şu şekilde görünmelidir:

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

Android uygulamanızda car-ui-lib bileşenlerini kullanın

Artık car-ui-lib olduğuna göre uygulamanıza bir araç çubuğu ekleyin.

  1. MainActivity.java dosyanızda onCreate yönteminin üzerine yazın:

    @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. ToolbarController içe aktardığınızdan emin olun:

    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.toolbar.ToolbarController;
    
  3. Theme.CarUi.WithToolbar temasını kullanmak için, uygulama > src > ana > AndroidManifest.xml öğesini seçin ve ardından AndroidManifest.xml aşağıdaki gibi görünecek şekilde güncelleyin:

    <?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. Uygulamayı oluşturmak için daha önce olduğu gibi yeşil Oynat düğmesine basın.

    Uygulamayı oluşturun

Uygulamanıza RRO'lar ekleyin

Süre: 30 dakika

RRO'lara aşina iseniz sonraki bölüme gidin: Uygulamanıza izin denetleyicisi ekleyin . Aksi takdirde, RRO'ların temellerini öğrenmek için bkz. Çalışma zamanında bir uygulamanın kaynaklarının değerini değiştirme .

Uygulamanıza bir izin denetleyicisi ekleyin

Bir RRO paketinin hangi kaynakları kapladığını kontrol etmek için uygulamanızın /res klasörüne overlayable.xml adlı bir dosya ekleyin. Bu dosya, uygulamanız ( hedef ) ile RRO paketiniz ( yer paylaşımı ) arasında bir izin denetleyicisi görevi görür.

  1. res/values/overlayable.xml dosyasını uygulamanıza ekleyin ve aşağıdaki içeriği dosyanıza kopyalayın:

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

    sample_text dizesinin bir RRO tarafından kaplanabilir olması gerektiğinden, kaynak adını uygulamanın overlayable.xml dosyasına ekleyin.

    overlayable.xml dosyanız res/values/ konumunda OLMALIDIR . Değilse OverlayManagerService onu bulamaz.

    Yerleştirilebilir kaynaklar ve bunların nasıl yapılandırılabileceği hakkında daha fazla bilgi edinmek için bkz. Yerleştirilebilir kaynakları kısıtlama .

Bir RRO paketi oluşturun

Bu bölümde, yukarıda görüntülenen dizeyi "Merhaba Dünya!" yerine değiştirmek için bir RRO paketi oluşturacaksınız. "Merhaba Dünya RRO"ya.

  1. Yeni bir proje oluşturmak için Dosya > Yeni > Yeni Proje'yi seçin. RRO paketleri yalnızca kaynakları içerdiğinden Boş Etkinlik yerine Etkinlik Yok'u seçtiğinizden emin olun.

    Yapılandırmalarınız aşağıda gösterilenlere benzer şekilde görünür. Kaydedildiği konum farklı olabilir:

  2. Yeni CarUiRRO projesini oluşturduktan sonra AndroidManifest.xml dosyasını değiştirerek projeyi RRO olarak bildirin.

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

    Bunu yapmak @xml/sample_overlay ile ilgili bir hata oluşturur. resourcesMap dosyası, kaynak adlarını hedef paketten RRO paketine eşler.

  3. Aşağıdaki kod bloğunu …/res/xml/sample_overlay.xml kopyalayın:

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="string/sample_text" value="@string/sample_text"/>
    </overlay>
    
  4. sample_text …/res/values/strings.xml dosyasına ekleyin:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiRRO</string>
        <string name="sample_text">Hello World RRO</string>
    </resources>
    
    RRO'nun Gradle yapısı oluşturuldu
  5. RRO hedefinizi oluşturmak için emülatörünüzde veya Android cihazınızda RRO'nuzun Gradle yapısını oluşturmak için yeşil Oynat düğmesine basın.

  6. RRO'nuzun düzgün şekilde kurulduğunu doğrulamak için şunu çalıştırın:

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

    Bu komut, sistemdeki RRO paketlerinin durumu hakkında faydalı bilgiler görüntüler.

    • [ ] RRO'nun kurulduğunu ve etkinleştirilmeye hazır olduğunu belirtir.
    • --- RRO'nun kurulu olduğunu ancak hatalar içerdiğini belirtir.
    • [X] RRO'nun kurulduğu ve etkinleştirildiği anlamına gelir.

    RRO'nuz hatalar içeriyorsa devam etmeden önce bkz. Çalışma zamanı kaynak katmanlarıyla ilgili sorunları giderme .

  7. RRO'yu etkinleştirmek ve etkinleştirildiğini doğrulamak için:

    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
    

Uygulamanız "Merhaba Dünya RRO" dizesini görüntüler.

Merhaba Dünya RRO!
Şekil 4 : Merhaba Dünya RRO!

Tebrikler! İlk RRO'nuzu yarattınız.

RRO'ları kullanırken, Bağlantı seçenekleri bölümünde açıklanan Android Varlık Paketleme Aracı (AAPT2) --no-resource-deduping ve --no-resource-removal bayraklarını kullanmak isteyebilirsiniz. Bayrakları bu codelab'e eklemeniz gerekli değildir, ancak kaynakların kaldırılmasını (ve hata ayıklama baş ağrılarını) önlemek için bunları RRO'larınızda kullanmanızı öneririz. Bunları RRO'nuzun build.gradle dosyasına şu şekilde ekleyebilirsiniz:

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

Bu bayraklar hakkında daha fazla bilgi edinmek için bkz. Paketi oluşturma ve AAPT2 .

Android uygulamanızda RRO'ları kullanarak car-ui-lib bileşenlerini değiştirin

Bu sayfada, Android uygulamanızdaki car-ui-lib kütüphanesindeki bileşenleri değiştirmek için çalışma zamanı kaynak katmanını (RRO) nasıl kullanabileceğinizi açıklanmaktadır.

Araç çubuğu arka plan rengini ayarlama

Süre: 15 dakika

Araç çubuğunun arka plan rengini değiştirmek için:

  1. RRO uygulamanıza aşağıdaki değeri ekleyin ve kaynağı parlak yeşil ( #0F0 ) olarak ayarlayın:

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

    car-ui-lib kütüphanesi car_ui_toolbar_background adında bir kaynak içerir. Bu kaynak bir RRO yapılandırmasında yer aldığında, yanlış değer hedeflendiğinden araç çubuğu değişmez.

  2. RRO'nuz için AndroidManifest.xml dosyasında, targetName car-ui-lib işaret edecek şekilde güncelleyin:

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

    RRO yapmak istediğiniz her hedef paket için yeni bir RRO paketi oluşturmanız GEREKİR. Örneğin iki farklı hedef için katman oluştururken iki katman apk'si oluşturmanız gerekir.

  3. RRO'yu daha önce olduğu gibi oluşturun, doğrulayın, yükleyin ve etkinleştirin.

Uygulamanız şu şekilde görünür:

Yeni Araç Çubuğu arka plan rengi
Şekil 5 : Yeni araç çubuğu arka plan rengi

RRO düzenleri ve stilleri

Süre: 15 dakika

Bu alıştırmada, daha önce oluşturduğunuz uygulamaya benzer yeni bir uygulama geliştireceksiniz. Bu uygulama düzenin üst üste bindirilmesine olanak tanır. Önceki adımların aynısını izleyin veya mevcut uygulamanızda değişiklik yapın.

  1. overlayable.xml dosyasına aşağıdaki satırları eklediğinizden emin olun:

    <?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. activity_main.xml dosyasının aşağıdaki gibi göründüğünden emin olun:

    <?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. RRO uygulamanızda res/layout/activity_main.xml dosyasını oluşturun ve aşağıdakileri ekleyin:

    <?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. Stilimizi RRO'ya eklemek için res/values/styles.xml dosyasını güncelleyin:

    <?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. Yeni uygulamanızın adını işaret edecek şekilde AndroidManifest.xml dosyasındaki targetName değerini değiştirin:

    …
    android:targetName="CarUiCodelab"
    …
    
  6. Kaynakları RRO'nuzdaki sample_overlay.xml dosyasına ekleyin:

    <?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. Uygulamayı ve RRO'yu öncekiyle aynı şekilde oluşturup yükleyin (yeşil Oynat düğmesi). RRO'nuzu etkinleştirdiğinizden emin olun.

Uygulama ve RRO aşağıdaki gibi oluşturulur. Merhaba Dünya RRO metni yeşildir ve RRO düzeninde belirtildiği gibi ortalanmıştır.

Merhaba Dünya RRO
Şekil 6 : Merhaba Dünya RRO

Uygulamanıza CarUiRecyclerView'ı ekleyin

Süre: 15 dakika

CarUiRecyclerView arayüzü, car-ui-lib kaynakları aracılığıyla özelleştirilmiş bir RecyclerView erişim için API'ler sağlar. Örneğin, CarUiRecyclerView kaydırma çubuğunun etkinleştirilip etkinleştirilmeyeceğini belirlemek için çalışma zamanında bir bayrağı kontrol eder ve ilgili düzeni seçer.

CarUiRecyclerViewContainer
Şekil 7. CarUiRecyclerViewContainer
  1. CarUiRecyclerView eklemek için bunu activity_main.xml ve MainActivity.java dosyalarınıza ekleyin. Sıfırdan yeni bir uygulama oluşturabilir veya mevcut uygulamayı değiştirebilirsiniz. Mevcut uygulamayı değiştirirseniz bildirilmemiş kaynakları overlayable.xml dosyasından kaldırdığınızdan emin olun.

    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"/>
    

    Göz ardı edebileceğiniz aşağıdaki hata görünebilir:

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

    Sınıfınız doğru yazıldığı ve car-ui-lib bağımlılık olarak eklediğiniz sürece apk'nizi oluşturabilir ve derleyebilirsiniz. Hatayı kaldırmak için Dosya > Önbellekleri Geçersiz Kıl'ı seçin ve ardından Geçersiz Kıl ve Yeniden Başlat'a tıklayın.

    MainActivity.java aşağıdakini ekleyin

    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. Uygulamanızı daha önce olduğu gibi oluşturun ve yükleyin.

Artık bir CarUiRecyclerView görüyorsunuz:

CarUiRecycler Görünümü
Şekil 7 : CarUiRecyclerView

Kaydırma çubuğunu kaldırmak için bir RRO kullanın

Süre: 10 dakika

Bu alıştırma, kaydırma çubuğunu CarUiRecyclerView kaldırmak için RRO'yu nasıl kullanacağınızı gösterir.

  1. RRO'nuza aşağıdaki dosyaları ekleyin ve değiştirin:

    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>
    

    car_ui_scrollbar_enable kaynağı, CarUiRecyclerView Yukarı ve Aşağı düğmeleriyle araba için optimize edilmiş kaydırma çubuğunun mevcut olup olmadığını kontrol eden bir car-ui-lib boolean kaynağıdır. false olarak ayarlandığında CarUiRecyclerView , AndroidX RecyclerView gibi davranır.

    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>
    

Uygulamanızı daha önce olduğu gibi oluşturun ve yükleyin. Kaydırma çubuğu artık CarUiRecyclerView kaldırılmıştır:

Kaydırma çubuğu olmayan CarUiRecyclerView
Şekil 8. Kaydırma çubuğu olmayan CarUiRecyclerView

CarUiRecyclerView kaydırma çubuğunu kaplamak için bir düzen kullanın

Süre: 15 dakika

Bu alıştırmada CarUiRecyclerView kaydırma çubuğu düzenini değiştireceksiniz.

  1. Aşağıdaki dosyaları RRO uygulamanıza ekleyin ve değiştirin.

    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>
    

    Bir düzen dosyasını kaplamak için tüm kimlikleri ve ad alanı niteliklerini RRO'nuzun overlay.xml dosyasına eklemeniz gerekir. Aşağıdaki dosyalara bakın.

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
       <item target="drawable/car_ui_recyclerview_ic_down" value="@drawable/car_ui_recyclerview_ic_down"/>
       <item target="drawable/car_ui_recyclerview_ic_up" value="@drawable/car_ui_recyclerview_ic_up"/>
       <item target="drawable/car_ui_recyclerview_scrollbar_thumb" value="@drawable/car_ui_recyclerview_scrollbar_thumb"/>
       <item target="id/car_ui_scroll_bar" value="@id/car_ui_scroll_bar"/>
       <item target="id/car_ui_scrollbar_thumb" value="@id/car_ui_scrollbar_thumb"/>
       <item target="id/car_ui_scrollbar_track" value="@id/car_ui_scrollbar_track"/>
       <item target="id/car_ui_scrollbar_page_up" value="@id/car_ui_scrollbar_page_up"/>
       <item target="id/car_ui_scrollbar_page_down" value="@id/car_ui_scrollbar_page_down"/>
       <item target="layout/car_ui_recyclerview_scrollbar" value="@layout/car_ui_recyclerview_scrollbar"/>
    </overlay>
    

    res/drawable/car_ui_recyclerview_ic_up.xml

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="48.0"
        android:viewportHeight="48.0">
        <path
            android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z"
            android:fillColor="#0000FF"/>
    </vector>
    

    res/drawable/car_ui_recyclerview_ic_down.xml

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="48.0"
        android:viewportHeight="48.0">
        <path
            android:pathData="M14.83,16.42L24,25.59l9.17,-9.17L36,19.25l-12,12 -12,-12z"
            android:fillColor="#0000FF"/>
    </vector>
    

    res/drawable/car_ui_recyclerview_scrollbar_thumb.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <solid android:color="#0000FF" />
        <corners android:radius="100dp"/>
    </shape>
    

    Bu dosyaların nasıl etkileşimde bulunduğunun incelenmesi önerilmektedir.

    Basitlik açısından boyutlar ve renkler sabit kodlanmıştır. Ancak en iyi uygulama, bu değerleri dimens.xml ve colors.xml dosyasında bildirmek, hatta res/color/ klasöründe renk dosyaları olarak belirlemektir. Daha fazla bilgi edinmek için bkz . Katkıda bulunanlar için AOSP Java kod stili .

  2. Uygulamanızı daha önce olduğu gibi oluşturun ve yükleyin. CarUiRecyclerView mavi kaydırma çubuğu ve gri raylarla oluşturdunuz.

Tebrikler! Her iki ok da kaydırma çubuğunun alt kısmında görünür. Android Studio aracılığıyla Gradle derleme sistemini kullanarak bir car-ui-lib düzen kaynak dosyasına başarıyla bir RRO uyguladınız.

Gri raylı mavi kaydırma çubuğuna sahip CarUiRecyclerView
Şekil 9. Gri raylı mavi kaydırma çubuğuna sahip CarUiRecyclerView

RRO Liste öğeleri

Süre: 15 dakika

Bu noktaya kadar, çerçeve bileşenlerini (AndroidX değil) kullanarak car-ui-lib bileşenlerine bir RRO uyguladınız. AndroidX bileşenlerini bir RRO'da kullanmak için, o bileşenin bağımlılıklarını hem uygulamaya hem de RRO build.gradle. Ayrıca bu bileşenin attrs uygulamanızdaki overlayable.xml dosyasına ve RRO'nuzdaki sample_overlay.xml eklemeniz gerekir.

Kütüphanemiz ( car-ui-lib ) ConstraintLayout yanı sıra diğer AndroidX bileşenlerini de kullanıyor, dolayısıyla overlayable.xml dosyası şöyle görünebilir:

<?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. CarUiRecyclerView liste öğelerinin düzenini ConstraintLayout kullanarak değiştirin. Aşağıdaki dosyaları RRO'nuza ekleyin veya değiştirin:

    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 çeşitli referanslara, uygulamanın bağımlılıkları olarak dahil edilmeyen çeşitli bileşenlere/kaynaklara referans verir. Bunlar car-ui-lib kaynaklarıdır. Bunu, app/build.gradle dosyasındaki RRO uygulamanıza bağımlılık olarak car-ui-lib ekleyerek düzeltebilirsiniz:

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

Başlık ve Gövde artık sola hizalanmak yerine sağa hizalanıyor.

Sağa hizalanmış Başlık ve Gövde
Şekil 10. Sağa Hizalanmış Başlık ve Gövde

Bir RRO'yu yalnızca AndroidX bileşenlerini ( ConstraintLayout ) kullanarak car-ui-lib , RRO sample_overlay.xml yanı sıra overlayable.xml adlı car-ui-lib dosyasında da nitelikleri mevcut olduğunda uyguladık. Kendi uygulamanızda da benzer bir şey yapmak mümkündür. car-ui-lib benzer şekilde, ilgili tüm attrs uygulamanızın overlayable.xml dosyasına eklemeniz yeterlidir.

Ancak uygulamanın build.gradle dosyasında car-ui-lib bağımlılığı varsa (uygulama car-ui-lib bileşenlerini kullandığında) AndroidX bileşenlerini kullanan bir uygulamayı RRO yapmak mümkün değildir . Öznitelik eşlemeleri car-ui-lib kitaplığının overlayable.xml dosyasında zaten tanımlandığından, bunları uygulamanızın overlayable.xml dosyasına car-ui-lib ile bağımlılık olarak eklemek, aşağıdaki gibi mergeDebugResources hatasına neden olur. Bunun nedeni, bu niteliklerin birden fazla overlayable.xml dosyasında mevcut olmasıdır:

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