Codelab: RROها را با اجزای car-ui-lib با استفاده از سیستم ساخت Gradle ایجاد کنید

از کتابخانه car-ui-lib برای راه‌اندازی سیستم‌های سرگرمی (IVI) خودسازگار، درون خودرویی استفاده کنید. این Codelab شما را با car-ui-lib و نحوه استفاده از همپوشانی منابع زمان اجرا (RRO) برای سفارشی کردن اجزای کتابخانه آشنا می کند.

چیزی که یاد خواهید گرفت

چگونه:

  • اجزای car-ui-lib را در برنامه اندروید خود قرار دهید.
  • از Gradle برای ساخت برنامه های اندروید و RRO استفاده کنید.
  • از RRO با car-ui-lib استفاده کنید.

این کد لبه جزئیات نحوه عملکرد RRO ها را توضیح نمی دهد. برای اطلاعات بیشتر به تغییر مقدار منابع برنامه در زمان اجرا و عیب یابی همپوشانی منابع زمان اجرا مراجعه کنید.

قبل از اینکه تو شروع کنی

پیش نیازها

قبل از شروع، مطمئن شوید که:

یک برنامه اندروید جدید ایجاد کنید

مدت زمان: 15 دقیقه

در این بخش شما یک پروژه اندروید استودیو جدید ایجاد می کنید.

  1. در Android Studio یک برنامه با EmptyActivity ایجاد کنید.

    یک فعالیت خالی ایجاد کنید
    شکل 1. یک فعالیت خالی ایجاد کنید
  2. نام برنامه را CarUiCodelab بگذارید و سپس زبان جاوا را انتخاب کنید. در صورت تمایل می توانید محل فایل را نیز انتخاب کنید. مقادیر پیش فرض را برای تنظیمات باقیمانده بپذیرید.

    برنامه خود را نام ببرید
    شکل 2. نام برنامه خود را بگذارید
  3. بلوک کد زیر را جایگزین activity_main.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"
        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>
    

    این بلوک کد رشته sample_text نمایش می دهد که تعریف نشده است.

  4. رشته منبع sample_text را اضافه کنید و آن را روی "Hello World!" در فایل strings.xml شما. برای باز کردن این فایل، app > src > main > res > values ​​> strings.xml را انتخاب کنید.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiCodelab</string>
        <string name="sample_text">Hello World!</string>
    </resources>
    
  5. برای ساخت اپلیکیشن خود، روی دکمه سبز رنگ Play در بالا سمت راست کلیک کنید. با انجام این کار، apk به طور خودکار از طریق Gradle در شبیه ساز یا دستگاه اندرویدی شما نصب می شود.

    دکمه پخش

برنامه جدید باید به طور خودکار در شبیه ساز یا دستگاه اندروید شما باز شود. اگر نه، برنامه CarUiCodelab را از راه‌انداز برنامه باز کنید، که اکنون نصب شده است. به نظر می رسد اینگونه است:

برنامه جدید CarUiCodelab را باز کنید
شکل 3. برنامه جدید CarUiCodelab را باز کنید

car-ui-lib را به برنامه اندروید خود اضافه کنید

مدت زمان: 15 دقیقه

car-ui-lib به برنامه خود اضافه کنید:

  1. برای افزودن وابستگی car-ui-lib به فایل build.gradle پروژه خود، 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'
        implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    }
    

از اجزای car-ui-lib در برنامه اندروید خود استفاده کنید

اکنون که car-ui-lib دارید، یک نوار ابزار به برنامه خود اضافه کنید.

  1. در فایل MainActivity.java ، روش 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. حتماً ToolbarController وارد کنید:

    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.toolbar.ToolbarController;
    
  3. برای استفاده از تم Theme.CarUi.WithToolbar ، app > src > main > AndroidManifest.xml را انتخاب کنید و سپس AndroidManifest.xml به‌روزرسانی کنید تا به صورت زیر ظاهر شود:

    <?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. برای ساخت اپلیکیشن، دکمه سبز رنگ Play را مانند قبل فشار دهید.

    برنامه را بسازید

RRO ها را به برنامه خود اضافه کنید

مدت زمان: 30 دقیقه

اگر با RRO ها آشنایی دارید، به بخش بعدی بروید، یک کنترل کننده مجوز به برنامه خود اضافه کنید . در غیر این صورت، برای یادگیری اصول اولیه RRO ها، به تغییر مقدار منابع برنامه در زمان اجرا مراجعه کنید.

یک کنترل کننده مجوز به برنامه خود اضافه کنید

برای کنترل اینکه یک بسته RRO کدام منابع را پوشش می دهد، فایلی به نام overlayable.xml به پوشه /res برنامه خود اضافه کنید. این فایل به عنوان یک کنترل کننده مجوز بین برنامه شما ( هدف ) و بسته RRO شما ( همپوشانی ) عمل می کند.

  1. res/values/overlayable.xml به برنامه خود اضافه کنید و محتوای زیر را در فایل خود کپی کنید:

    <?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 باید توسط یک RRO قابل همپوشانی باشد، نام منبع را در برنامه overlayable.xml قرار دهید.

    فایل overlayable.xml شما باید در res/values/ قرار داشته باشد. اگر نه، OverlayManagerService نمی تواند آن را پیدا کند.

    برای کسب اطلاعات بیشتر در مورد منابع قابل همپوشانی و نحوه پیکربندی آنها، به محدود کردن منابع قابل همپوشانی مراجعه کنید.

یک بسته RRO ایجاد کنید

در این بخش، یک بسته RRO ایجاد می کنید تا رشته نمایش داده شده در بالا را از "Hello World!" به "Hello World RRO".

  1. برای ایجاد یک پروژه جدید، File > New > New Project را انتخاب کنید. مطمئن شوید که No Activity را به جای Empty Activity انتخاب کنید زیرا بسته های RRO فقط حاوی منابع هستند.

    تنظیمات شما مشابه آنچه در زیر نشان داده شده است ظاهر می شود. مکانی که آنها در آن ذخیره می شوند ممکن است متفاوت باشد:

  2. پس از ایجاد پروژه جدید CarUiRRO ، پروژه را با تغییر AndroidManifest.xml به عنوان یک RRO اعلام کنید.

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

    با انجام این کار خطایی با @xml/sample_overlay ایجاد می شود. فایل resourcesMap نام منابع را از بسته هدف به بسته RRO نگاشت می کند.

  3. بلوک کد زیر را در …/res/xml/sample_overlay.xml کپی کنید:

    <?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 اضافه کنید:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiRRO</string>
        <string name="sample_text">Hello World RRO</string>
    </resources>
    
    ساخت Gradle از RRO ایجاد شد
  5. برای ساختن هدف RRO خود، دکمه سبز رنگ Play را فشار دهید تا یک ساخت Gradle از RRO خود در شبیه ساز یا دستگاه اندرویدی خود ایجاد کنید.

  6. برای تأیید اینکه RRO شما به درستی نصب شده است، اجرا کنید:

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

    این دستور اطلاعات مفیدی را در مورد وضعیت بسته های RRO در سیستم نمایش می دهد.

    • [ ] مشخص می کند که RRO نصب شده و آماده فعال سازی است.
    • --- نشان می دهد که RRO نصب شده است اما دارای خطا است.
    • [X] به این معنی است که RRO نصب و فعال شده است.

    اگر RRO شما دارای خطا است، قبل از ادامه به عیب یابی همپوشانی منابع زمان اجرا مراجعه کنید.

  7. برای فعال کردن RRO و تأیید فعال بودن آن:

    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
    

برنامه شما رشته "Hello World RRO" را نمایش می دهد.

سلام جهان RRO!
شکل 4 : Hello World RRO!

تبریک می گویم! شما اولین RRO خود را ایجاد کرده اید.

هنگام استفاده از RRO، ممکن است بخواهید از پرچم‌های ابزار بسته‌بندی دارایی Android (AAPT2) --no-resource-deduping و --no-resource-removal شرح داده شده در گزینه‌های پیوند استفاده کنید. اضافه کردن پرچم‌ها در این لبه کد ضروری نیست، اما پیشنهاد می‌کنیم برای جلوگیری از حذف منابع (و سردرد اشکال‌زدایی) از آنها در RRO خود استفاده کنید. می توانید آنها را به فایل build.gradle RRO خود اضافه کنید:

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

برای کسب اطلاعات بیشتر در مورد این پرچم ها، به ساخت بسته و AAPT2 مراجعه کنید.

اجزای car-ui-lib را با استفاده از RRO در برنامه اندروید خود تغییر دهید

این صفحه نحوه استفاده از همپوشانی منبع زمان اجرا (RRO) را برای تغییر اجزای کتابخانه car-ui-lib در برنامه Android خود توضیح می دهد.

رنگ پس زمینه نوار ابزار را تنظیم کنید

مدت زمان: 15 دقیقه

برای تغییر رنگ پس زمینه نوار ابزار:

  1. مقدار زیر را به برنامه RRO خود اضافه کنید و منبع را روی سبز روشن تنظیم کنید ( #0F0 ):

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

    کتابخانه car-ui-lib حاوی منبعی به نام car_ui_toolbar_background است. هنگامی که این منبع در پیکربندی یک RRO وجود دارد، نوار ابزار تغییر نمی کند زیرا مقدار اشتباهی مورد هدف قرار گرفته است.

  2. در AndroidManifest.xml برای RRO خود، targetName به‌روزرسانی کنید تا به car-ui-lib اشاره کند:

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

    شما باید یک بسته RRO جدید برای هر بسته هدفی که می خواهید RRO ایجاد کنید. به عنوان مثال، هنگام ایجاد پوشش برای دو هدف مختلف، باید دو apk همپوشانی ایجاد کنید.

  3. RRO را به همان روش قبلی بسازید، تأیید کنید، نصب کنید و فعال کنید.

برنامه شما به این شکل ظاهر می شود:

رنگ پس زمینه نوار ابزار جدید
شکل 5 : رنگ پس زمینه نوار ابزار جدید

طرح بندی و سبک های RRO

مدت زمان: 15 دقیقه

در این تمرین، یک اپلیکیشن جدید شبیه به اپلیکیشنی که قبلا ساخته بودید، می سازید. این برنامه اجازه می دهد تا طرح را روی هم قرار دهید. همان مراحل قبلی را دنبال کنید یا برنامه موجود خود را تغییر دهید.

  1. حتماً خطوط زیر را به 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. اطمینان حاصل کنید activity_main.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"
        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 خود، یک res/layout/activity_main.xml ایجاد کنید و موارد زیر را اضافه کنید:

    <?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. برای اضافه کردن سبک خود به RRO res/values/styles.xml را به‌روزرسانی کنید:

    <?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. targetName در AndroidManifest.xml تغییر دهید تا به نام برنامه جدید خود اشاره کنید:

    …
    android:targetName="CarUiCodelab"
    …
    
  6. منابع را به فایل sample_overlay.xml در RRO خود اضافه کنید:

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="string/sample_text" value="@string/sample_text"/>
        <item target="id/textView" value="@id/textView"/>
        <item target="layout/activity_main" value="@layout/activity_main"/>
    </overlay>
    
  7. برنامه و RRO را به همان روش قبلی بسازید و نصب کنید (دکمه سبز بازی ). حتما RRO خود را فعال کنید.

برنامه و RRO به صورت زیر ارائه می شوند. متن Hello World RRO سبز است و همانطور که در طرح بندی RRO مشخص شده است در مرکز قرار دارد.

سلام جهان RRO
شکل 6 : Hello World RRO

CarUiRecyclerView را به برنامه خود اضافه کنید

مدت زمان: 15 دقیقه

رابط CarUiRecyclerView APIهایی را برای دسترسی به RecyclerView فراهم می کند که از طریق منابع car-ui-lib سفارشی شده است. به عنوان مثال، CarUiRecyclerView یک پرچم را در زمان اجرا بررسی می کند تا تعیین کند که آیا نوار اسکرول باید فعال باشد یا نه و طرح مربوطه را انتخاب می کند.

CarUiRecyclerViewContainer
شکل 7. CarUiRecyclerViewContainer
  1. برای افزودن CarUiRecyclerView ، آن را به فایل های activity_main.xml و MainActivity.java خود اضافه کنید. می توانید یک برنامه جدید از ابتدا ایجاد کنید یا برنامه موجود را تغییر دهید. اگر برنامه موجود را تغییر می‌دهید، حتماً منابع اعلام‌نشده را از 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"/>
    

    ممکن است خطای زیر ظاهر شود که می توانید آن را نادیده بگیرید:

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

    تا زمانی که کلاس شما درست نوشته شده باشد و car-ui-lib به عنوان وابستگی اضافه کرده باشید، می توانید apk خود را بسازید و کامپایل کنید. برای حذف خطا، File > Invalidate Caches را انتخاب کنید سپس روی Invalidate و Restart کلیک کنید.

    موارد زیر را به 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. برنامه خود را مانند قبل بسازید و نصب کنید.

اکنون CarUiRecyclerView را می بینید:

CarUiRecyclerView
شکل 7 : CarUiRecyclerView

از یک RRO برای حذف نوار اسکرول استفاده کنید

مدت زمان: 10 دقیقه

این تمرین به شما نشان می دهد که چگونه از یک RRO برای حذف نوار اسکرول از CarUiRecyclerView استفاده کنید.

  1. در RRO خود، فایل های زیر را اضافه و اصلاح کنید:

    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 یک منبع بولی car-ui-lib است که کنترل می‌کند نوار اسکرول بهینه‌سازی شده خودرو با دکمه‌های بالا و پایین در CarUiRecyclerView وجود داشته باشد یا خیر. وقتی روی false تنظیم شود، CarUiRecyclerView مانند AndroidX RecyclerView عمل می کند.

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="bool/car_ui_scrollbar_enable" value="@bool/car_ui_scrollbar_enable"/>
    </overlay>
    

برنامه خود را مانند قبل بسازید و نصب کنید. اکنون نوار اسکرول از CarUiRecyclerView حذف شده است:

CarUiRecyclerView بدون اسکرول
شکل 8. CarUiRecyclerView بدون اسکرول

از یک طرح برای همپوشانی نوار اسکرول CarUiRecyclerView استفاده کنید

مدت زمان: 15 دقیقه

در این تمرین، طرح نوار اسکرول CarUiRecyclerView را تغییر می دهید.

  1. فایل های زیر را در برنامه 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>
    

    برای همپوشانی یک فایل طرح بندی، باید تمام شناسه ها و ویژگی های فضای نام را به overlay.xml RRO خود اضافه کنید. فایل های زیر را ببینید.

    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>
    

    پیشنهاد می شود نحوه تعامل این فایل ها بررسی شود.

    برای سادگی، ابعاد و رنگ ها کدگذاری شده اند. با این حال، بهترین روش این است که این مقادیر را در dimens.xml و colors.xml یا حتی به عنوان فایل‌های رنگی در پوشه res/color/ تعیین کنید. برای کسب اطلاعات بیشتر، به سبک کد جاوا AOSP برای مشارکت کنندگان مراجعه کنید.

  2. برنامه خود را مانند قبل بسازید و نصب کنید. شما CarUiRecyclerView با اسکرول آبی و ریل های خاکستری ساخته اید.

تبریک می گویم! هر دو فلش در امتداد پایین نوار اسکرول ظاهر می‌شوند، شما با موفقیت یک RRO را به فایل منبع طرح‌بندی car-ui-lib با استفاده از سیستم ساخت Gradle از طریق Android Studio اعمال کرده‌اید.

CarUiRecyclerView با نوار پیمایش آبی با ریل های خاکستری
شکل 9. CarUiRecyclerView با نوار پیمایش آبی با ریل های خاکستری

موارد فهرست RRO

مدت زمان: 15 دقیقه

تا این مرحله، شما یک RRO را برای اجزای car-ui-lib با استفاده از اجزای چارچوب (نه AndroidX) اعمال کرده‌اید. برای استفاده از اجزای AndroidX در یک RRO، باید وابستگی‌های آن مؤلفه را هم به برنامه و هم به RRO build.gradle. همچنین باید attrs آن مؤلفه را به overlayable.xml در برنامه خود و همچنین sample_overlay.xml در RRO خود اضافه کنید.

کتابخانه ما ( car-ui-lib ) از ConstraintLayout و همچنین سایر مؤلفه های AndroidX استفاده می کند، بنابراین overlayable.xml آن ممکن است به شکل زیر باشد:

<?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 با استفاده از ConstraintLayout تغییر دهید. فایل های زیر را در RRO خود اضافه یا تغییر دهید:

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
       <item target="id/car_ui_list_item_touch_interceptor" value="@id/car_ui_list_item_touch_interceptor"/>
       <item target="id/car_ui_list_item_reduced_touch_interceptor" value="@id/car_ui_list_item_reduced_touch_interceptor"/>
       <item target="id/car_ui_list_item_start_guideline" value="@id/car_ui_list_item_start_guideline"/>
       <item target="id/car_ui_list_item_icon_container" value="@id/car_ui_list_item_icon_container"/>
       <item target="id/car_ui_list_item_icon" value="@id/car_ui_list_item_icon"/>
       <item target="id/car_ui_list_item_content_icon" value="@id/car_ui_list_item_content_icon"/>
       <item target="id/car_ui_list_item_avatar_icon" value="@id/car_ui_list_item_avatar_icon"/>
       <item target="id/car_ui_list_item_title" value="@id/car_ui_list_item_title"/>
       <item target="id/car_ui_list_item_body" value="@id/car_ui_list_item_body"/>
       <item target="id/car_ui_list_item_action_container_touch_interceptor" value="@id/car_ui_list_item_action_container_touch_interceptor"/>
       <item target="id/car_ui_list_item_action_container" value="@id/car_ui_list_item_action_container"/>
       <item target="id/car_ui_list_item_action_divider" value="@id/car_ui_list_item_action_divider"/>
       <item target="id/car_ui_list_item_switch_widget" value="@id/car_ui_list_item_switch_widget"/>
       <item target="id/car_ui_list_item_checkbox_widget" value="@id/car_ui_list_item_checkbox_widget"/>
       <item target="id/car_ui_list_item_radio_button_widget" value="@id/car_ui_list_item_radio_button_widget"/>
       <item target="id/car_ui_list_item_supplemental_icon" value="@id/car_ui_list_item_supplemental_icon"/>
       <item target="id/car_ui_list_item_end_guideline" value="@id/car_ui_list_item_end_guideline"/>
       <item target="attr/layout_constraintBottom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/>
       <item target="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintBottom_toTopOf"/>
       <item target="attr/layout_constraintEnd_toEndOf" value="@attr/layout_constraintEnd_toEndOf"/>
       <item target="attr/layout_constraintEnd_toStartOf" value="@attr/layout_constraintEnd_toStartOf"/>
       <item target="attr/layout_constraintGuide_begin" value="@attr/layout_constraintGuide_begin"/>
       <item target="attr/layout_constraintGuide_end" value="@attr/layout_constraintGuide_end"/>
       <item target="attr/layout_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/>
       <item target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_toLeftOf"/>
       <item target="attr/layout_constraintLeft_toRightOf" value="@attr/layout_constraintLeft_toRightOf"/>
       <item target="attr/layout_constraintRight_toLeftOf" value="@attr/layout_constraintRight_toLeftOf"/>
       <item target="attr/layout_constraintRight_toRightOf" value="@attr/layout_constraintRight_toRightOf"/>
       <item target="attr/layout_constraintStart_toEndOf" value="@attr/layout_constraintStart_toEndOf"/>
       <item target="attr/layout_constraintStart_toStartOf" value="@attr/layout_constraintStart_toStartOf"/>
       <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf"/>
       <item target="attr/layout_constraintTop_toTopOf" value="@attr/layout_constraintTop_toTopOf"/>
       <item target="attr/layout_goneMarginBottom" value="@attr/layout_goneMarginBottom"/>
       <item target="attr/layout_goneMarginEnd" value="@attr/layout_goneMarginEnd"/>
       <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginLeft"/>
       <item target="attr/layout_goneMarginRight" value="@attr/layout_goneMarginRight"/>
       <item target="attr/layout_goneMarginStart" value="@attr/layout_goneMarginStart"/>
       <item target="attr/layout_goneMarginTop" value="@attr/layout_goneMarginTop"/>
       <item target="attr/layout_constraintVertical_chainStyle" value="@attr/layout_constraintVertical_chainStyle"/>
       <item target="layout/car_ui_list_item" value="@layout/car_ui_list_item"/>
    </overlay>
    

    res/layout/car_ui_list_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:tag="carUiListItem"
        android:minHeight="@dimen/car_ui_list_item_height">
    
        <!-- The following touch interceptor views are sized to encompass the specific sub-sections of
        the list item view to easily control the bounds of a background ripple effects. -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <!-- This touch interceptor does not include the action container -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_reduced_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/car_ui_list_item_action_container"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/car_ui_list_item_start_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="@dimen/car_ui_list_item_start_inset" />
    
        <FrameLayout
            android:id="@+id/car_ui_list_item_icon_container"
            android:layout_width="@dimen/car_ui_list_item_icon_container_width"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="@+id/car_ui_list_item_start_guideline"
            app:layout_constraintTop_toTopOf="parent">
    
            <ImageView
                android:id="@+id/car_ui_list_item_icon"
                android:layout_width="@dimen/car_ui_list_item_icon_size"
                android:layout_height="@dimen/car_ui_list_item_icon_size"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_content_icon"
                android:layout_width="@dimen/car_ui_list_item_content_icon_width"
                android:layout_height="@dimen/car_ui_list_item_content_icon_height"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_avatar_icon"
                android:background="@drawable/car_ui_list_item_avatar_icon_outline"
                android:layout_width="@dimen/car_ui_list_item_avatar_icon_width"
                android:layout_height="@dimen/car_ui_list_item_avatar_icon_height"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
        </FrameLayout>
    
        <CarUiTextView
            android:id="@+id/car_ui_list_item_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
            android:singleLine="@bool/car_ui_list_item_single_line_title"
            android:textAppearance="@style/TextAppearance.CarUi.ListItem"
            android:layout_gravity="right"
            android:gravity="right"
            android:textAlignment="viewEnd"
            app:layout_constraintBottom_toTopOf="@+id/car_ui_list_item_body"
            app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container"
            app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
        <CarUiTextView
            android:id="@+id/car_ui_list_item_body"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
            android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
            android:layout_gravity="right"
            android:gravity="right"
            android:textAlignment="viewEnd"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container"
            app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container"
            app:layout_constraintTop_toBottomOf="@+id/car_ui_list_item_title"
            app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
    
        <!-- This touch interceptor is sized and positioned to encompass the action container   -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_action_container_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="@id/car_ui_list_item_action_container"
            app:layout_constraintEnd_toEndOf="@id/car_ui_list_item_action_container"
            app:layout_constraintStart_toStartOf="@id/car_ui_list_item_action_container"
            app:layout_constraintTop_toTopOf="@id/car_ui_list_item_action_container" />
    
        <FrameLayout
            android:id="@+id/car_ui_list_item_action_container"
            android:layout_width="wrap_content"
            android:minWidth="@dimen/car_ui_list_item_icon_container_width"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@+id/car_ui_list_item_end_guideline"
            app:layout_constraintTop_toTopOf="parent">
    
            <View
                android:id="@+id/car_ui_list_item_action_divider"
                android:layout_width="@dimen/car_ui_list_item_action_divider_width"
                android:layout_height="@dimen/car_ui_list_item_action_divider_height"
                android:layout_gravity="start|center_vertical"
                android:background="@drawable/car_ui_list_item_divider" />
    
            <Switch
                android:id="@+id/car_ui_list_item_switch_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <CheckBox
                android:id="@+id/car_ui_list_item_checkbox_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <RadioButton
                android:id="@+id/car_ui_list_item_radio_button_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_supplemental_icon"
                android:layout_width="@dimen/car_ui_list_item_supplemental_icon_size"
                android:layout_height="@dimen/car_ui_list_item_supplemental_icon_size"
                android:layout_gravity="center"
                android:scaleType="fitCenter" />
        </FrameLayout>
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/car_ui_list_item_end_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. car_ui_list_item.xml به چندین مرجع به چندین مؤلفه/منابع اشاره می کند که به عنوان وابستگی برنامه گنجانده نشده اند. اینها منابع car-ui-lib هستند. می توانید با افزودن car-ui-lib به عنوان وابستگی به برنامه RRO خود در 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'
    }
    

اکنون عنوان و متن به جای تراز چپ، راست چین شده اند.

عنوان و متن با تراز راست
شکل 10. عنوان و متن تراز راست

ما فقط زمانی یک RRO را برای car-ui-lib با استفاده از مؤلفه‌های AndroidX ( ConstraintLayout ) اعمال کردیم که ویژگی‌های آن در فایل car-ui-lib با نام overlayable.xml و همچنین RRO sample_overlay.xml وجود داشت. این امکان وجود دارد که کاری مشابه در برنامه خود انجام دهید. فقط کافی است تمام attrs مربوطه را به برنامه overlayable.xml اضافه کنید، مشابه car-ui-lib .

با این حال، زمانی که برنامه دارای car-ui-lib به عنوان یک وابستگی در build.gradle خود باشد (زمانی که برنامه از اجزای car-ui-lib استفاده می کند)، نمی توان برنامه ای را با استفاده از اجزای AndroidX RRO کرد. از آنجایی که نگاشت ویژگی ها قبلاً در overlayable.xml کتابخانه car-ui-lib تعریف شده بودند، افزودن آنها به overlayable.xml برنامه شما با car-ui-lib به عنوان یک وابستگی باعث ایجاد خطای mergeDebugResources مانند آنچه در زیر می شود می شود. این به این دلیل است که این ویژگی ها در چندین فایل overlayable.xml وجود دارند:

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