car-ui-lib
ライブラリを使用して、自己完結型の車載インフォテインメント(IVI)システムを起動します。この Codelab では car-ui-lib
とランタイム リソース オーバーレイ(RRO)を使用してライブラリのコンポーネントをカスタマイズする方法を紹介します。
学習内容
次のことを行う方法を学習します。
- Android アプリに
car-ui-lib
コンポーネントを含める。 - Gradle を使用して Android アプリと RRO を構築する。
car-ui-lib
で RRO を使用する。
この Codelab では RRO の仕組みの詳細は説明しません。詳しくは、実行時にアプリのリソースの値を変更する、ランタイム リソース オーバーレイのトラブルシューティングをご覧ください。
準備
前提条件
開始前に以下の準備が整っていることを確認します。
コマンドラインを使用できるパソコン(Linux マシン、Linux 用 Windows サブシステムを使用できる Mac または Windows マシン)。
マシンに接続されている Android デバイスまたはエミュレータ。Android ソースのダウンロード、Android のビルドをご覧ください。
RRO に関する基礎知識。
新しい Android アプリを作成する
所要時間: 15 分
このセクションでは、新しい Android Studio プロジェクトを作成します。
Android Studio で
EmptyActivity
のアプリを作成します。図 1. Empty Activity を作成する アプリに
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
を表示します。これは定義されていません。strings.xml
ファイルにリソース文字列sample_text
を追加して、「Hello World!」に設定します。このファイルを開くには、[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] ボタンをクリックします。クリックすると自動的に Gradle 経由で APK がエミュレータまたは Android デバイスにインストールされます。
エミュレータまたは Android デバイスで、新しいアプリが自動的に開きます。開かない場合は、アプリ ランチャーから CarUiCodelab
アプリを開きます。この時点でこのアプリはインストールされています。次のような画面が開きます。
![新しい CarUiCodelab アプリを開く](https://source.android.com/static/docs/automotive/images/codelab_04.png?hl=ja)
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' }
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
テーマを使用するには、[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>
アプリをビルドするには、先ほどと同様に緑の [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] > [New] > [New Project] を選択します。RRO パッケージにはリソースのみが含まれるため、必ず Empty Activity ではなく、No Activity を選択してください。
設定は以下に示すものと同様になります。保存される場所は異なる場合があります。
新しい
CarUiRRO
プロジェクトを作成後に、AndroidManifest.xml
を修正してプロジェクトを RRO として宣言します。<?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>
…/res/values/strings.xml
にsample_text
を追加します。<?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] ボタンを押して、エミュレータまたは Android デバイスで RRO の Gradle ビルドを作成します。
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」が表示されます。
![Hello World RRO!](https://source.android.com/static/docs/automotive/images/codelab_09.png?hl=ja)
お疲れさまでした。これで最初の RRO が作成されました。
RRO を使用する際には、リンク オプションに記載の Android Asset Packaging Tool(AAPT2)フラグの --no-resource-deduping
と --no-resource-removal
を使用することもできます。この Codelab でフラグを追加することは必須ではありませんが、ご自身の RRO ではそれを使用して、リソースの削除(およびデバッグの手間)が発生しないようにします。次のように RRO の build.gradle
ファイルに追加できます。
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
これらのフラグの詳細については、パッケージのビルドと AAPT2 をご覧ください。
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 の設定に含まれる場合、誤った値がターゲットとなるため、ツールバーは変更されません。RRO の
AndroidManifest.xml
で、targetName
がcar-ui-lib
を指すように更新します。… android:targetName="car-ui-lib" …
RRO の対象とする各ターゲット パッケージに対して新しい RRO パッケージを作成する必要があります。たとえば、2 つの異なるターゲットに対してオーバーレイを作成する場合、2 つのオーバーレイ APK を作成する必要があります。
先ほどと同じ方法で、RRO のビルド、検証、インストール、有効化を行います。
アプリは次のように表示されます。
![ツールバーの新しい背景色](https://source.android.com/static/docs/automotive/images/codelab_10.png?hl=ja)
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 は次のようにレンダリングされます。レイアウト RRO で指定されているとおり、「Hello World RRO」のテキストは緑色で中心に配置されています。
![Hello World RRO](https://source.android.com/static/docs/automotive/images/codelab_11.png?hl=ja)
CarUiRecyclerView をアプリに追加する
所要時間: 15 分
CarUiRecyclerView
インターフェースは car-ui-lib
リソース経由でカスタマイズされる RecyclerView
にアクセスできる API を提供します。たとえば、CarUiRecyclerView
は実行時にフラグを確認して、スクロールバーを有効にすべきかどうかを判断し、対応するレイアウトを選択します。
![CarUiRecyclerViewContainer](https://source.android.com/static/docs/automotive/images/codelab_12.png?hl=ja)
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 のビルドとコンパイルはできます。エラーを削除するには、[File] > [Invalidate Caches] を選択して、[Invalidate and Restart.] をクリックします。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=ja)
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=ja)
レイアウトを使用して 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/
フォルダで色ファイルとして指定することをおすすめします。詳しくは、コントリビューター向け AOSP Java コードスタイルをご覧ください。アプリをこれまでと同じようにビルドしてインストールします。青のスクロールバーとグレーのレールの
CarUiRecyclerView
がビルドされます。
お疲れさまでした。スクロールバーの下に上下の矢印が表示されます。Android Studio から Gradle ビルドシステムを使用して、正常に RRO を car-ui-lib
レイアウト リソース ファイルに適用できました。
![青のスクロールバーとグレーのレールの CarUiRecyclerView](https://source.android.com/static/docs/automotive/images/codelab_15.png?hl=ja)
RRO リストアイテム
所要時間: 15 分
この時点で、AndroidX ではなくフレームワーク コンポーネントを使用して、RRO を car-ui-lib
コンポーネントに適用しました。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>
ConstraintLayout
を使用してCarUiRecyclerView
のリストアイテムのレイアウトを変更します以下のファイルを 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=ja)
属性が overlayable.xml
という名前の car-ui-lib
ファイルと RRO sample_overlay.xml
に存在している場合、AndroidX コンポーネント(ConstraintLayout
)を使用して、RRO を car-ui-lib
にのみ適用しました。自分のアプリで同様の対応をすることは可能です。car-ui-lib
と同様に、すべての該当する attrs
をアプリの overlayable.xml
に追加します。
ただし、アプリの build.gradle
に car-ui-lib
が依存関係として存在する場合(アプリが car-ui-lib
コンポーネントを使用する場合)、AndroidX コンポーネントを使用して、アプリを RRO することはできません。属性マッピングは car-ui-lib
ライブラリの overlayable.xml
ですでに定義されているため、それをアプリの overlayable.xml
に car-ui-lib
を依存関係として追加すると、次のような mergeDebugResources
エラーが発生する場合があります。これらの属性が複数の overlayable.xml
ファイルに存在するためです。
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'