Codelab: Gradle derleme sistemini kullanarak car-ui-lib bileşenleriyle RRO'lar oluşturma

Kendi kendine tutarlı, araç içi bilgi-eğlence (IVI) sistemlerini başlatmak için car-ui-lib kitaplığını kullanın. Bu codelab'de, car-ui-lib ile kitaplıktaki bileşenleri özelleştirmek için çalışma zamanında kaynak yer paylaşımlarını (RRO'lar) nasıl kullanabileceğiniz açıklanmaktadır.

Öğrenecekleriniz

Nasıl yapılır?

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

Bu codelab'de, RRO'ların işleyiş şekli ayrıntılı olarak açıklanmamıştır. Daha fazla bilgi edinmek için Bir uygulamanın kaynaklarının değerini çalışma zamanında değiştirme ve Çalışma zamanında kaynak yer paylaşımlarıyla ilgili sorunları giderme başlıklı makaleleri inceleyin.

Başlamadan önce

Ön koşullar

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

  • Komut satırı bulunan bilgisayar (Linux makinesi, Mac veya Linux için Windows alt sistemi bulunan Windows makinesi).

  • Android Studio.

  • Cihazınıza bağlı bir Android cihaz veya emülatör. Android kaynağını indirme ve Android'i derleme başlıklı makaleleri inceleyin.

  • RRO'lar hakkında temel düzeyde bilgi sahibi olma

Yeni bir Android uygulaması oluşturma

Süre: 15 dakika

Bu bölümde yeni bir Android Studio projesi oluşturursunuz.

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

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

     Uygulamanıza ad verme
    Şekil 2. Uygulamanızı adlandırma
  3. activity_main.xml öğesini aşağıdaki kod blokuyla 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ış sample_text dizesini gösterir.

  4. strings.xml dosyanıza sample_text kaynak dizesini ekleyin ve "Merhaba Dünya!" olarak ayarlayın. Bu dosyayı açmak için app > src > main > res > values > strings.xml'i 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. Bu işlem, APK'yı Gradle aracılığıyla otomatik olarak emülatörünüze veya Android cihazınıza yükler.

    Oynat düğmesi

Yeni uygulama, emülatörünüzde veya Android cihazınızda otomatik olarak açılır. Aksi takdirde, uygulama başlatıcıdan CarUiCodelab uygulamasını (artık yüklü) açın. Bu şekilde görünür:

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

car-ui-lib'i Android uygulamanıza ekleme

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 uygulama > build.gradle'yi seçin. Bağımlılıklarınız aşağıdaki gibi 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 kullanma

car-ui-lib'e sahip olduğunuza 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 dosyasını 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 app > src > main > AndroidManifest.xml'i 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ı derlemek için daha önce olduğu gibi yeşil Oynat düğmesine basın.

    Uygulamayı oluşturma

Uygulamanıza RRO ekleme

Süre: 30 dakika

RRO'ları biliyorsanız Uygulamanıza izin denetleyici ekleme başlıklı sonraki bölüme gidin. Aksi takdirde, RRO'ların temellerini öğrenmek için Uygulamanın kaynaklarının değerini çalışma zamanında değiştirme başlıklı makaleyi inceleyin.

Uygulamanıza izin denetleyici ekleme

Bir RRO paketinin hangi kaynakların üzerine bineceğini 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. Uygulamanıza res/values/overlayable.xml 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 dizesi bir RRO tarafından yer paylaşımına uygun olmalıdır. Bu nedenle, kaynak adını uygulamanın overlayable.xml dosyasına ekleyin.

    overlayable.xml dosyanız res/values/ içinde OLMALIDIR. Aksi takdirde OverlayManagerService bu öğeyi bulamaz.

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

RRO paketi oluşturma

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

  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ğıdaki görselde gösterilenlere benzer şekilde görünür. Kayıtlı oldukları konum farklı olabilir:

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

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

    Bu işlem, @xml/sample_overlay ile ilgili bir hata oluşturur. resourcesMap dosyası, hedef paketteki kaynak adlarını RRO paketiyle eşler. hasCode işaretini false olarak ayarlamak, RRO paketleri için zorunludur. Ayrıca, RRO paketlerinin DEX dosyaları içermesine izin verilmez.

  3. Aşağıdaki kod bloğunu …/res/xml/sample_overlay.xml alanına 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'a ekleme:

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

  6. RRO'nuzun düzgün şekilde yüklendiğini doğrulamak için şunları ç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österir.

    • [ ], RRO'nun yüklü olduğunu ve etkinleştirilmeye hazır olduğunu gösterir.
    • ---, RRO'nun yüklü olduğunu ancak hata içerdiğini gösterir.
    • [X], RRO'nun yüklü ve etkin olduğu anlamına gelir.

    RRO'nuz hata içeriyorsa devam etmeden önce Çalışma zamanında kaynak yer paylaşımı sorunlarını giderme başlıklı makaleyi inceleyin.

  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österiyor.

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

Tebrikler! İlk RRO'nuzu oluşturdunuz.

RRO'ları kullanırken Bağlantı seçenekleri bölümünde açıklanan Android Asset Packaging Tool (AAPT2) --no-resource-deduping ve --no-resource-removal işaretlerini kullanabilirsiniz. Bu codelab'e işaretleri eklemeniz gerekmez ancak kaynakların kaldırılmasını (ve hata ayıklamayla ilgili baş ağrılarını) önlemek için RRO'larınızda bu işaretleri kullanmanızı öneririz. Bunları RRO'nuzun build.gradle dosyasına aşağıdaki gibi ekleyebilirsiniz:

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

Bu işaretler hakkında daha fazla bilgi edinmek için Paketi derleme ve AAPT2 başlıklı makaleleri inceleyin.

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

Bu sayfada, Android uygulamanızdaki car-ui-lib kitaplığındaki bileşenleri değiştirmek için çalışma zamanında kaynak yer paylaşımını (RRO) nasıl kullanabileceğiniz 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şile (#0F0) ayarlayın:

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

    car-ui-lib kitaplığında car_ui_toolbar_background adlı bir kaynak var. Bu kaynak, bir RRO'nun yapılandırmasında yer aldığında yanlış değer hedeflendiği için araç çubuğu değişmez.

  2. RRO'nuz için AndroidManifest.xml içinde targetName'u car-ui-lib'ye yönlendirecek şekilde güncelleyin:

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

    RRO yapmak istediğiniz her hedef paket için yeni bir RRO paketi OLUŞTURMANIZ GEREKİR. Örneğin, iki farklı hedef için yer paylaşımı oluştururken iki yer paylaşımı apk'sı oluşturmanız gerekir.

  3. RRO'yu daha önce yaptığınız gibi derleyin, doğrulayın, yükleyin ve etkinleştirin.

Uygulamanız şöyle 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 oluşturursunuz. Bu uygulama, düzenin yer paylaşımına uygun olmasına olanak tanır. Önceki adımlardan aynısını uygulayın veya mevcut uygulamanızı değiştirin.

  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'ü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 bir res/layout/activity_main.xml 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. res/values/styles.xml öğesini güncelleyerek stilimizi RRO'ya ekleyin:

    <?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. AndroidManifest.xml içindeki targetName değerini yeni uygulamanızın adına yönlendirecek şekilde 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 daha önce olduğu gibi (yeşil Oynat düğmesi) derleyip yükleyin. RRO'nuzu etkinleştirdiğinizden emin olun.

Uygulama ve RRO aşağıdaki gibi oluşturulur. Merhaba Dünya RRO metni yeşildir ve düzen RRO'sunda belirtildiği gibi ortalanmalıdır.

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

Uygulamanıza CarUiRecyclerView ekleme

Süre: 15 dakika

CarUiRecyclerView arayüzü, car-ui-lib kaynakları aracılığıyla özelleştirilmiş bir RecyclerView'a erişmek 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 işareti kontrol eder ve ilgili düzeni seçer.

CarUiRecyclerViewContainer
Şekil 7. CarUiRecyclerViewContainer
  1. CarUiRecyclerView eklemek için 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 beyan edilmemiş kaynakları overlayable.xml'ten 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"/>
    

    Aşağıdaki hatayı görebilirsiniz. Bu hatayı yoksayabilirsiniz:

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

    Sınıfınızın yazımı doğru olduğu ve car-ui-lib'ü bağımlılık olarak eklediğiniz sürece APK'nızı derleyip derleyebilirsiniz. Hatayı kaldırmak için Dosya > Önbellekleri Geçersiz Kıl'ı seçip Geçersiz kıl ve yeniden başlat'ı tıklayın.

    Aşağıdakileri MainActivity.java alanına 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ı eskisi gibi derleyip yükleyin.

Artık CarUiRecyclerView görüyorsunuz:

CarUiRecyclerView
Şekil 7 : CarUiRecyclerView

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

Süre: 10 dakika

Bu alıştırmada, CarUiRecyclerView'ten kaydırma çubuğunu kaldırmak için RRO'nun nasıl kullanılacağı gösterilmektedir.

  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 öğesinde yukarı ve aşağı düğmeleri bulunan otomobile optimize edilmiş kaydırma çubuğunun mevcut olup olmadığını kontrol eden bir car-ui-lib boole 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ı eskisi gibi derleyip yükleyin. Kaydırma çubuğu şuradan kaldırıldı:CarUiRecyclerView

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

CarUiRecyclerView kaydırma çubuğunu yer paylaşımı yapmak 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. RRO uygulamanıza aşağıdaki dosyaları 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ı yer paylaşımı yapmak için kimliklerin ve ad alanının tümünü RRO'nuzun overlay.xml bölümüne eklemeniz gerekir. Aşağıdaki dosyaları inceleyin.

    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ğunu incelemeniz önerilir.

    Kolaylık sağlamak için boyutlar ve renkler sabit kodlanmıştır. Ancak en iyi uygulama, bu değerleri dimens.xml ve colors.xml içinde veya hatta res/color/ klasöründe renk dosyaları olarak tanımlamaktır. Daha fazla bilgi için Katkıda bulunanlar için AOSP Java kod stili başlıklı makaleyi inceleyin.

  2. Uygulamanızı eskisi gibi derleyip yükleyin. Mavi kaydırma çubuğu ve gri raylar içeren CarUiRecyclerView oluşturdunuz.

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

Gri raylara sahip mavi kaydırma çubuğu olan CarUiRecyclerView
Şekil 9. Gri raylara sahip mavi kaydırma çubuğu içeren CarUiRecyclerView

RRO Liste öğeleri

Süre: 15 dakika

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

Kitaplığımız (car-ui-lib), diğer AndroidX bileşenlerinin yanı sıra ConstraintLayout'ü kullandığından overlayable.xml şu şekilde 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. ConstraintLayout'u kullanarak CarUiRecyclerView'teki liste öğelerinin düzenini değiştirin. RRO'nuza aşağıdaki dosyaları ekleyin veya mevcut dosyaları 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, uygulamanın bağımlılıkları olarak dahil edilmeyen çeşitli bileşenlere/kaynaklara referans verir. Bunlar car-ui-lib kaynaklarıdır. Bu sorunu, app/build.gradle'teki RRO uygulamanıza car-ui-lib'ü bağımlılık olarak 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 hizalanmış yerine sağa hizalanmış.

Sağa hizalanmış başlık ve gövde
Şekil 10. Sağ hizalı başlık ve gövde

AndroidX bileşenlerini (ConstraintLayout) kullanarak car-ui-lib'e yalnızca car-ui-lib adlı dosyada ve sample_overlay.xml adlı RRO'da özellikleri bulunduğunda RRO uyguladık.overlayable.xml Kendi uygulamanızda da benzer bir şey yapabilirsiniz. car-ui-lib'ye benzer şekilde, ilgili tüm attrs öğelerini uygulamanızın overlayable.xml bölümüne eklemeniz yeterlidir.

Ancak uygulamanın build.gradle dosyasında car-ui-lib bağımlılığı varsa (uygulama car-ui-lib bileşenlerini kullanıyorsa) AndroidX bileşenlerini kullanan bir uygulamanın RRO'su yapılamaz. Özellik eşlemeleri car-ui-lib kitaplığının overlayable.xml bölümünde zaten tanımlanmış olduğundan, bunları car-ui-lib bağımlılığıyla birlikte uygulamanızın overlayable.xml bölümüne eklemek aşağıdaki gibi bir mergeDebugResources hatasına neden olur. Bunun nedeni, aşağıdaki özelliklerin birden fazla overlayable.xml dosyasında bulunmasıdır:

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