Użyj car-ui-lib, aby uruchamiać spójne systemy multimedialne w pojazdach. W tym ćwiczeniu dowiesz się, czym jest car-ui-lib i jak za pomocą nakładek zasobów środowiska wykonawczego (RRO) dostosowywać komponenty w bibliotece.
Czego się nauczysz
Instrukcje:
- Umieść w aplikacji na Androida komponenty
car-ui-lib. - Używaj Gradle do kompilowania aplikacji na Androida i nakładek RRO.
- Używaj RRO z
car-ui-lib.
W tym ćwiczeniu nie opisujemy szczegółowo działania nakładek RRO. Więcej informacji znajdziesz w artykułach Zmiana wartości zasobów aplikacji w czasie działania i Rozwiązywanie problemów z nakładkami zasobów w czasie działania.
Zanim rozpoczniesz
Wymagania wstępne
Zanim zaczniesz, upewnij się, że masz:
Komputer z wierszem poleceń (urządzenie z systemem Linux, Mac lub Windows z podsystemem Windows dla systemu Linux).
Urządzenie z Androidem lub emulator podłączony do komputera. Zobacz Pobieranie źródła Androida i Kompilowanie Androida.
Podstawowa wiedza o RRO.
Tworzenie nowej aplikacji na Androida
Czas trwania: 15 minut
W tej sekcji utworzysz nowy projekt w Android Studio.
W Android Studio utwórz aplikację z
EmptyActivity.
Rysunek 1.Tworzenie pustej aktywności Nazwij aplikację
CarUiCodelab, a potem wybierz język Java. W razie potrzeby możesz też wybrać lokalizację pliku. Zaakceptuj domyślne wartości pozostałych ustawień.
Rysunek 2. Nazwij aplikację Zastąp
activity_main.xmltym 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 znaków
sample_text, który nie jest zdefiniowany.Dodaj ciąg zasobu
sample_texti 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 utworzyć aplikację, w prawym górnym rogu kliknij zielony przycisk Odtwórz. Spowoduje to automatyczne zainstalowanie pliku APK w emulatorze lub na urządzeniu z Androidem za pomocą Gradle.
Nowa aplikacja powinna otworzyć się automatycznie na emulatorze lub urządzeniu z Androidem. Jeśli nie, otwórz aplikację CarUiCodelab z menu z aplikacjami.
Wygląda to tak:
Dodawanie biblioteki car-ui-lib do aplikacji na Androida
Czas trwania: 15 minut
Dodaj car-ui-lib do aplikacji:
Aby dodać zależność
car-ui-libdo plikubuild.gradleprojektu, wybierz app > build.gradle. Zależności powinny wyglądać tak: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żywanie komponentów car-ui-lib w aplikacji na Androida
Teraz, gdy masz car-ui-lib, dodaj pasek narzędzi do aplikacji.
W pliku
MainActivity.javazastą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 app > src > main > AndroidManifest.xml, a następnie zaktualizujAndroidManifest.xml, aby wyglądało to tak:<?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 skompilować aplikację, naciśnij zielony przycisk Odtwórz, tak jak wcześniej.
Dodawanie do aplikacji nakładek RRO
Czas trwania: 30 minut
Jeśli znasz nakładki RRO, przejdź do następnej sekcji: Dodawanie kontrolera uprawnień do aplikacji. Jeśli chcesz poznać podstawy nakładek RRO, przeczytaj artykuł Zmiana wartości zasobów aplikacji w czasie działania.
Dodawanie do aplikacji kontrolera uprawnień
Aby określić, które zasoby ma zastępować pakiet RRO, dodaj do folderu /res aplikacji plik o nazwie overlayable.xml. Ten plik pełni funkcję kontrolera uprawnień między aplikacją (elementem docelowym) a pakietem RRO (nakładką).
Dodaj
res/values/overlayable.xmldo aplikacji i skopiuj do pliku te wiersze:<?xml version="1.0" encoding="utf-8"?> <resources> <overlayable name="CarUiCodelab"> <policy type="public"> <item type="string" name="sample_text"/> </policy> </overlayable> </resources>Ciąg
sample_textmusi być nakładany przez RRO, więc umieść nazwę zasobu w pliku overlayable.xml aplikacji.Plik
overlayable.xmlMUSI znajdować się w katalogures/values/. W przeciwnym razieOverlayManagerServicenie będzie w stanie go znaleźć.Więcej informacji o zasobach, które można nakładać, i sposobach ich konfigurowania znajdziesz w artykule Ograniczanie zasobów, które można nakładać.
Tworzenie pakietu RRO
W tej sekcji utworzysz pakiet RRO, aby zmienić ciąg znaków wyświetlany powyżej z „Hello World!” na „Hello World RRO”.
Aby utworzyć nowy projekt, kliknij Plik > Nowy > Nowy projekt. Pamiętaj, aby wybrać Brak aktywności zamiast Pusta aktywność, ponieważ pakiety RRO zawierają tylko zasoby.
Konfiguracje będą wyglądać podobnie do tych na ilustracji poniżej. Miejsce, w którym są zapisywane, może się różnić:
Po utworzeniu nowego projektu
CarUiRROzadeklaruj go 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>Spowoduje to błąd w usłudze
@xml/sample_overlay. PlikresourcesMapmapuje nazwy zasobów z pakietu docelowego na pakiet RRO. Ustawienie flagihasCodenafalsejest obowiązkowe w przypadku pakietów RRO. Ponadto pakiety RRO nie mogą zawierać plików DEX.Skopiuj ten blok kodu do pliku
…/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_textdo…/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 utworzyć docelowy RRO, naciśnij zielony przycisk Odtwórz, aby utworzyć kompilację Gradle RRO na emulatorze lub urządzeniu z Androidem.
Aby sprawdzić, czy RRO jest prawidłowo zainstalowany, uruchom to polecenie:
shell:~$ adb shell cmd overlay list --user current | grep -i com.example com.example.caruicodelab [ ] com.example.caruirroTo polecenie wyświetla przydatne informacje o stanie pakietów RRO w systemie.
[ ]oznacza, że RRO jest zainstalowany i gotowy do aktywacji.---oznacza, że nakładka RRO jest zainstalowana, ale zawiera błędy.[X]oznacza, że RRO jest zainstalowany i aktywny.
Jeśli RRO zawiera błędy, przed kontynuowaniem zapoznaj się z artykułem Rozwiązywanie problemów z nakładkami zasobów w czasie działania.
Aby włączyć RRO i sprawdzić, czy jest włączony:
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
Aplikacja wyświetli ciąg znaków „Hello World RRO”.
Gratulacje! Udało Ci się utworzyć pierwszy RRO.
Podczas korzystania z RRO możesz używać flag narzędzia AAPT2 (Android Asset Packaging Tool) --no-resource-deduping i --no-resource-removal opisanych w sekcji Opcje linkowania.
W tym ćwiczeniu z programowania nie musisz dodawać tych flag, ale zalecamy ich używanie w przypadku nakładek RRO, aby uniknąć usuwania zasobów (i problemów z debugowaniem). Możesz je dodać do pliku build.gradle RRO w ten sposób:
android {
…
aaptOptions {
additionalParameters "--no-resource-deduping", "--no-resource-removal"
}
}
Więcej informacji o tych flagach znajdziesz w sekcjach Tworzenie pakietu i AAPT2.
Modyfikowanie car-ui-lib komponentów za pomocą nakładek RRO w aplikacji na Androida
Na tej stronie dowiesz się, jak używać nakładki zasobów w czasie działania (RRO) do modyfikowania komponentów z biblioteki car-ui-lib w aplikacji na Androida.
Ustawianie koloru tła paska narzędzi
Czas trwania: 15 minut
Aby zmienić kolor tła paska narzędzi:
Dodaj do aplikacji RRO tę wartość i ustaw zasób na jasny zielony (
#0F0):<?xml version="1.0" encoding="utf-8"?> <resources> <drawable name="car_ui_toolbar_background">#0F0</drawable> </resources>Biblioteka
car-ui-libzawiera zasób o nazwiecar_ui_toolbar_background. Jeśli ten zasób znajduje się w konfiguracji RRO, pasek narzędzi nie zmienia się, ponieważ jest kierowany na nieprawidłową wartość.W
AndroidManifest.xmldla RRO zaktualizujtargetName, aby wskazywałcar-ui-lib:… android:targetName="car-ui-lib" …Dla każdego pakietu docelowego, który chcesz poddać RRO, MUSISZ utworzyć nowy pakiet RRO. Na przykład podczas tworzenia nakładek dla 2 różnych miejsc docelowych musisz utworzyć 2 pliki APK nakładek.
Zbuduj, zweryfikuj, zainstaluj i włącz RRO w taki sam sposób jak wcześniej.
Aplikacja będzie wyglądać tak:
Układy i style RRO
Czas trwania: 15 minut
W tym ćwiczeniu utworzysz nową aplikację podobną do tej, którą utworzono wcześniej. Ta aplikacja umożliwia nakładanie układu. Wykonaj te same czynności co wcześniej lub zmodyfikuj istniejącą aplikację.
Pamiętaj, aby dodać te 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>Sprawdź, czy
activity_main.xmlwygląda tak:<?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
res/layout/activity_main.xmli dodaj te informacje:<?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
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ń
targetNamewAndroidManifest.xml, aby wskazywało nazwę nowej aplikacji:… android:targetName="CarUiCodelab" …Dodaj zasoby do pliku
sample_overlay.xmlw nakładce 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 wcześniej (zielony przycisk Play). Pamiętaj, aby włączyć RRO.
Aplikacja i RRO są renderowane w ten sposób: Tekst RRO „Hello World” jest zielony i wyśrodkowany zgodnie z określeniem w RRO układu.
Dodawanie CarUiRecyclerView do aplikacji
Czas trwania: 15 minut
Interfejs CarUiRecyclerView udostępnia interfejsy API umożliwiające dostęp do RecyclerView
dostosowanego za pomocą zasobów car-ui-lib. Na przykład CarUiRecyclerView
sprawdza w czasie działania flagę, 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.xmliMainActivity.java. Możesz utworzyć nową aplikację od podstaw lub zmodyfikować istniejącą. Jeśli zmodyfikujesz istniejącą aplikację, usuń zoverlayable.xmlniezadeklarowane zasoby.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ę ten błąd, który możesz zignorować:
Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerViewJeśli nazwa klasy jest poprawna i
car-ui-libzostała dodana jako zależność, możesz skompilować plik APK. Aby usunąć błąd, wybierz File > Invalidate Caches (Plik > Unieważnij pamięć podręczną), a następnie kliknij Invalidate and Restart (Unieważnij i uruchom ponownie).Dodać te boty do pokoju „
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; }Zbuduj i zainstaluj aplikację jak wcześniej.
Zobaczysz teraz CarUiRecyclerView:
Usuwanie paska przewijania za pomocą RRO
Czas trwania: 10 minut
W tym ćwiczeniu pokazujemy, jak za pomocą nakładki zasobów środowiska wykonawczego usunąć pasek przewijania z CarUiRecyclerView.
W nakładce RRO dodaj i zmodyfikuj te 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_enableto zasóbcar-ui-libtypu logicznego, który określa, czy wCarUiRecyclerViewjest obecny zoptymalizowany pod kątem samochodów pasek przewijania z przyciskami w górę i w dół. Gdy ta opcja jest ustawiona nafalse,CarUiRecyclerViewdział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>
Zbuduj i zainstaluj aplikację jak wcześniej. Pasek przewijania został 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 te pliki w 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 elementu
overlay.xmlw nakładce 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>Warto sprawdzić, jak te pliki ze sobą współpracują.
Dla uproszczenia wymiary i kolory są zakodowane na stałe. Zalecamy jednak deklarowanie tych wartości w
dimens.xmlicolors.xmllub nawet oznaczanie ich jako plików kolorów w folderzeres/color/. Więcej informacji znajdziesz w artykule AOSP Java code style for contributors (w języku angielskim).Zbuduj i zainstaluj aplikację jak wcześniej. Masz już
CarUiRecyclerViewz niebieskim paskiem przewijania i szarymi szynami.
Gratulacje! Obie strzałki pojawiają się u dołu paska przewijania. RRO został zastosowany do pliku zasobu układu car-ui-lib za pomocą systemu kompilacji Gradle w Androidzie Studio.
Elementy listy RRO
Czas trwania: 15 minut
Do tej pory stosowano RRO do car-ui-lib komponentów za pomocą komponentów platformy (nie AndroidX). Aby używać komponentów AndroidX w RRO, musisz dodać zależności tego komponentu zarówno do aplikacji, jak i do RRO.build.gradle. Musisz też dodać attrs tego komponentu do overlayable.xml w aplikacji, a także sample_overlay.xml w RRO.
Nasza biblioteka (car-ui-lib) korzysta z ConstraintLayout oraz innych komponentów AndroidX, więc jej overlayable.xml może wyglądać tak:
<?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
CarUiRecyclerViewza pomocąConstraintLayout. Dodaj lub zmień te pliki w 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.xmlodwołuje się do kilku komponentów lub zasobów, które nie są uwzględnione jako zależności aplikacji. Są to zasobycar-ui-lib. Aby to zrobić, dodajcar-ui-libjako 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.
RRO zastosowaliśmy tylko do car-ui-lib przy użyciu komponentów AndroidXConstraintLayout, gdy jego atrybuty były obecne w car-ui-lib
pliku o nazwie overlayable.xml, a także w RRO sample_overlay.xml. Podobną funkcję możesz dodać do swojej aplikacji. Wystarczy, że dodasz wszystkie odpowiednie attrs do overlayable.xml aplikacji, podobnie jak w przypadku car-ui-lib.
Nie można jednak zastosować RRO do aplikacji korzystającej z komponentów AndroidX, jeśli w build.gradle (gdy aplikacja korzysta z komponentów car-ui-lib) ma ona car-ui-lib jako zależność. Mapowania atrybutów zostały już zdefiniowane w car-ui-lib biblioteki overlayable.xml, więc dodanie ich do overlayable.xml aplikacji z car-ui-lib jako zależności spowoduje błąd mergeDebugResources, taki jak poniżej. Dzieje się tak, ponieważ te atrybuty występują w wielu plikach overlayable.xml:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'