Skorzystaj z biblioteki car-ui-lib
aby uruchomić spójne, pokładowe systemy informacyjno-rozrywkowe (IVI). W tym laboratorium z programowania zapoznasz się z car-ui-lib
i zobaczysz, jak możesz używać nakładek zasobów wykonawczych (RRO) do dostosowywania komponentów w bibliotece.
Czego się dowiesz
Jak:
- Dołącz komponenty
car-ui-lib
do swojej aplikacji na Androida. - Użyj Gradle do tworzenia aplikacji na Androida i RRO.
- Użyj RRO z
car-ui-lib
.
To ćwiczenie z programowania nie opisuje szczegółowo, jak działają RRO. Aby dowiedzieć się więcej, zobacz Zmienianie wartości zasobów aplikacji w czasie wykonywania i Rozwiązywanie problemów z nakładkami zasobów w czasie wykonywania .
Zanim zaczniesz
Warunki wstępne
Zanim zaczniesz, upewnij się, że masz:
Komputer z wierszem poleceń (komputer z systemem Linux, komputer Mac lub komputer z systemem Windows i podsystemem Windows dla systemu Linux).
Urządzenie z Androidem lub emulator podłączone do Twojego komputera. Zobacz Pobieranie źródła systemu Android i Tworzenie systemu Android .
Podstawowa wiedza na temat RRO.
Utwórz nową aplikację na Androida
Czas trwania: 15 minut
W tej sekcji utworzysz nowy projekt Android Studio.
W Android Studio utwórz aplikację z
EmptyActivity
.Nazwij aplikację
CarUiCodelab
, a następnie wybierz język Java. W razie potrzeby możesz także wybrać lokalizację pliku. Zaakceptuj wartości domyślne pozostałych ustawień.Zastąp plik
activity_main.xml
następującym blokiem kodu:<?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>
Ten blok kodu wyświetla ciąg
sample_text
, który nie jest zdefiniowany.Dodaj ciąg zasobu
sample_text
i ustaw go na „Hello World!” w plikustrings.xml
. Aby otworzyć ten plik, wybierz 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>
Aby zbudować aplikację, kliknij zielony przycisk Odtwórz w prawym górnym rogu. Spowoduje to automatyczną instalację aplikacji na emulatorze lub urządzeniu z systemem Android za pośrednictwem Gradle.
Nowa aplikacja powinna otworzyć się automatycznie na Twoim emulatorze lub urządzeniu z Androidem. Jeśli nie, otwórz aplikację CarUiCodelab
w programie uruchamiającym aplikacje, który jest teraz zainstalowany. Wygląda to tak:
Dodaj car-ui-lib do swojej aplikacji na Androida
Czas trwania: 15 minut
Dodaj car-ui-lib
do swojej aplikacji:
Aby dodać zależność
car-ui-lib
do plikubuild.gradle
projektu, wybierz aplikacja > build.gradle . Twoje zależności powinny wyglądać następująco: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' }
Użyj komponentów car-ui-lib w swojej aplikacji na Androida
Teraz, gdy masz już car-ui-lib
, dodaj pasek narzędzi do swojej aplikacji.
W pliku
MainActivity.java
zastąp metodę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); }
Pamiętaj, aby zaimportować
ToolbarController
:import com.android.car.ui.core.CarUi; import com.android.car.ui.toolbar.ToolbarController;
Aby użyć motywu
Theme.CarUi.WithToolbar
, wybierz aplikację > src > main > AndroidManifest.xml , a następnie zaktualizujAndroidManifest.xml
tak, aby wyglądał następująco:<?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>
Aby zbudować aplikację, naciśnij zielony przycisk Play , tak jak poprzednio.
Dodaj RRO do swojej aplikacji
Czas trwania: 30 minut
Jeśli znasz RRO, przejdź do następnej sekcji, Dodaj kontroler uprawnień do swojej aplikacji . W przeciwnym razie, aby poznać podstawy RRO, zobacz temat Zmiana wartości zasobów aplikacji w czasie wykonywania .
Dodaj kontroler uprawnień do swojej aplikacji
Aby kontrolować, które zasoby są nakładane przez pakiet RRO, dodaj plik o nazwie overlayable.xml
do folderu /res
aplikacji. Ten plik służy jako kontroler uprawnień między Twoją aplikacją ( celem ) a pakietem RRO ( nakładką ).
Dodaj
res/values/overlayable.xml
do swojej aplikacji i skopiuj następującą zawartość do swojego pliku:<?xml version="1.0" encoding="utf-8"?> <resources> <overlayable name="CarUiCodelab"> <policy type="public"> <item type="string" name="sample_text"/> </policy> </overlayable> </resources>
Ponieważ ciąg
sample_text
musi nadawać się do nałożenia przez RRO, dołącz nazwę zasobu do pliku overlayable.xml aplikacji.Twój plik
overlayable.xml
MUSI znajdować się wres/values/
. Jeśli nie,OverlayManagerService
nie będzie w stanie go zlokalizować.Aby dowiedzieć się więcej o zasobach, które można nakładać, oraz o tym, jak można je skonfigurować, zobacz temat Ograniczanie zasobów, które można nakładać .
Utwórz pakiet RRO
W tej sekcji utworzysz pakiet RRO, aby zmienić wyświetlany powyżej ciąg znaków z „Hello World!” do „Hello World RRO”.
Aby utworzyć nowy projekt, wybierz Plik > Nowy > Nowy projekt . Pamiętaj, aby wybrać opcję Brak działania zamiast Puste działanie, ponieważ pakiety RRO zawierają tylko zasoby.
Twoje konfiguracje wyglądają podobnie do tych przedstawionych poniżej. Lokalizacja, w której są zapisywane, może się różnić:
Po utworzeniu nowego projektu
CarUiRRO
zadeklaruj projekt jako RRO, modyfikującAndroidManifest.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>
Wykonanie tej czynności powoduje błąd z
@xml/sample_overlay
. PlikresourcesMap
odwzorowuje nazwy zasobów z pakietu docelowego na pakiet RRO.Skopiuj następujący blok kodu do
…/res/xml/sample_overlay.xml
:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> </overlay>
Dodaj
sample_text
do…/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>
Aby zbudować swój cel RRO, naciśnij zielony przycisk Odtwórz , aby utworzyć kompilację Gradle swojego RRO na emulatorze lub urządzeniu z systemem Android.
Aby sprawdzić, czy RRO jest poprawnie zainstalowane, uruchom:
shell:~$ adb shell cmd overlay list --user current | grep -i com.example com.example.caruicodelab [ ] com.example.caruirro
To polecenie wyświetla przydatne informacje o stanie pakietów RRO w systemie.
-
[ ]
oznacza, że RRO jest zainstalowane i gotowe do aktywacji. -
---
wskazuje, że RRO jest zainstalowane, ale zawiera błędy. -
[X]
oznacza, że RRO jest zainstalowane i aktywowane.
Jeśli RRO zawiera błędy, zanim przejdziesz dalej, zobacz Rozwiązywanie problemów z nakładkami zasobów środowiska wykonawczego .
-
Aby włączyć RRO i sprawdzić, czy jest włączone:
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
Twoja aplikacja wyświetla ciąg „Hello World RRO”.
Gratulacje! Stworzyłeś swoje pierwsze RRO.
Podczas korzystania z RRO możesz użyć flag narzędzia Android Asset Packaging Tool (AAPT2) --no-resource-deduping
i --no-resource-removal
opisanych w opcjach łącza . Dodawanie flag w tym ćwiczeniu z programowania nie jest konieczne, ale sugerujemy użycie ich w RRO, aby uniknąć usuwania zasobów (i problemów związanych z debugowaniem). Możesz dodać je do pliku build.gradle
swojego RRO w następujący sposób:
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
Aby dowiedzieć się więcej na temat tych flag, zobacz Kompilowanie pakietu i AAPT2 .
Modyfikuj komponenty car-ui-lib
za pomocą RRO w aplikacji na Androida
Na tej stronie opisano, jak używać nakładki zasobów wykonawczych (RRO) do modyfikowania komponentów z biblioteki car-ui-lib
w aplikacji na Androida.
Ustaw kolor tła paska narzędzi
Czas trwania: 15 minut
Aby zmienić kolor tła paska narzędzi:
Dodaj następującą wartość do swojej aplikacji RRO i ustaw zasób na jasnozielony (
#0F0
):<?xml version="1.0" encoding="utf-8"?> <resources> <drawable name="car_ui_toolbar_background">#0F0</drawable> </resources>
Biblioteka
car-ui-lib
zawiera zasób o nazwiecar_ui_toolbar_background
. Gdy ten zasób jest zawarty w konfiguracji RRO, pasek narzędzi nie zmienia się, ponieważ docelowa jest niewłaściwa wartość.W pliku
AndroidManifest.xml
dla swojego RRO zaktualizujtargetName
, aby wskazywał nacar-ui-lib
:… android:targetName="car-ui-lib" …
MUSISZ utworzyć nowy pakiet RRO dla każdego pakietu docelowego, który chcesz RRO. Na przykład podczas tworzenia nakładek dla dwóch różnych obiektów docelowych należy utworzyć dwie aplikacje nakładek.
Zbuduj, zweryfikuj, zainstaluj i włącz RRO w taki sam sposób jak poprzednio.
Twoja aplikacja wygląda następująco:
Układy i style RRO
Czas trwania: 15 minut
W tym ćwiczeniu utworzysz nową aplikację podobną do aplikacji utworzonej wcześniej. Ta aplikacja umożliwia nakładanie układu. Wykonaj te same kroki co poprzednio lub zmodyfikuj istniejącą aplikację.
Pamiętaj, aby dodać następujące wiersze do pliku
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>
Upewnij się, że
activity_main.xml
wygląda następująco:<?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>
W aplikacji RRO utwórz plik
res/layout/activity_main.xml
i dodaj następujące elementy:<?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>
Zaktualizuj plik
res/values/styles.xml
aby dodać nasz styl do 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>
Zmień
targetName
wAndroidManifest.xml
, aby wskazywała nazwę nowej aplikacji:… android:targetName="CarUiCodelab" …
Dodaj zasoby do pliku
sample_overlay.xml
w swoim RRO:<?xml version="1.0" encoding="utf-8"?> <overlay> <item target="string/sample_text" value="@string/sample_text"/> <item target="id/textView" value="@id/textView"/> <item target="layout/activity_main" value="@layout/activity_main"/> </overlay>
Zbuduj i zainstaluj aplikację oraz RRO w taki sam sposób jak poprzednio (zielony przycisk Odtwórz ). Pamiętaj, aby włączyć RRO.
Aplikacja i RRO renderują się w następujący sposób. Tekst Hello World RRO jest zielony i wyśrodkowany, jak określono w układzie RRO.
Dodaj CarUiRecyclerView do swojej aplikacji
Czas trwania: 15 minut
Interfejs CarUiRecyclerView
zapewnia interfejsy API umożliwiające dostęp do RecyclerView
, który jest dostosowywany za pomocą zasobów car-ui-lib
. Na przykład CarUiRecyclerView
sprawdza flagę w czasie wykonywania, aby określić, czy pasek przewijania powinien być włączony, czy nie, i wybiera odpowiedni układ.
Aby dodać
CarUiRecyclerView
, dodaj go do plikówactivity_main.xml
iMainActivity.java
. Możesz utworzyć nową aplikację od zera lub zmodyfikować istniejącą aplikację. Jeśli zmodyfikujesz istniejącą aplikację, pamiętaj o usunięciu niezadeklarowanych zasobów zoverlayable.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"/>
Może pojawić się następujący błąd, który możesz zignorować:
Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerView
Tak długo, jak twoja klasa jest napisana poprawnie i dodałeś
car-ui-lib
jako zależność, możesz zbudować i skompilować swoją apk. Aby usunąć błąd, wybierz opcję Plik > Unieważnij pamięć podręczną, a następnie kliknij Unieważnij i uruchom ponownie.Dodaj następujący tekst do
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; }
Kompiluj i instaluj aplikację tak jak poprzednio.
Teraz widzisz CarUiRecyclerView
:
Użyj RRO, aby usunąć pasek przewijania
Czas trwania: 10 minut
W tym ćwiczeniu pokazano, jak używać RRO do usuwania paska przewijania z CarUiRecyclerView
.
W swoim RRO dodaj i zmodyfikuj następujące pliki:
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>
Zasób
car_ui_scrollbar_enable
to zasób logicznycar-ui-lib
, który kontroluje, czy pasek przewijania zoptymalizowany pod kątem samochodu z przyciskami w górę i w dół wCarUiRecyclerView
jest obecny, czy nie. Po ustawieniu wartościfalse
CarUiRecyclerView
działa jak 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>
Kompiluj i instaluj aplikację tak jak poprzednio. Pasek przewijania został teraz usunięty z CarUiRecyclerView
:
Użyj układu, aby nałożyć pasek przewijania CarUiRecyclerView
Czas trwania: 15 minut
W tym ćwiczeniu zmodyfikujesz układ paska przewijania CarUiRecyclerView
.
Dodaj i zmodyfikuj następujące pliki w swojej aplikacji 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>
Aby nałożyć plik układu, musisz dodać wszystkie identyfikatory i atrybuty przestrzeni nazw do pliku
overlay.xml
swojego RRO. Zobacz pliki poniżej.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>
Sugeruje się sprawdzenie interakcji tych plików.
Dla uproszczenia wymiary i kolory są zakodowane na stałe. Jednak najlepszą praktyką jest deklarowanie tych wartości w
dimens.xml
colors.xml
lub nawet oznaczanie ich jako plików kolorów w folderzeres/color/
. Aby dowiedzieć się więcej, zobacz Styl kodu Java AOSP dla autorów .Kompiluj i instaluj aplikację tak jak poprzednio. Zbudowałeś
CarUiRecyclerView
z niebieskim paskiem przewijania i szarymi szynami.
Gratulacje! Obie strzałki pojawiają się na dole paska przewijania. Pomyślnie zastosowałeś RRO do pliku zasobów układu car-ui-lib
przy użyciu systemu kompilacji Gradle w Android Studio.
Elementy listy RRO
Czas trwania: 15 minut
Do tego momentu zastosowałeś RRO do komponentów car-ui-lib
przy użyciu komponentów frameworka (nie AndroidX). Aby używać komponentów AndroidX w RRO, musisz dodać zależności tego komponentu zarówno do aplikacji, jak i do pliku RRO build.gradle.
Musisz także dodać attrs
tego komponentu do overlayable.xml
w swojej aplikacji, a także sample_overlay.xml
w swoim RRO.
Nasza biblioteka ( car-ui-lib
) korzysta z ConstraintLayout
oraz innych komponentów AndroidX, więc jej overlayable.xml
może wyglądać następująco:
<?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>
Zmień układ elementów listy w
CarUiRecyclerView
przy użyciuConstraintLayout
. Dodaj lub zmodyfikuj następujące pliki w swoim 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>
plik
car_ui_list_item.xml
zawiera kilka odniesień do kilku komponentów/zasobów, które nie są uwzględnione jako zależności aplikacji. To są zasobycar-ui-lib
. Możesz to naprawić, dodająccar-ui-lib
jako zależność do aplikacji RRO wapp/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' }
Tytuł i treść są teraz wyrównane do prawej, a nie do lewej.
Zastosowaliśmy RRO do car-ui-lib
przy użyciu komponentów AndroidX ( ConstraintLayout
), gdy jego atrybuty były obecne w pliku car-ui-lib
o nazwie overlayable.xml
, a także RRO sample_overlay.xml
. Można zrobić coś podobnego we własnej aplikacji. Po prostu dodaj wszystkie odpowiednie attrs
do pliku overlayable.xml
swojej aplikacji, podobnie jak w przypadku car-ui-lib
.
Nie jest jednak możliwe wykonanie RRO aplikacji przy użyciu komponentów AndroidX, jeśli aplikacja ma zależność car-ui-lib
w swoim build.gradle
(kiedy aplikacja korzysta z komponentów car-ui-lib
). Ponieważ mapowania atrybutów zostały już zdefiniowane w pliku overlayable.xml
biblioteki car-ui-lib
, dodanie ich do pliku overlayable.xml
aplikacji z car-ui-lib
jako zależnością spowodowałoby błąd mergeDebugResources
podobny do poniższego. Dzieje się tak, ponieważ te atrybuty są obecne w wielu plikach overlayable.xml
:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'