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" encodin>g<="ut>f-8&q<uot;? resources st>ring name=&q<uot;app>_name<"CarUiCodelab/string> string <name=&q>u<ot;sample_>text"Hello World!/string /resourcesアプリをビルドするために、右上にある緑の [Play] ボタンをクリックします。クリックすると自動的に Gradle 経由で APK がエミュレータまたは Android デバイスにインストールされます。
エミュレータまたは Android デバイスで、新しいアプリが自動的に開きます。開かない場合は、アプリ ランチャーから CarUiCodelab アプリを開きます。この時点でこのアプリはインストールされています。次のような画面が開きます。
car-ui-lib を Android アプリに追加する
所要時間: 15 分
car-ui-lib をアプリに追加します。
car-ui-lib依存関係をプロジェクトのbuild.gradleファイルに追加するには、[app] > [build.gradle] を選択します。依存関係は次のように表示されます。dependencies { implementation 'com.android.car.ui:car-ui-lib:2.0.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' }
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" encodin>g<="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:s<upportsRtl="true" android:theme="@style/Theme.CarUi.WithToolba>r" < tools:targ>etApi="31&qu<ot; activity android:name=&quo>t;.MainActivity&qu<ot; android:exported="true" > intent-fi<lter > ac<tion andr>oid:n<ame="an>dr<oid.inten>t.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" encodin>g<="ut>f-8&q<uot;? resources overlayable> name=&qu<ot;CarUiCodelab">; pol<icy type="public" > item ty<pe=&quo>t;str<ing" na>m<e="sa>mple_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" encodin>g<="utf-8"? manifest xmlns:android="http://schemas.android.com/apk/res/android" >packag<e="com.example.caruirro" > app<lication android:hasCode="false" / uses-sdk android:minSdkV>ersion<="29" android:targetSdkVersion="29"/ overlay android:targetPackage="com.example.caruicodelab" android:targetName="CarUiCodelab" > < andro>id:isStatic="false" android:resourcesMap="@xml/sample_overlay" / /manifestそうすることにより
@xml/sample_overlayでエラーが作成されます。resourcesMapファイルはリソース名をターゲット パッケージから RRO パッケージにマッピングします。 RRO パッケージでは、フラグhasCodeを必ずfalseに設定する必要があります。 また、RRO パッケージに DEX ファイルを含めることはできません。以下のコードのブロックを
…/res/xml/sample_overlay.xmlにコピーします。<?xml version="1.0" encodin>g<=">utf-8<"? overlay item target="string/sample_text">;< value=&>quot;@string/sample_text"/ /overlay…/res/values/strings.xmlにsample_textを追加します。<?xml version="1.0" encodin>g<="ut>f-8&q<uot;? resources st>ring nam<e=">;app_<name"CarUiRRO/string> string nam<e=">;<sample_tex>t"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」が表示されます。
お疲れさまでした。これで最初の 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" encodin>g<="ut>f-8&q<uot;? resources drawable name="c>ar_u<i_toolbar>_<background>"#0F0/drawable /resourcescar-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 のビルド、検証、インストール、有効化を行います。
アプリは次のように表示されます。
RRO レイアウトとスタイル
所要時間: 15 分
この演習では、先ほどビルドしたアプリと同様の新しいアプリをビルドします。このアプリではレイアウトのオーバーレイが可能です。先ほどと同じ手順に沿って行うか、既存のアプリを修正します。
必ず次の行を
overlayable.xmlに追加してください。<?xml version="1.0" encodin>g<="ut>f-8<"? resources overlayable> name<="CarUiCodelab&>quot; < policy type="public" > item <type="string" name="sampl>e_text&<quot;/ item type="la>yout&<quot; n>ame<="activ>i<ty_main&qu>ot;/ item type="id" name="textView"/ /policy /overlayable /resourcesactivity_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" encodin>g<="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/TextA>ppearance.CarUi" android:layout_gravity="center_vertical|center_horizontal"/ /FrameLayoutres/values/styles.xmlを更新してスタイルを RRO に追加します。<?xml version="1.0" encodin>g<="ut>f-8&q<uot;? resources style name="TextAppearance.CarUi" parent="an>droid:Tex<tAppearance.DeviceDefault&quo>t; < > item na<me="android:textColor&q>uot;#<0f0/i>tem < > <item name=>"android:textSize"100sp/item /style /resources新しいアプリを指すように、
AndroidManifest.xmlのtargetNameを変更します。… android:targetName="CarUiCodelab" …RRO の
sample_overlay.xmlファイルにリソースを追加します。<?xml version="1.0" encodin>g<=">utf-8<"? overlay item target="string/sample_text">; val<ue="@string/sample_text"/ item ta>rget=<"id/textView" value="@id/textView"/ item >t<arget=&q>uot;layout/activity_main" value="@layout/activity_main"/ /overlay先ほどと同じ方法でアプリと RRO をビルドしてインストールします(緑の [Play] ボタン)。忘れずに RRO を有効にしてください。
アプリと RRO は次のようにレンダリングされます。レイアウト RRO で指定されているとおり、「Hello World RRO」のテキストは緑色で中心に配置されています。
CarUiRecyclerView をアプリに追加する
所要時間: 15 分
CarUiRecyclerView インターフェースは car-ui-lib リソース経由でカスタマイズされる RecyclerView にアクセスできる API を提供します。たとえば、CarUiRecyclerView は実行時にフラグを確認して、スクロールバーを有効にすべきかどうかを判断し、対応するレイアウトを選択します。
CarUiRecyclerViewを追加するには、activity_main.xmlとMainActivity.javaファイルに追加します。新しいアプリをゼロから作成することも、既存のアプリを修正することもできます。既存のアプリを修正する場合は、overlayable.xmlからの宣言されていないリソースを必ず削除してください。activity_main.xml<?xml version="1.0" encodin>g<="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 が表示されるようになります。
RRO を使用してスクロールバーを削除する
所要時間: 10 分
この演習では RRO を使用して CarUiRecyclerView からスクロールバーを削除する方法を示します。
RRO に以下のファイルを追加して修正します。
AndroidManifest.xml<?xml version="1.0" encodin>g<="utf-8"? manifest xmlns:android="http://schemas.android.com/apk/res/android" >packag<e="com.example.caruirro" > app<lication android:hasCode="false" / uses-sdk android:minSdkV>ersion<="29" android:targetSdkVersion="29"/ overlay android:targetPackage="com.example.caruicodelab" android:targetName="car-ui-lib" > < andro>id:isStatic="false" android:resourcesMap="@xml/sample_overlay" / /manifestres/values/bools.xml<?xml version="1.0" encodin>g<="ut>f-8&q<uot;? resources bool name=">;car_<ui_sc>r<ollbar_ena>ble"false/bool /resourcesリソース
car_ui_scrollbar_enableはcar-ui-libブール値リソースで、自動車向けに最適された、上下ボタンが付いたスクロールバーをCarUiRecyclerViewに表示するかどうかをコントロールします。falseに設定すると、CarUiRecyclerViewは AndroidXRecyclerViewのように動作します。res/xml/sample_overlay.xml<?xml version="1.0" encodin>g<=">utf-8<"? overlay item target="bool/car_ui_scrollbar_enable" value=&q>u<ot;@bool>/car_ui_scrollbar_enable"/ /overlay
アプリをこれまでと同じようにビルドしてインストールします。スクロールバーは CarUiRecyclerView から削除されました。
レイアウトを使用して CarUiRecyclerView スクロールバーをオーバーレイする
所要時間: 15 分
この演習では、CarUiRecyclerView のスクロールバー レイアウトを修正します。
以下のファイルを RRO アプリに追加して修正します。
res/layout/car_ui_recycler_view_scrollbar.xml<?xml version="1.0" encodin>g<="utf-8"? RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="112dp" android:layout_height="match_pa>rent&<quot; 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>_cent<erHorizontal="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="10>dp&qu<ot; 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_hei>ght=&<quot;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:f>ocusa<ble="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&quo>t<; andro>id: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" encodin>g<=">utf-<8"? overlay item target="drawable/car_ui_recyclerview_ic_down" value="@dra>wabl<e/car_ui_recyclerview_ic_down"/ item target="drawable/car_ui_recyclerview_ic_up&>quot<; value="@drawable/car_ui_recyclerview_ic_up"/ item target="drawable/car_ui_recyclerview_scroll>bar_<thumb" value="@drawable/car_ui_recyclerview_scrollbar_t>humb<"/ item target="id/car_ui_scroll_bar" value="@id/car>_ui_<scroll_bar"/ item target="id/car_ui_scrollbar_thumb" valu>e=&q<uot;@id/car_ui_scrollbar_thumb"/ item target="id/car_ui_scrollbar_>trac<k" value="@id/car_ui_scrollbar_track"/ item target="id/car_u>i_sc<rollbar_page_up" value="@id/car_ui_scrollbar_page_up"/ item target="id/car>_<ui_scrol>lbar_page_down" value="@id/car_ui_scrollbar_page_down"/ item target="layout/car_ui_recyclerview_scrollbar" value="@layout/car_ui_recyclerview_scrollbar"/ /overlayres/drawable/car_ui_recyclerview_ic_up.xml<?xml version="1.0" encodin>g<="utf-8"? vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:view>portW<idth="48.0" android:viewportHeight="48.0" path android:pathData="M14.83,30.83L>2<4,21.66>l9.17,9.17L36,28 24,16 12,28z" android:fillColor="#0000FF"/ /vectorres/drawable/car_ui_recyclerview_ic_down.xml<?xml version="1.0" encodin>g<="utf-8"? vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:view>portW<idth="48.0" android:viewportHeight="48.0" path android:pathData="M14.83,16.42L24,25.5>9<l9.17,->9.17L36,19.25l-12,12 -12,-12z" android:fillColor="#0000FF"/ /vectorres/drawable/car_ui_recyclerview_scrollbar_thumb.xml<?xml version="1.0" encodin>g<="utf-8"? shape xmlns:android="http://schemas.android.com/apk/res/android"> <android:shape="rectangle&q>uot; < solid android:color="#>0<000FF&>quot; / corners android:radius="100dp"/ /shapeこれらのファイルの仕組みを確認しておくことをおすすめします。
簡単に説明すると、寸法と色はハードコードされています。ただし、これらの値を
dimens.xmlおよびcolors.xmlで宣言するか、res/color/フォルダで色ファイルとして指定することをおすすめします。詳しくは、コントリビューター向け AOSP Java コードスタイルをご覧ください。アプリをこれまでと同じようにビルドしてインストールします。青のスクロールバーとグレーのレールの
CarUiRecyclerViewがビルドされます。
お疲れさまでした。スクロールバーの下に上下の矢印が表示されます。Android Studio から Gradle ビルドシステムを使用して、正常に RRO を car-ui-lib レイアウト リソース ファイルに適用できました。
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=>&<#39;UTF-8>'<?
resources
overlayable n>ame="car-ui-li<b"
…
item type="attr" name=&>quot;layo<ut_constraintBottom_toBottomOf"/
item type=>"att<r" name="layout_constraintBottom_toTop>Of"/<
item type="attr" name="layout>_constrai<ntCircle"/
item type="attr" nam>e="l<ayout_constraintCircleAngle"/
item type=&qu>ot;attr&q<uot; name="layout_constraintCircleRadius"/
> i<tem type="attr" name="layout_constraintD>imensionR<atio"/
item type="attr" name=&>quot;layo<ut_constraintEnd_toEndOf"/
item type=&>quot;attr<" name="layout_constraintEnd_toStartOf"/>
<item type="attr" name="layout_constraintG>uide_begi<n"/
item type="attr" name=&qu>ot;layout<_constraintGuide_end"/
item type=">attr"<; name="layout_constraintGuide_percent"/
> item t<ype="attr" name="layout_constraintHeight_d>efault&qu<ot;/
item type="attr" name="layout_const>raintHeig<ht_max"/
item type="attr" name=">;layout_c<onstraintHeight_min"/
item type="att>r" n<ame="layout_constraintHeight_percent"/
> item ty<pe="attr" name="layout_constraintHorizont>al_bias&q<uot;/
item type="attr" name="lay>out_const<raintHorizontal_chainStyle"/
item type=&quo>t;attr&qu<ot; name="layout_constraintHorizontal_weight"/
> i<tem type="attr" name="layout_constraintL>eft_creat<or"/
item type="attr" name="l>ayout_con<straintLeft_toLeftOf"/
item type>="at<tr" name="layout_constraintLeft_toRightOf&q>uot;/
< item type="attr" name="layout_constr>aintRight<_creator"/
item type="attr" na>me="<layout_constraintRight_toLeftOf"/
item typ>e="a<ttr" name="layout_constraintRight_toRightOf"/
> item ty<pe="att>r<" nam>e="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" encodin>g<=">utf-<8"? overlay item target="id/car_ui_list_item_touch_interceptor" value="@id/c>ar_u<i_list_item_touch_interceptor"/ item target="id/car_ui_list_item_reduced_touch_interceptor" value>=&qu<ot;@id/car_ui_list_item_reduced_touch_interceptor"/ item target="id/car_ui_list_it>em_s<tart_guideline" value="@id/car_ui_list_item_start_guideline"/ item target=&>quot<;id/car_ui_list_item_icon_container" value="@id/car_ui_list_ite>m_ic<on_container"/ item target="id/car_ui_list_item_icon" value="@id/c>ar_u<i_list_item_icon"/ item target="id/car_ui_list_item_content_icon" val>ue=&<quot;@id/car_ui_list_item_content_icon"/ item target="id/car_u>i_li<st_item_avatar_icon" value="@id/car_ui_list_item_avatar_icon&qu>ot;/< item target="id/car_ui_list_item_title" value="@id/car_ui_list_item_title"/ item target="id/car_ui_li>st_i<tem_body" value="@id/car_ui_list_item_body"/ item target="id/car_ui_list_i>tem_<action_container_touch_interceptor" value="@id/car_ui_list_item_action_container_to>uch_<interceptor"/ item target="id/car_ui_list_item_action_container" value=&q>uot;<@id/car_ui_list_item_action_container"/ item target="id/car_ui_list_item_action_di>vide<r" value="@id/car_ui_list_item_action_divider"/ item target="id/car_ui_list_item>_swi<tch_widget" value="@id/car_ui_list_item_switch_widget"/ item target="id/car_>ui_l<ist_item_checkbox_widget" value="@id/car_ui_list_item_checkbox_widget"/ i>tem <target="id/car_ui_list_item_radio_button_widget" value="@id/car_ui_list_item_radio_butto>n_wi<dget"/ item target="id/car_ui_list_item_supplemental_icon" value="@id/car_>ui_l<ist_item_supplemental_icon"/ item target="id/car_ui_list_item_end_guideline&qu>ot; <value="@id/car_ui_list_item_end_guideline"/ item target="attr/layout_constrai>ntBo<ttom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/ item t>arge<t="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintB>otto<m_toTopOf"/ item target="attr/layout_constraintEnd_toEndOf" value="@attr/lay>out_<constraintEnd_toEndOf"/ item target="attr/layout_constraintEnd_toStartOf" val>ue=&<quot;@attr/layout_constraintEnd_toStartOf"/ item target="attr/layout_constraintGuide>_beg<in" value="@attr/layout_constraintGuide_begin"/ item target="attr/layout_c>onst<raintGuide_end" value="@attr/layout_constraintGuide_end"/ item target="attr/>layo<ut_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/ > ite<m target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_to>Left<Of"/ item target="attr/layout_constraintLeft_toRightOf" value="@attr/layou>t_co<nstraintLeft_toRightOf"/ item target="attr/layout_constraintRight_toLeftOf&quo>t; v<alue="@attr/layout_constraintRight_toLeftOf"/ item target="attr>/lay<out_constraintRight_toRightOf" value="@attr/layout_constraintRigh>t_to<RightOf"/ item target="attr/layout_constraintStart_toEndOf"> val<ue="@attr/layout_constraintStart_toEndOf"/ item target="attr/>layo<ut_constraintStart_toStartOf" value="@attr/layout_constraintStart_toS>tart<Of"/ item target="attr/layout_constraintTop_toBottomOf" v>alue<="@attr/layout_constraintTop_toBottomOf"/ item target="attr/layout_constraintTop_toTopOf&>quot<; value="@attr/layout_constraintTop_toTopOf"/ item target=>&<quot;att>r/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"/ /overlayres/layout/car_ui_list_item.xml<?xml version="1.0" encodin>g<="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="carU>iListI<tem" android:minHeight="@dimen/car_ui_list_item_height" !-- The following touch interceptor views are sized to encompass the specific sub-sections of th>e lis<t 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_constr>aintEn<d_toEndOf="parent" app:layout_constraintStart_toS>tartO<f="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_constraintBotto>m_toBo<ttomOf="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:i>d=&quo<t;@+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_containe>r" < 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_to>TopOf=&quo<t;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&qu>ot; < 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" a>ndroi<d: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:>textA<ppearance="@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:lay>out_wi<dth="0dp" android:layout_height="wrap_content" androi>d:lay<out_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_t<itle" 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=&qu>ot;@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=&<quot;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:l<ayout_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&q>uot; < >androi<d: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:l>ay<out_height="wrap_content" an>droid: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.ConstraintLayoutcar_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' }
タイトルと本文が左揃えではなく右揃えになりました。
属性が 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'