Codelab: สร้าง RRO ด้วยคอมโพเนนต์ Car-ui-lib โดยใช้ระบบบิลด์ Gradle

ใช้ไลบรารี car-ui-lib เพื่อเปิดระบบสาระบันเทิง (IVI) ในรถยนต์ที่ทำงานอย่างสอดคล้องกัน Codelab นี้จะแนะนำ car-ui-lib และวิธีใช้การวางซ้อนทรัพยากรรันไทม์ (RRO) เพื่อปรับแต่งคอมโพเนนต์ในไลบรารี

สิ่งที่คุณจะได้เรียนรู้

วิธีดำเนินการ

  • ใส่คอมโพเนนต์ car-ui-lib ในแอป Android
  • ใช้ Gradle เพื่อสร้างแอป Android และ RRO
  • ใช้ RRO กับ car-ui-lib

โค้ดแล็บนี้ไม่ได้อธิบายรายละเอียดเกี่ยวกับวิธีการทำงานของ RRO ดูข้อมูลเพิ่มเติมได้จากหัวข้อเปลี่ยนค่าของทรัพยากรของแอปที่รันไทม์ และแก้ปัญหาการวางซ้อนทรัพยากรรันไทม์

ก่อนจะเริ่มต้น

สิ่งที่ต้องมีก่อน

โปรดตรวจสอบว่าคุณมีสิ่งต่อไปนี้ก่อนที่จะเริ่มต้น

  • คอมพิวเตอร์ที่มีบรรทัดคำสั่ง (เครื่อง Linux, Mac หรือ Windows ที่มี Windows Subsystem for Linux)

  • Android Studio

  • อุปกรณ์ Android หรือโปรแกรมจำลองที่เชื่อมต่อกับเครื่อง ดูหัวข้อดาวน์โหลดซอร์สโค้ด Android และสร้าง Android

  • ความรู้พื้นฐานเกี่ยวกับ RRO

สร้างแอป Android ใหม่

ระยะเวลา: 15 นาที

ในส่วนนี้ คุณสร้างโปรเจ็กต์ Android Studio ใหม่

  1. สร้างแอปที่มี EmptyActivity ใน Android Studio

    สร้างกิจกรรมว่าง
    รูปที่ 1สร้างกิจกรรมว่าง
  2. ตั้งชื่อแอป CarUiCodelab แล้วเลือกภาษา Java นอกจากนี้ คุณยังเลือกตำแหน่งไฟล์ได้หากต้องการ ยอมรับค่าเริ่มต้นสําหรับการตั้งค่าที่เหลือ

     ตั้งชื่อแอป
    รูปที่ 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" encodin>g<="ut>f-8&q<uot;?
    resources
        st>ring name=&q<uot;app>_name<"CarUiCodelab/string>
        string <name=&q>u<ot;sample_>text"Hello World!/string
    /resources
    
  5. หากต้องการสร้างแอป ให้คลิกปุ่มเล่นสีเขียวที่ด้านขวาบน ซึ่งจะติดตั้ง APK ลงในโปรแกรมจำลองหรืออุปกรณ์ Android โดยอัตโนมัติผ่าน Gradle

    ปุ่มเล่น

แอปใหม่ควรเปิดขึ้นโดยอัตโนมัติในโปรแกรมจำลองหรืออุปกรณ์ Android หากไม่ได้เปิดไว้ ให้เปิดแอป CarUiCodelab จากตัวเปิดแอปซึ่งติดตั้งไว้แล้ว ซึ่งจะปรากฏดังนี้

เปิดแอป CarUiCodelab เวอร์ชันใหม่
รูปที่ 3 เปิดแอป CarUiCodelab ใหม่

เพิ่ม car-ui-lib ลงในแอป Android

ระยะเวลา: 15 นาที

วิธีเพิ่ม car-ui-lib ลงในแอป

  1. หากต้องการเพิ่มทรัพยากร Dependency car-ui-lib ลงในไฟล์ build.gradle ของโปรเจ็กต์ ให้เลือกแอป > 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 ในแอป Android

เมื่อคุณมี 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" encodin>g<="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:s<upportsRtl="true"
            android:theme="@style/Theme.CarUi.WithToolba>r"
         <   tools:targ>etApi="31&qu<ot;
            activity
                android:name=&quo>t;.MainActivity&qu<ot;
                android:exported="true"
            >    intent-fi<lter
             >       ac<tion andr>oid:n<ame="an>dr<oid.inten>t.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" encodin>g<="ut>f-8&q<uot;?
    resources
        overlayable> name=&qu<ot;CarUiCodelab">;
            pol<icy type="public"
              >  item ty<pe=&quo>t;str<ing" na>m<e="sa>mple_text"/
            /policy
        /overlayable
    /resources
    

    เนื่องจากสตริง sample_text ต้องวางซ้อนได้โดย RRO ให้ใส่ชื่อทรัพยากรใน overlayable.xml ของแอป

    ไฟล์ overlayable.xml ต้องอยู่ใน res/values/ หากไม่ OverlayManagerService จะหาตำแหน่งของไฟล์นั้นไม่ได้

    ดูข้อมูลเพิ่มเติมเกี่ยวกับทรัพยากรที่วางซ้อนได้และวิธีกำหนดค่าได้ที่จํากัดทรัพยากรที่วางซ้อนได้

สร้างแพ็กเกจ RRO

ในส่วนนี้ คุณจะได้สร้างแพ็กเกจ RRO เพื่อเปลี่ยนสตริงที่แสดงด้านบนจาก "Hello World!" เป็น "Hello World RRO"

  1. หากต้องการสร้างโปรเจ็กต์ใหม่ ให้เลือกไฟล์ > ใหม่ > โปรเจ็กต์ใหม่ โปรดตรวจสอบว่าได้เลือกไม่มีกิจกรรมแทนกิจกรรมว่าง เนื่องจากแพ็กเกจ RRO มีเฉพาะทรัพยากร

    การกำหนดค่าจะปรากฏคล้ายกับภาพด้านล่าง ตำแหน่งที่บันทึกรายการต่างๆ อาจแตกต่างกันไป ดังนี้

  2. หลังจากสร้างโปรเจ็กต์ CarUiRRO ใหม่แล้ว ให้ประกาศโปรเจ็กต์เป็น RRO โดยการแก้ไข AndroidManifest.xml

    <?xml version="1.0" encodin>g<="utf-8"?
    manifest xmlns:android="http://schemas.android.com/apk/res/android"
        >packag<e="com.example.caruirro"
    
     >   app<lication android:hasCode="false" /
    
        uses-sdk
            android:minSdkV>ersion<="29"
            android:targetSdkVersion="29"/
    
        overlay
            android:targetPackage="com.example.caruicodelab"
            android:targetName="CarUiCodelab"
       > <    andro>id:isStatic="false"
            android:resourcesMap="@xml/sample_overlay"
            /
    /manifest
    

    การดำเนินการนี้จะทำให้เกิดข้อผิดพลาดกับ @xml/sample_overlay ไฟล์ resourcesMap จะแมปชื่อทรัพยากรจากแพ็กเกจเป้าหมายไปยังแพ็กเกจ RRO การตั้งค่า Flag hasCode เป็น false เป็นสิ่งจำเป็นสำหรับแพ็กเกจ RRO นอกจากนี้ แพ็กเกจ RRO ต้องไม่มีไฟล์ DEX

  3. คัดลอกบล็อกโค้ดต่อไปนี้ลงใน …/res/xml/sample_overlay.xml

    <?xml version="1.0" encodin>g<=">utf-8<"?
    overlay
        item target="string/sample_text">;< value=&>quot;@string/sample_text"/
    /overlay
    
  4. วิธีเพิ่ม sample_text ลงใน …/res/values/strings.xml

    <?xml version="1.0" encodin>g<="ut>f-8&q<uot;?
    resources
        st>ring nam<e=">;app_<name"CarUiRRO/string>
        string nam<e=">;<sample_tex>t"Hello World RRO/string
    /resources
    
    สร้างบิลด์ Gradle ของ RRO
  5. หากต้องการสร้างเป้าหมาย RRO ให้กดปุ่ม Play สีเขียวเพื่อสร้าง Gradle build ของ RRO ในโปรแกรมจำลองหรืออุปกรณ์ Android

  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 คุณอาจต้องใช้ Flag --no-resource-deduping และ --no-resource-removal ของเครื่องมือแพ็กเกจเนื้อหา Android (AAPT2) ที่อธิบายไว้ในตัวเลือกการลิงก์ คุณไม่จำเป็นต้องเพิ่ม Flag ใน Codelab นี้ แต่เราขอแนะนำให้ใช้ Flag ใน RRO เพื่อหลีกเลี่ยงการนำทรัพยากรออก (และปัญหาในการแก้ไขข้อบกพร่อง) คุณสามารถเพิ่มข้อมูลดังกล่าวลงในไฟล์ build.gradle ของ RRO ได้โดยทำดังนี้

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับ Flag เหล่านี้ได้ที่หัวข้อสร้างแพ็กเกจและ AAPT2

แก้ไขคอมโพเนนต์ car-ui-lib โดยใช้ RRO ในแอป Android

หน้านี้จะอธิบายวิธีใช้การวางซ้อนทรัพยากรรันไทม์ (RRO) เพื่อแก้ไขคอมโพเนนต์จากไลบรารี car-ui-lib ในแอป Android

ตั้งค่าสีพื้นหลังของแถบเครื่องมือ

ระยะเวลา: 15 นาที

วิธีเปลี่ยนสีพื้นหลังของแถบเครื่องมือ

  1. เพิ่มค่าต่อไปนี้ลงในแอป RRO และตั้งค่าทรัพยากรเป็นสีเขียวสด (#0F0)

    <?xml version="1.0" encodin>g<="ut>f-8&q<uot;?
    resources
        drawable name="c>ar_u<i_toolbar>_<background>&quot;#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 ตัวอย่างเช่น เมื่อสร้างการวางซ้อนสําหรับเป้าหมาย 2 รายการที่แตกต่างกัน คุณต้องสร้าง Apk การวางซ้อน 2 รายการ

  3. สร้าง ยืนยัน ติดตั้ง และเปิดใช้ RRO ในลักษณะเดียวกับก่อนหน้านี้

แอปของคุณจะปรากฏดังนี้

สีพื้นหลังของแถบเครื่องมือใหม่
รูปที่ 5: สีพื้นหลังของแถบเครื่องมือใหม่

เลย์เอาต์และสไตล์ RRO

ระยะเวลา: 15 นาที

ในการฝึกนี้ คุณจะได้สร้างแอปใหม่ซึ่งคล้ายกับแอปที่สร้างไว้ก่อนหน้านี้ แอปนี้ช่วยให้วางเลย์เอาต์ซ้อนกันได้ ทำตามขั้นตอนเดิมหรือแก้ไขแอปที่มีอยู่

  1. อย่าลืมเพิ่มบรรทัดต่อไปนี้ลงใน overlayable.xml

    <?xml version="1.0" encodin>g<="ut>f-8<"?
    resources
      overlayable> name<="CarUiCodelab&>quot;
     <   policy type="public"
        >  item <type="string" name="sampl>e_text&<quot;/
          item type="la>yout&<quot; n>ame<="activ>i<ty_main&qu>ot;/
          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" encodin>g<="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/TextA>ppearance.CarUi"
          android:layout_gravity="center_vertical|center_horizontal"/
    /FrameLayout
    
  4. อัปเดต res/values/styles.xml เพื่อเพิ่มสไตล์ของเราลงใน RRO โดยทำดังนี้

    <?xml version="1.0" encodin>g<="ut>f-8&q<uot;?
    resources
        style name="TextAppearance.CarUi" parent="an>droid:Tex<tAppearance.DeviceDefault&quo>t;
     <     >  item na<me="android:textColor&q>uot;#<0f0/i>tem
     <      > <item name=>&quot;android:textSize"100sp/item
        /style
    /resources
    
  5. เปลี่ยน targetName ใน AndroidManifest.xml ให้ชี้ไปที่ชื่อแอปใหม่

    …
    android:targetName="CarUiCodelab"
    …
    
  6. เพิ่มทรัพยากรลงในไฟล์ sample_overlay.xml ใน RRO

    <?xml version="1.0" encodin>g<=">utf-8<"?
    overlay
        item target="string/sample_text">; val<ue="@string/sample_text"/
        item ta>rget=<"id/textView" value="@id/textView"/
        item >t<arget=&q>uot;layout/activity_main" value="@layout/activity_main"/
    /overlay
    
  7. สร้างและติดตั้งแอปและ RRO ในลักษณะเดียวกับก่อนหน้านี้ (ปุ่ม Play สีเขียว) อย่าลืมเปิดใช้ RRO

แอปและ RRO จะแสดงผลดังนี้ ข้อความ RRO ของ Hello World เป็นสีเขียวและอยู่ตรงกลางตามที่ระบุไว้ใน RRO ของเลย์เอาต์

Hello World RRO
รูปที่ 6: Hello World RRO

เพิ่ม CarUiRecyclerView ลงในแอป

ระยะเวลา: 15 นาที

อินเทอร์เฟซ CarUiRecyclerView มี API ในการเข้าถึง RecyclerView ที่ปรับแต่งผ่านทรัพยากร car-ui-lib ตัวอย่างเช่น CarUiRecyclerView จะตรวจสอบ Flag ที่รันไทม์เพื่อพิจารณาว่าควรเปิดใช้แถบเลื่อนหรือไม่ และเลือกเลย์เอาต์ที่เกี่ยวข้อง

CarUiRecyclerViewContainer
รูปที่ 7 CarUiRecyclerViewContainer
  1. หากต้องการเพิ่ม CarUiRecyclerView ให้เพิ่มลงในไฟล์ activity_main.xml และ MainActivity.java คุณสามารถสร้างแอปใหม่ตั้งแต่ต้นหรือแก้ไขแอปที่มีอยู่ก็ได้ หากแก้ไขแอปที่มีอยู่ โปรดอย่าลืมนำทรัพยากรที่ไม่ได้ประกาศออกจาก overlayable.xml

    activity_main.xml

    <?xml version="1.0" encodin>g<="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 ได้ หากต้องการนำข้อผิดพลาดออก ให้เลือกไฟล์ > ล้างแคช แล้วคลิกล้างและรีสตาร์ท

    เพิ่มรายการต่อไปนี้ไปยัง 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" encodin>g<="utf-8"?
    manifest xmlns:android="http://schemas.android.com/apk/res/android"
        >packag<e="com.example.caruirro"
    
     >   app<lication android:hasCode="false" /
    
        uses-sdk
            android:minSdkV>ersion<="29"
            android:targetSdkVersion="29"/
    
        overlay
            android:targetPackage="com.example.caruicodelab"
            android:targetName="car-ui-lib"
       > <    andro>id:isStatic="false"
            android:resourcesMap="@xml/sample_overlay"
            /
    /manifest
    

    res/values/bools.xml

    <?xml version="1.0" encodin>g<="ut>f-8&q<uot;?
    resources
        bool name=">;car_<ui_sc>r<ollbar_ena>ble"false/bool
    /resources
    

    ทรัพยากร car_ui_scrollbar_enable คือทรัพยากรบูลีน car-ui-lib ซึ่งควบคุมว่ามีแถบเลื่อนที่ปรับให้เหมาะกับรถยนต์พร้อมปุ่มขึ้นและลงใน CarUiRecyclerView หรือไม่ เมื่อตั้งค่าเป็น false CarUiRecyclerView จะทํางานเหมือน AndroidX RecyclerView

    res/xml/sample_overlay.xml

    <?xml version="1.0" encodin>g<=">utf-8<"?
    overlay
        item target="bool/car_ui_scrollbar_enable" value=&q>u<ot;@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" encodin>g<="utf-8"?
    RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="112dp"
        android:layout_height="match_pa>rent&<quot;
        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>_cent<erHorizontal="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="10>dp&qu<ot;
            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_hei>ght=&<quot;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:f>ocusa<ble="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&quo>t<;
            andro>id: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" encodin>g<=">utf-<8"?
    overlay
       item target="drawable/car_ui_recyclerview_ic_down" value="@dra>wabl<e/car_ui_recyclerview_ic_down"/
       item target="drawable/car_ui_recyclerview_ic_up&>quot<; value="@drawable/car_ui_recyclerview_ic_up"/
       item target="drawable/car_ui_recyclerview_scroll>bar_<thumb" value="@drawable/car_ui_recyclerview_scrollbar_t>humb<"/
       item target="id/car_ui_scroll_bar" value="@id/car>_ui_<scroll_bar"/
       item target="id/car_ui_scrollbar_thumb" valu>e=&q<uot;@id/car_ui_scrollbar_thumb"/
       item target="id/car_ui_scrollbar_>trac<k" value="@id/car_ui_scrollbar_track"/
       item target="id/car_u>i_sc<rollbar_page_up" value="@id/car_ui_scrollbar_page_up"/
       item target="id/car>_<ui_scrol>lbar_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" encodin>g<="utf-8"?
    vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:view>portW<idth="48.0"
        android:viewportHeight="48.0"
        path
            android:pathData="M14.83,30.83L>2<4,21.66>l9.17,9.17L36,28 24,16 12,28z"
            android:fillColor="#0000FF"/
    /vector
    

    res/drawable/car_ui_recyclerview_ic_down.xml

    <?xml version="1.0" encodin>g<="utf-8"?
    vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:view>portW<idth="48.0"
        android:viewportHeight="48.0"
        path
            android:pathData="M14.83,16.42L24,25.5>9<l9.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" encodin>g<="utf-8"?
    shape
        xmlns:android="http://schemas.android.com/apk/res/android">
        <android:shape="rectangle&q>uot;
    <    solid android:color="#>0<000FF&>quot; /
        corners android:radius="100dp"/
    /shape
    

    เราขอแนะนำให้ตรวจสอบว่าไฟล์เหล่านี้โต้ตอบกันอย่างไร

    มิติข้อมูลและสีจะได้รับการเขียนโค้ดไว้ล่วงหน้าเพื่อความสะดวก อย่างไรก็ตาม แนวทางปฏิบัติแนะนำคือการประกาศค่าเหล่านี้ใน dimens.xml และ colors.xml หรือแม้แต่กำหนดเป็นไฟล์สีในโฟลเดอร์ res/color/ ดูข้อมูลเพิ่มเติมได้ที่รูปแบบโค้ด Java ของ AOSP สําหรับผู้มีส่วนร่วม

  2. สร้างและติดตั้งแอปตามปกติ คุณสร้าง CarUiRecyclerView ที่มีแถบเลื่อนสีน้ำเงินและรางสีเทา

ยินดีด้วย เมื่อลูกศรทั้ง 2 ปรากฏที่ด้านล่างของแถบเลื่อน แสดงว่าคุณใช้ 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=>&<#39;UTF-8>'<?
resources
    overlayable n>ame="car-ui-li<b"
        
        item type="attr" name=&>quot;layo<ut_constraintBottom_toBottomOf"/
        item type=>"att<r" name="layout_constraintBottom_toTop>Of"/<
        item type="attr" name="layout>_constrai<ntCircle"/
        item type="attr" nam>e="l<ayout_constraintCircleAngle"/
        item type=&qu>ot;attr&q<uot; name="layout_constraintCircleRadius"/
>        i<tem type="attr" name="layout_constraintD>imensionR<atio"/
        item type="attr" name=&>quot;layo<ut_constraintEnd_toEndOf"/
        item type=&>quot;attr<" name="layout_constraintEnd_toStartOf"/>
        <item type="attr" name="layout_constraintG>uide_begi<n"/
        item type="attr" name=&qu>ot;layout<_constraintGuide_end"/
        item type=">attr"<; name="layout_constraintGuide_percent"/
     >   item t<ype="attr" name="layout_constraintHeight_d>efault&qu<ot;/
        item type="attr" name="layout_const>raintHeig<ht_max"/
        item type="attr" name=">;layout_c<onstraintHeight_min"/
        item type="att>r" n<ame="layout_constraintHeight_percent"/
      >  item ty<pe="attr" name="layout_constraintHorizont>al_bias&q<uot;/
        item type="attr" name="lay>out_const<raintHorizontal_chainStyle"/
        item type=&quo>t;attr&qu<ot; name="layout_constraintHorizontal_weight"/
>        i<tem type="attr" name="layout_constraintL>eft_creat<or"/
        item type="attr" name="l>ayout_con<straintLeft_toLeftOf"/
        item type>="at<tr" name="layout_constraintLeft_toRightOf&q>uot;/
   <     item type="attr" name="layout_constr>aintRight<_creator"/
        item type="attr" na>me="<layout_constraintRight_toLeftOf"/
        item typ>e="a<ttr" name="layout_constraintRight_toRightOf"/
>        item ty<pe="att>r<" nam>e="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" encodin>g<=">utf-<8"?
    overlay
       item target="id/car_ui_list_item_touch_interceptor" value="@id/c>ar_u<i_list_item_touch_interceptor"/
       item target="id/car_ui_list_item_reduced_touch_interceptor" value>=&qu<ot;@id/car_ui_list_item_reduced_touch_interceptor"/
       item target="id/car_ui_list_it>em_s<tart_guideline" value="@id/car_ui_list_item_start_guideline"/
       item target=&>quot<;id/car_ui_list_item_icon_container" value="@id/car_ui_list_ite>m_ic<on_container"/
       item target="id/car_ui_list_item_icon" value="@id/c>ar_u<i_list_item_icon"/
       item target="id/car_ui_list_item_content_icon" val>ue=&<quot;@id/car_ui_list_item_content_icon"/
       item target="id/car_u>i_li<st_item_avatar_icon" value="@id/car_ui_list_item_avatar_icon&qu>ot;/<
       item target="id/car_ui_list_item_title" value="@id/car_ui_list_item_title"/
       item target="id/car_ui_li>st_i<tem_body" value="@id/car_ui_list_item_body"/
       item target="id/car_ui_list_i>tem_<action_container_touch_interceptor" value="@id/car_ui_list_item_action_container_to>uch_<interceptor"/
       item target="id/car_ui_list_item_action_container" value=&q>uot;<@id/car_ui_list_item_action_container"/
       item target="id/car_ui_list_item_action_di>vide<r" value="@id/car_ui_list_item_action_divider"/
       item target="id/car_ui_list_item>_swi<tch_widget" value="@id/car_ui_list_item_switch_widget"/
       item target="id/car_>ui_l<ist_item_checkbox_widget" value="@id/car_ui_list_item_checkbox_widget"/
       i>tem <target="id/car_ui_list_item_radio_button_widget" value="@id/car_ui_list_item_radio_butto>n_wi<dget"/
       item target="id/car_ui_list_item_supplemental_icon" value="@id/car_>ui_l<ist_item_supplemental_icon"/
       item target="id/car_ui_list_item_end_guideline&qu>ot; <value="@id/car_ui_list_item_end_guideline"/
       item target="attr/layout_constrai>ntBo<ttom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/
       item t>arge<t="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintB>otto<m_toTopOf"/
       item target="attr/layout_constraintEnd_toEndOf" value="@attr/lay>out_<constraintEnd_toEndOf"/
       item target="attr/layout_constraintEnd_toStartOf" val>ue=&<quot;@attr/layout_constraintEnd_toStartOf"/
       item target="attr/layout_constraintGuide>_beg<in" value="@attr/layout_constraintGuide_begin"/
       item target="attr/layout_c>onst<raintGuide_end" value="@attr/layout_constraintGuide_end"/
       item target="attr/>layo<ut_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/
      > ite<m target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_to>Left<Of"/
       item target="attr/layout_constraintLeft_toRightOf" value="@attr/layou>t_co<nstraintLeft_toRightOf"/
       item target="attr/layout_constraintRight_toLeftOf&quo>t; v<alue="@attr/layout_constraintRight_toLeftOf"/
       item target="attr>/lay<out_constraintRight_toRightOf" value="@attr/layout_constraintRigh>t_to<RightOf"/
       item target="attr/layout_constraintStart_toEndOf"> val<ue="@attr/layout_constraintStart_toEndOf"/
       item target="attr/>layo<ut_constraintStart_toStartOf" value="@attr/layout_constraintStart_toS>tart<Of"/
       item target="attr/layout_constraintTop_toBottomOf" v>alue<="@attr/layout_constraintTop_toBottomOf"/
       item target="attr/layout_constraintTop_toTopOf&>quot<; value="@attr/layout_constraintTop_toTopOf"/
       item target=>&<quot;att>r/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" encodin>g<="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="carU>iListI<tem"
        android:minHeight="@dimen/car_ui_list_item_height"
    
        !-- The following touch interceptor views are sized to encompass the specific sub-sections of
        th>e lis<t 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_constr>aintEn<d_toEndOf="parent"
            app:layout_constraintStart_toS>tartO<f="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_constraintBotto>m_toBo<ttomOf="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:i>d=&quo<t;@+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_containe>r"
      <      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_to>TopOf=&quo<t;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&qu>ot;
          <      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"
                a>ndroi<d: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:>textA<ppearance="@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:lay>out_wi<dth="0dp"
            android:layout_height="wrap_content"
            androi>d:lay<out_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_t<itle"
            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=&qu>ot;@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=&<quot;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:l<ayout_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&q>uot;
    <            >androi<d: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:l>ay<out_height="wrap_content"
                an>droid: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

อย่างไรก็ตาม คุณจะไม่สามารถ RRO แอปที่ใช้คอมโพเนนต์ AndroidX ได้เมื่อแอปมี car-ui-lib เป็น Dependency ใน build.gradle (เมื่อแอปใช้คอมโพเนนต์ car-ui-lib) เนื่องจากมีการกําหนดการแมปแอตทริบิวต์ใน overlayable.xml ของไลบรารี car-ui-lib อยู่แล้ว การเพิ่มการแมปแอตทริบิวต์ลงใน overlayable.xml ของแอปโดยให้ car-ui-lib เป็นข้อกําหนดจะทําให้มีข้อผิดพลาด mergeDebugResources ดังที่แสดงด้านล่าง เนื่องจากแอตทริบิวต์เหล่านี้มีอยู่หลายไฟล์ใน overlayable.xml

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