ใช้car-ui-libไลบรารีเพื่อเปิดตัวระบบสาระบันเทิงในรถยนต์ (IVI) ที่สอดคล้องกันในตัวเอง Codelab นี้จะแนะนำให้คุณรู้จัก car-ui-lib และวิธีใช้
การซ้อนทับทรัพยากรที่รันไทม์ (RRO) เพื่อปรับแต่งคอมโพเนนต์ในไลบรารี
สิ่งที่คุณจะได้เรียนรู้
วิธีการ:
- ใส่
car-ui-libคอมโพเนนต์ในแอป Android - ใช้ Gradle เพื่อสร้างแอป Android และ RRO
- ใช้ RRO กับ
car-ui-lib
Codelab นี้ไม่ได้อธิบายรายละเอียดวิธีการทำงานของ RRO ดูข้อมูลเพิ่มเติมได้ที่ เปลี่ยนค่าของทรัพยากรของแอปขณะรันไทม์และ แก้ปัญหาการซ้อนทับทรัพยากรขณะรันไทม์
ก่อนจะเริ่มต้น
สิ่งที่ต้องมีก่อน
โปรดตรวจสอบว่าคุณมีสิ่งต่อไปนี้ก่อนเริ่มต้น
คอมพิวเตอร์ที่มีบรรทัดคำสั่ง (เครื่อง Linux, Mac หรือเครื่อง Windows ที่มี ระบบย่อย Windows สำหรับ Linux)
อุปกรณ์ Android หรือโปรแกรมจำลองที่เชื่อมต่อกับเครื่องของคุณ ดูดาวน์โหลดแหล่งที่มาของ Android และสร้าง Android
ความรู้พื้นฐานเกี่ยวกับ RRO
สร้างแอป Android ใหม่
ระยะเวลา: 15 นาที
ในส่วนนี้ คุณจะสร้างโปรเจ็กต์ Android Studio ใหม่
สร้างแอปที่มี
EmptyActivityใน Android Studio
รูปที่ 1สร้างกิจกรรมว่าง ตั้งชื่อแอป
CarUiCodelabแล้วเลือกภาษา Java นอกจากนี้ คุณยังเลือกตำแหน่งไฟล์ได้หากต้องการ ยอมรับค่าเริ่มต้นสำหรับการตั้งค่าที่เหลือ
รูปที่ 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>บล็อกโค้ดนี้แสดงสตริง
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>หากต้องการสร้างแอป ให้คลิกปุ่ม Play สีเขียวที่ด้านขวาบน การทำเช่นนี้จะ ติดตั้ง APK ในโปรแกรมจำลองหรืออุปกรณ์ Android ผ่าน Gradle โดยอัตโนมัติ
แอปใหม่ควรเปิดขึ้นโดยอัตโนมัติในโปรแกรมจำลองหรืออุปกรณ์ Android หากไม่พบ ให้เปิดแอป CarUiCodelab จากตัวเปิดแอปที่ติดตั้งไว้
โดยจะปรากฏดังนี้
เพิ่ม car-ui-lib ลงในแอป Android
ระยะเวลา: 15 นาที
เพิ่ม car-ui-lib ลงในแอปโดยทำดังนี้
หากต้องการเพิ่มทรัพยากร Dependency
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ให้เลือก app > src > main > AndroidManifest.xml แล้วอัปเดตAndroidManifest.xmlให้ปรากฏดังนี้<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.caruicodelab"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.CarUi.WithToolbar" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>หากต้องการสร้างแอป ให้กดปุ่มเล่นสีเขียวเหมือนเดิม
เพิ่ม 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!" เป็น "Hello World RRO"
หากต้องการสร้างโปรเจ็กต์ใหม่ ให้เลือกไฟล์ > ใหม่ > โปรเจ็กต์ใหม่ โปรดเลือกไม่มีกิจกรรมแทนที่จะเลือกกิจกรรมว่าง เนื่องจากแพ็กเกจ RRO มีเฉพาะทรัพยากร
การกำหนดค่าของคุณจะปรากฏคล้ายกับการกำหนดค่าที่แสดงด้านล่าง โดยตำแหน่งที่บันทึกอาจแตกต่างกันดังนี้
หลังจากสร้าง
CarUiRROโปรเจ็กต์AndroidManifest.xmlใหม่แล้ว ให้ประกาศโปรเจ็กต์เป็น 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_overlayresourcesMapไฟล์จะแมปชื่อทรัพยากรจากแพ็กเกจเป้าหมายไปยังแพ็กเกจ RRO ต้องตั้งค่าสถานะhasCodeเป็นfalseสำหรับแพ็กเกจ RRO นอกจากนี้ แพ็กเกจ RRO ต้องไม่มีไฟล์ DEXคัดลอกบล็อกโค้ดต่อไปนี้ลงใน
…/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 คุณอาจต้องใช้แฟล็ก --no-resource-deduping และ --no-resource-removal ของ Android Asset Packaging Tool (AAPT2)
ที่อธิบายไว้ใน
ตัวเลือกการลิงก์
คุณไม่จำเป็นต้องเพิ่ม Flag ใน Codelab นี้ แต่เราขอแนะนำให้ใช้ Flag เหล่านี้ใน 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 ตัวอย่างเช่น เมื่อสร้างการวางซ้อนสำหรับเป้าหมาย 2 รายการที่แตกต่างกัน คุณต้อง สร้าง APK การวางซ้อน 2 รายการ
สร้าง ยืนยัน ติดตั้ง และเปิดใช้ 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 ในลักษณะเดียวกับก่อนหน้า (ปุ่ม Play สีเขียว) อย่าลืมเปิดใช้ RRO
แอปและ RRO จะแสดงผลดังนี้ ข้อความ RRO ของ Hello World เป็นสีเขียวและอยู่ตรงกลางตามที่ระบุไว้ใน RRO ของเลย์เอาต์
เพิ่ม CarUiRecyclerView ลงในแอป
ระยะเวลา: 15 นาที
อินเทอร์เฟซ CarUiRecyclerView มี API สำหรับเข้าถึง RecyclerView
ที่ปรับแต่งผ่านทรัพยากร car-ui-lib เช่น CarUiRecyclerView
ตรวจสอบ Flag ที่รันไทม์เพื่อพิจารณาว่าควรเปิดใช้แถบเลื่อนหรือไม่
และเลือกเลย์เอาต์ที่เกี่ยวข้อง
หากต้องการเพิ่ม
CarUiRecyclerViewให้เพิ่มลงในไฟล์activity_main.xmlและMainActivity.javaคุณจะสร้างแอปใหม่ตั้งแต่ต้นหรือ แก้ไขแอปที่มีอยู่ก็ได้ หากแก้ไขแอปที่มีอยู่ โปรดนำ ทรัพยากรที่ไม่ได้ประกาศออกจากoverlayable.xmlactivity_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.javapackage 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จะแสดงหรือไม่ เมื่อตั้งค่าเป็นfalseCarUiRecyclerViewจะทําหน้าที่เหมือนRecyclerViewของ AndroidXres/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>หากต้องการซ้อนทับไฟล์เลย์เอาต์ คุณต้องเพิ่มแอตทริบิวต์รหัสและเนมสเปซทั้งหมดลงใน
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/ดูข้อมูลเพิ่มเติมได้ที่ รูปแบบโค้ด Java ของ AOSP สำหรับผู้ร่วมให้ข้อมูลสร้างและติดตั้งแอปตามปกติ คุณสร้าง
CarUiRecyclerViewด้วยแถบเลื่อนสีน้ำเงินและรางสีเทา
ยินดีด้วย ลูกศรทั้ง 2 ตัวจะปรากฏที่ด้านล่างของแถบเลื่อน ซึ่งหมายความว่าคุณได้ใช้ RRO กับไฟล์ทรัพยากรเลย์เอาต์ car-ui-lib โดยใช้ระบบบิลด์ Gradle ผ่าน 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เพิ่มหรือแก้ไขไฟล์ต่อไปนี้ใน RROres/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อ้างอิงคอมโพเนนต์หลายรายการ/ ทรัพยากรที่ไม่ได้รวมไว้เป็นทรัพยากร Dependency ของแอป ซึ่งเป็น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) เนื่องจากมีการกำหนดการแมปแอตทริบิวต์ไว้แล้วใน car-ui-lib ของไลบรารี overlayable.xml การเพิ่มแอตทริบิวต์เหล่านั้นลงใน overlayable.xml ของแอปโดยมี car-ui-lib เป็นทรัพยากร Dependency จะทำให้เกิดข้อผิดพลาด mergeDebugResources ดังที่แสดงด้านล่าง เนื่องจากแอตทริบิวต์เหล่านี้
อยู่ในไฟล์ overlayable.xml หลายไฟล์
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'