使用 car-ui-lib
程式庫推出自我一致性、車內和資訊娛樂系統
(IVI) 系統發生這類錯誤。本程式碼研究室將介紹 car-ui-lib
,並說明如何
使用執行階段資源疊加層 (RRO) 自訂程式庫中的元件。
課程內容
教學示範
- 在 Android 應用程式中加入
car-ui-lib
元件。 - 使用 Gradle 建構 Android 應用程式和 RRO。
- 將 RRO 與
car-ui-lib
搭配使用。
本程式碼研究室不會詳細說明 RRO 的運作方式。詳情請見 在執行階段變更應用程式資源的值,並 執行階段資源重疊疑難排解 。
事前準備
必要條件
開始之前,請先確認你已備妥:
裝有指令列的電腦 (搭載 Linux 的電腦、Mac 或 Windows 電腦,以及 Windows 子系統 (Linux 適用)。
已連接至電腦的 Android 裝置或模擬器。詳情請見 下載 Android 原始碼並 建構 Android。
RRO 的基本知識。
建立新的 Android 應用程式
時間長度:15 分鐘
在本節中,您將建立新的 Android Studio 專案。
在 Android Studio 中,使用
EmptyActivity
建立應用程式。圖 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 >主要 >解析度 > 值 >string.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
應用程式。
看起來會像這樣:
![開啟新的 CarUiCodelab 應用程式](https://source.android.com/static/docs/automotive/images/codelab_04.png?hl=zh-tw)
在 Android 應用程式中新增 car-ui-lib
時間長度:15 分鐘
將 car-ui-lib
新增至應用程式:
如要在專案的
build.gradle
檔案中新增car-ui-lib
依附元件, 選取 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' }
在 Android 應用程式中使用 car-ui-lib 元件
現在您已擁有 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>
如要建構應用程式,像先前一樣按下綠色的「Play」按鈕。
在應用程式中新增 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」
如要建立新專案,請依序選取「File」(檔案) >「新增 >新專案。請務必 由於 RRO 套件包含下列項目,因此請選取「No Activity」而非「Empty Activity」 只有資源
您的設定看起來與下圖類似。 儲存位置可能有所不同:
建立新的
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 目標,請按下綠色的「Play」按鈕建立 Gradle 您必須在模擬器或 Android 裝置上建立 RRO 版本。
如要確認 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」字串。
![World RRO,你好!](https://source.android.com/static/docs/automotive/images/codelab_09.png?hl=zh-tw)
恭喜!你已建立第一個 RRO,
使用 RRO 時,建議您使用 Android 資產封裝工具 (AAPT2)
標記 --no-resource-deduping
和 --no-resource-removal
「連結選項」。
您不需要在本程式碼研究室中新增標記,但建議您使用標記
,以免系統移除資源及偵錯。個人中心
可以將這些內容新增到 RRO 的 build.gradle
檔案,如下所示:
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
在 Android 應用程式中使用 RRO 修改 car-ui-lib
元件
本頁面說明如何使用執行階段資源重疊 (RRO) 來
在 Android 應用程式中修改 car-ui-lib
程式庫中的元件。
設定工具列背景顏色
時間長度: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
中,更新targetName
使其指向car-ui-lib
:… android:targetName="car-ui-lib" …
您必須為每個要 RRO 的目標套件建立新的 RRO 套件。 例如,建立兩個不同目標的疊加層時, 建立兩個重疊 APK
以先前的方式建構、驗證、安裝及啟用 RRO。
應用程式看起來會像這樣:
![新工具列背景顏色](https://source.android.com/static/docs/automotive/images/codelab_10.png?hl=zh-tw)
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>
將
AndroidManifest.xml
中的targetName
變更為指向名稱 新的應用程式:… android:targetName="CarUiCodelab" …
將資源新增至 RRO 中的
sample_overlay.xml
檔案:<?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 的算繪方式如下。Hello World RRO 文字是綠色, 置中顯示。
![Hello World RRO](https://source.android.com/static/docs/automotive/images/codelab_11.png?hl=zh-tw)
將 CarUiRecyclerView 新增至應用程式
時間長度:15 分鐘
CarUiRecyclerView
介面提供用於存取 RecyclerView
的 API
透過 car-ui-lib
資源自訂執行個體例如:CarUiRecyclerView
在執行階段檢查旗標,判斷是否應啟用捲軸
然後選取對應的版面配置
![CarUiRecyclerViewContainer](https://source.android.com/static/docs/automotive/images/codelab_12.png?hl=zh-tw)
如要新增
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
:
![CarUiRecyclerView](https://source.android.com/static/docs/automotive/images/codelab_13.png?hl=zh-tw)
使用 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](https://source.android.com/static/docs/automotive/images/codelab_14.png?hl=zh-tw)
使用版面配置疊加 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 和命名空間 設為 RRO 的
overlay.xml
。請參閱下方檔案。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/
資料夾內指定為顏色檔案如要瞭解詳情 看 貢獻者的 Android 開放原始碼計畫 Java 程式碼樣式。照常建構並安裝應用程式。
CarUiRecyclerView
已建造 具有藍色捲軸和灰色欄桿
恭喜!這兩個箭頭都會顯示在捲軸的底部
已成功使用 Gradle 版本將 RRO 套用至 car-ui-lib
版面配置資源檔案
建構應用程式
![CarUiRecyclerView,有藍色捲軸和灰色邊欄](https://source.android.com/static/docs/automotive/images/codelab_15.png?hl=zh-tw)
RRO 清單項目
時間長度:15 分鐘
此時,您已使用架構將 RRO 套用至 car-ui-lib
元件
(非 AndroidX)。如要在 RRO 中使用 AndroidX 元件,您必須新增
該元件對應用程式和 RRO 的依附元件 build.gradle.
您
也必須在應用程式內將該元件的 attrs
新增至 overlayable.xml
做為 RRO 中的 sample_overlay.xml
。
我們的程式庫 (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
新增為 以下依附元件在app/build.gradle
中對 RRO 應用程式有依附元件: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' }
標題和內文現在靠右對齊,而不是靠左對齊。
![靠右對齊標題和內文](https://source.android.com/static/docs/automotive/images/codelab_16.png?hl=zh-tw)
我們只使用 AndroidX 元件將 RRO 套用至 car-ui-lib
(ConstraintLayout
) 屬性出現在 car-ui-lib
中時
檔案名稱為 overlayable.xml
和 RRO sample_overlay.xml
。是
讓您在自己的應用程式中得到類似效果您只要將
與應用程式的 overlayable.xml
設為 attrs
,與 car-ui-lib
類似。
不過,當應用程式採用 AndroidX 元件時,「無法」使用 AndroidX 元件執行 RRO 操作。
應用程式的 car-ui-lib
有依附元件build.gradle
(如果應用程式使用
car-ui-lib
元件)。由於屬性對應已定義於
將 car-ui-lib
程式庫的 overlayable.xml
新增至
如果應用程式的 overlayable.xml
使用 car-ui-lib
做為依附元件,會導致
類似下方的 mergeDebugResources
錯誤。這是因為這些屬性
出現在多個 overlayable.xml
檔案中:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'