Codelab: สร้าง RRO ด้วยส่วนประกอบ car-ui-lib โดยใช้ระบบ Gradle build

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

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

วิธี:

  • รวมส่วนประกอบ car-ui-lib ไว้ในแอป Android ของคุณ
  • ใช้ Gradle เพื่อสร้างแอป Android และ RRO
  • ใช้ RRO กับ car-ui-lib

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

ก่อนคุณเริ่ม

ข้อกำหนดเบื้องต้น

ก่อนที่คุณจะเริ่มต้น ตรวจสอบให้แน่ใจว่าคุณมี:

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

  • แอนดรอยด์สตูดิโอ

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

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

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

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

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

  1. ใน Android Studio ให้สร้างแอปด้วย EmptyActivity

    สร้างกิจกรรมที่ว่างเปล่า
    รูปที่ 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" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiCodelab</string>
        <string name="sample_text">Hello World!</string>
    </resources>
    
  5. หากต้องการสร้างแอปของคุณ ให้คลิกปุ่ม เล่น สีเขียวที่มุมขวาบน การทำเช่นนั้นจะติดตั้ง APK ลงในโปรแกรมจำลองหรืออุปกรณ์ Android ของคุณโดยอัตโนมัติผ่าน Gradle

    ปุ่มเล่น

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

เปิดแอป CarUiCodelab ใหม่
รูปที่ 3 เปิดแอป CarUiCodelab ใหม่

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

ระยะเวลา: 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 ในแอป 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 ให้เลือก แอป > 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. หากต้องการสร้างแอป ให้กดปุ่ม เล่น สีเขียวเหมือนเมื่อก่อน

    สร้างแอป

เพิ่ม 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!" ถึง "สวัสดีชาวโลก RRO"

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

    การกำหนดค่าของคุณปรากฏคล้ายกับที่แสดงด้านล่าง ตำแหน่งที่บันทึกไว้อาจแตกต่างกัน:

  2. หลังจากที่คุณสร้างโปรเจ็กต์ CarUiRRO ใหม่แล้ว ให้ประกาศโปรเจ็กต์เป็น 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="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 build ของ RRO
  5. หากต้องการสร้างเป้าหมาย RRO ให้กดปุ่ม เล่น สีเขียวเพื่อสร้าง 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 : สวัสดีชาวโลก RRO!

ยินดีด้วย! คุณได้สร้าง RRO แรกของคุณแล้ว

เมื่อใช้ RRO คุณอาจต้องการใช้แฟล็ก Android Asset Packaging Tool (AAPT2) --no-resource-deduping และ --no-resource-removal ที่อธิบายไว้ใน ตัวเลือกลิงก์ ไม่จำเป็นต้องเพิ่มแฟล็กใน Codelab นี้ แต่เราขอแนะนำให้คุณใช้แฟล็กใน RRO ของคุณเพื่อหลีกเลี่ยงการนำทรัพยากรออก (และการแก้ไขข้อบกพร่องที่ปวดหัว) คุณสามารถเพิ่มลงในไฟล์ build.gradle ของ RRO ได้ดังนี้:

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

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

แก้ไขส่วนประกอบ car-ui-lib โดยใช้ RRO ในแอป Android ของคุณ

หน้านี้อธิบายวิธีที่คุณสามารถใช้รันไทม์รีซอร์สโอเวอร์เลย์ (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. อัปเดต res/values/styles.xml เพื่อเพิ่มสไตล์ของเราให้กับ RRO:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
            <item name="android:textColor">#0f0</item>
            <item name="android:textSize">100sp</item>
        </style>
    </resources>
    
  5. เปลี่ยน 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 : สวัสดีชาวโลก 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 ของคุณได้ หากต้องการลบข้อผิดพลาด ให้เลือก ไฟล์ > ทำให้แคชใช้ไม่ได้ จากนั้นคลิก ทำให้ใช้ไม่ได้และรีสตาร์ท

    เพิ่มสิ่งต่อไปนี้ใน 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>
    

    หากต้องการซ้อนทับไฟล์เลย์เอาต์ คุณต้องเพิ่ม ID และแอตทริบิวต์เนมสเปซ ทั้งหมด ลงใน 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 Java สำหรับผู้มีส่วนร่วม

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

ยินดีด้วย! ลูกศรทั้งสองปรากฏขึ้นที่ด้านล่างของแถบเลื่อน คุณใช้ RRO กับไฟล์ทรัพยากรเลย์เอาต์ car-ui-lib ได้สำเร็จโดยใช้ระบบ Gradle build ผ่าน 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

อย่างไรก็ตาม เป็นไป ไม่ ได้ที่จะ RRO แอปที่ใช้ส่วนประกอบ AndroidX เมื่อแอปมี car-ui-lib เป็นการพึ่งพาใน 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'