ใช้ไลบรารี 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 ใหม่
ใน Android Studio ให้สร้างแอปด้วย
EmptyActivity
ตั้งชื่อแอป
CarUiCodelab
จากนั้นเลือกภาษา Java คุณยังสามารถเลือกตำแหน่งไฟล์ได้หากต้องการ ยอมรับค่าเริ่มต้นสำหรับการตั้งค่าที่เหลือแทนที่
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
ซึ่งไม่ได้กำหนดไว้เพิ่มสตริงทรัพยากร
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>
หากต้องการสร้างแอปของคุณ ให้คลิกปุ่ม เล่น สีเขียวที่มุมขวาบน การทำเช่นนั้นจะติดตั้ง APK ลงในโปรแกรมจำลองหรืออุปกรณ์ Android ของคุณโดยอัตโนมัติผ่าน Gradle
แอปใหม่ควรเปิดโดยอัตโนมัติบนอุปกรณ์จำลองหรืออุปกรณ์ Android ของคุณ หากไม่เป็นเช่นนั้น ให้เปิดแอป CarUiCodelab
จากตัวเรียกใช้งานแอปซึ่งติดตั้งไว้แล้ว ปรากฏดังนี้:
เพิ่ม car-ui-lib ลงในแอป Android ของคุณ
ระยะเวลา: 15 นาที
เพิ่ม car-ui-lib
ให้กับแอปของคุณ:
หากต้องการเพิ่มการพึ่งพา
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
แล้ว ให้เพิ่มแถบเครื่องมือลงในแอปของคุณ
ในไฟล์
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); }
อย่าลืมนำเข้า
ToolbarController
:import com.android.car.ui.core.CarUi; import com.android.car.ui.toolbar.ToolbarController;
หากต้องการใช้ธีม
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>
หากต้องการสร้างแอป ให้กดปุ่ม เล่น สีเขียวเหมือนเมื่อก่อน
เพิ่ม RRO ลงในแอปของคุณ
ระยะเวลา: 30 นาที
หากคุณคุ้นเคยกับ RRO ให้ไปที่ส่วนถัดไป เพิ่มตัวควบคุมสิทธิ์ให้กับแอปของคุณ หรือหากต้องการเรียนรู้พื้นฐานของ RRO โปรดดูที่ การเปลี่ยนแปลงมูลค่าของทรัพยากรของแอป ณ รันไทม์
เพิ่มตัวควบคุมสิทธิ์ให้กับแอปของคุณ
หากต้องการควบคุมทรัพยากรที่ซ้อนทับแพ็คเกจ RRO ให้เพิ่มไฟล์ชื่อ overlayable.xml
ลงในโฟลเดอร์ /res
ของแอปของคุณ ไฟล์นี้ทำหน้าที่เป็นตัวควบคุมสิทธิ์ระหว่างแอปของคุณ ( เป้าหมาย ) และแพ็คเกจ RRO ของคุณ ( โอเวอร์เลย์ )
เพิ่ม
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"
หากต้องการสร้างโปรเจ็กต์ใหม่ ให้เลือก ไฟล์ > ใหม่ > โปรเจ็กต์ใหม่ อย่าลืมเลือก No Activity แทน Empty Activity เนื่องจากแพ็คเกจ RRO มีเฉพาะทรัพยากรเท่านั้น
การกำหนดค่าของคุณปรากฏคล้ายกับที่แสดงด้านล่าง ตำแหน่งที่บันทึกไว้อาจแตกต่างกัน:
หลังจากที่คุณสร้างโปรเจ็กต์
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คัดลอกบล็อกโค้ดต่อไปนี้ลงใน
…/res/xml/sample_overlay.xml
:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> </overlay>
เพิ่ม
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>
หากต้องการสร้างเป้าหมาย RRO ให้กดปุ่ม เล่น สีเขียวเพื่อสร้าง Gradle build ของ RRO ของคุณบนเครื่องจำลองหรืออุปกรณ์ Android
หากต้องการตรวจสอบว่า 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 ของคุณมีข้อผิดพลาด โปรดดู ที่ แก้ไขปัญหาการซ้อนทับทรัพยากรรันไทม์ ก่อนที่จะดำเนินการต่อ
-
หากต้องการเปิดใช้งาน 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 แรกของคุณแล้ว
เมื่อใช้ 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 นาที
หากต้องการเปลี่ยนสีพื้นหลังของแถบเครื่องมือ:
เพิ่มค่าต่อไปนี้ให้กับแอป 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 แถบเครื่องมือจะไม่เปลี่ยนแปลงเนื่องจากมีการกำหนดเป้าหมายค่าที่ไม่ถูกต้องใน
AndroidManifest.xml
สำหรับ RRO ของคุณ ให้อัปเดตtargetName
ให้ชี้ไปที่car-ui-lib
:… android:targetName="car-ui-lib" …
คุณต้องสร้างแพ็คเกจ RRO ใหม่สำหรับแต่ละแพ็คเกจเป้าหมายที่คุณต้องการ RRO ตัวอย่างเช่น เมื่อสร้างโอเวอร์เลย์สำหรับสองเป้าหมายที่แตกต่างกัน คุณต้องสร้าง apk โอเวอร์เลย์สองอัน
สร้าง ตรวจสอบ ติดตั้ง และเปิดใช้งาน RRO ในลักษณะเดียวกับเมื่อก่อน
แอปของคุณปรากฏดังนี้:
เค้าโครงและสไตล์ RRO
ระยะเวลา: 15 นาที
ในแบบฝึกหัดนี้ คุณสร้างแอปใหม่ที่คล้ายกับแอปที่คุณสร้างไว้ก่อนหน้านี้ แอพนี้อนุญาตให้วางเลย์เอาต์ได้ ทำตามขั้นตอนเดิมหรือแก้ไขแอปที่มีอยู่
ตรวจสอบให้แน่ใจว่าคุณเพิ่มบรรทัดต่อไปนี้ใน
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>
ตรวจสอบให้แน่ใจว่า
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>
ในแอป 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>
อัปเดต
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>
เปลี่ยน
targetName
ในAndroidManifest.xml
ให้ชี้ไปที่ชื่อแอปใหม่ของคุณ:… android:targetName="CarUiCodelab" …
เพิ่มทรัพยากรลงในไฟล์
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>
สร้างและติดตั้งแอปและ RRO ในลักษณะเดียวกับเมื่อก่อน (ปุ่ม เล่น สีเขียว) อย่าลืมเปิดใช้งาน RRO ของคุณ
แอปและ RRO แสดงผลดังนี้ ข้อความ Hello World RRO เป็นสีเขียวและอยู่กึ่งกลางตามที่ระบุไว้ในเค้าโครง RRO
เพิ่ม CarUiRecyclerView ลงในแอปของคุณ
ระยะเวลา: 15 นาที
อินเทอร์เฟซ CarUiRecyclerView
มี API เพื่อเข้าถึง RecyclerView
ที่ปรับแต่งผ่านทรัพยากร car-ui-lib
ตัวอย่างเช่น CarUiRecyclerView
จะตรวจสอบแฟล็ก ณ รันไทม์เพื่อพิจารณาว่าควรเปิดใช้งานแถบเลื่อนหรือไม่ และเลือกเค้าโครงที่เกี่ยวข้อง
หากต้องการเพิ่ม
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; }
สร้างและติดตั้งแอปของคุณเหมือนเมื่อก่อน
ตอนนี้คุณเห็น CarUiRecyclerView
:
ใช้ RRO เพื่อลบแถบเลื่อน
ระยะเวลา: 10 นาที
แบบฝึกหัดนี้จะแสดงให้คุณเห็นถึงวิธีการใช้ RRO เพื่อลบแถบเลื่อนออกจาก CarUiRecyclerView
ใน 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
จะทำหน้าที่เหมือนกับ AndroidXRecyclerView
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
ระยะเวลา: 15 นาที
ในแบบฝึกหัดนี้ คุณจะปรับเปลี่ยนเค้าโครงแถบเลื่อน CarUiRecyclerView
เพิ่มและแก้ไขไฟล์ต่อไปนี้ในแอป 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 สำหรับผู้มีส่วนร่วมสร้างและติดตั้งแอปของคุณเหมือนเมื่อก่อน คุณได้สร้าง
CarUiRecyclerView
ด้วยแถบเลื่อนสีน้ำเงินและรางสีเทา
ยินดีด้วย! ลูกศรทั้งสองปรากฏขึ้นที่ด้านล่างของแถบเลื่อน คุณใช้ RRO กับไฟล์ทรัพยากรเลย์เอาต์ car-ui-lib
ได้สำเร็จโดยใช้ระบบ Gradle build ผ่าน Android Studio
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>
เปลี่ยนเค้าโครงของรายการใน
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>
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' }
ตอนนี้ชื่อเรื่องและเนื้อหาถูกจัดชิดขวาแทนที่จะจัดชิดซ้าย
เราใช้ 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'