Codelab: צור RRO עם רכיבי car-ui-lib באמצעות מערכת הבנייה Gradle

השתמש בספריית car-ui-lib כדי להשיק מערכות מידע בידור (IVI) עקביות בעצמן, בתוך הרכב. מעבדת קוד זה מציגה לך את car-ui-lib וכיצד אתה יכול להשתמש בשכבות-על של משאבי ריצה (RRO) כדי להתאים אישית רכיבים בספרייה.

מה תלמד

איך ל:

  • כלול רכיבי car-ui-lib באפליקציית Android שלך.
  • השתמש ב-Gradle כדי לבנות אפליקציות Android ו-RROs.
  • השתמש ב-RROs עם car-ui-lib .

מעבד קוד זה אינו מפרט כיצד פועלים RRO. ראה שינוי הערך של משאבי אפליקציה בזמן ריצה ופתרון בעיות בשכבות-על של משאבי זמן ריצה למידע נוסף.

לפני שאתה מתחיל

דרישות מוקדמות

לפני שתתחיל, ודא שיש לך:

צור אפליקציית אנדרואיד חדשה

משך: 15 דקות

בחלק זה, אתה יוצר פרויקט Android Studio חדש.

  1. ב-Android Studio צור אפליקציה עם EmptyActivity .

    צור פעילות ריקה
    איור 1. צור פעילות ריקה
  2. תן שם לאפליקציה CarUiCodelab ולאחר מכן בחר את שפת Java. אתה יכול גם לבחור מיקום קובץ אם תרצה. קבל את ערכי ברירת המחדל עבור שאר ההגדרות.

    תן שם לאפליקציה שלך
    איור 2. תן שם לאפליקציה שלך
  3. החלף את 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 , שאינה מוגדרת.

  4. הוסף את מחרוזת המשאב sample_text והגדר אותה ל-"Hello World!" בקובץ strings.xml שלך. כדי לפתוח קובץ זה, בחר אפליקציה > src > main > res > ערכים > strings.xml .

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiCodelab</string>
        <string name="sample_text">Hello World!</string>
    </resources>
    
  5. כדי לבנות את האפליקציה שלך, לחץ על כפתור ההפעלה הירוק בפינה השמאלית העליונה. פעולה זו תתקין את ה-apk באופן אוטומטי באמולטור או במכשיר האנדרואיד שלך דרך Gradle.

    כפתור הפעלה

האפליקציה החדשה אמורה להיפתח אוטומטית באמולטור או במכשיר האנדרואיד שלך. אם לא, פתח את אפליקציית CarUiCodelab ממפעיל האפליקציות, שמותקן כעת. זה נראה כך:

פתח את אפליקציית CarUiCodelab החדשה
איור 3. פתח את אפליקציית CarUiCodelab החדשה

הוסף את car-ui-lib לאפליקציית Android שלך

משך: 15 דקות

הוסף את car-ui-lib לאפליקציה שלך:

  1. כדי להוסיף את התלות 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'
    }
    

השתמש ברכיבי car-ui-lib באפליקציית Android שלך

עכשיו כשיש לך car-ui-lib , הוסף סרגל כלים לאפליקציה שלך.

  1. בקובץ 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);
    }
    
  2. הקפד לייבא ToolbarController :

    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.toolbar.ToolbarController;
    
  3. כדי להשתמש בערכת הנושא Theme.CarUi.WithToolbar , בחר אפליקציה > src > main > AndroidManifest.xml ולאחר מכן עדכן את AndroidManifest.xml כך שיופיע באופן הבא:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.example.caruicodelab">
    
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.CarUi.WithToolbar"
            tools:targetApi="31">
            <activity
                android:name=".MainActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    
  4. כדי לבנות את האפליקציה, לחץ על כפתור ההפעלה הירוק כמו קודם.

    בנה את האפליקציה

הוסף RROs לאפליקציה שלך

משך: 30 דקות

אם אתה מכיר RROs, עבור לקטע הבא, הוסף בקר הרשאות לאפליקציה שלך . אחרת, כדי ללמוד את היסודות של RROs, ראה שינוי הערך של משאבי אפליקציה בזמן ריצה .

הוסף בקר הרשאות לאפליקציה שלך

כדי לשלוט באילו משאבים שכבות-על של חבילת RRO, הוסף קובץ בשם overlayable.xml לתיקיית /res של האפליקציה שלך. קובץ זה משמש כבקר הרשאות בין האפליקציה שלך ( היעד ) לבין חבילת ה-RRO שלך ( שכבת העל ).

  1. הוסף res/values/overlayable.xml לאפליקציה שלך והעתק את התוכן הבא לקובץ שלך:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <overlayable name="CarUiCodelab">
            <policy type="public">
                <item type="string" name="sample_text"/>
            </policy>
        </overlayable>
    </resources>
    

    מכיוון שהמחרוזת sample_text חייבת להיות ניתנת לכיסוי על ידי RRO, כלול את שם המשאב ב-overlayable.xml של האפליקציה.

    קובץ overlayable.xml שלך חייב להימצא ב- res/values/ . אם לא, ה- OverlayManagerService לא יכול לאתר אותו.

    למידע נוסף על משאבי שכבת-על וכיצד ניתן להגדיר אותם, ראה הגבלת משאבים ניתנים לשכבת-על .

צור חבילת RRO

בסעיף זה, אתה יוצר חבילת RRO כדי לשנות את המחרוזת המוצגת למעלה מ"Hello World!" ל"Hello World RRO".

  1. כדי ליצור פרויקט חדש, בחר קובץ > חדש > פרויקט חדש . הקפד לבחור ללא פעילות במקום פעילות ריקה מכיוון שחבילות RRO מכילות משאבים בלבד.

    התצורות שלך מופיעות בדומה לאלו המוצגות להלן. המיקום שאליו הם נשמרים עשוי להיות שונה:

  2. לאחר יצירת פרויקט CarUiRRO החדש, הכריז על הפרויקט כ-RRO על ידי שינוי AndroidManifest.xml .

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.caruirro">
    
        <application android:hasCode="false" />
    
        <uses-sdk
            android:minSdkVersion="29"
            android:targetSdkVersion="29"/>
    
        <overlay
            android:targetPackage="com.example.caruicodelab"
            android:targetName="CarUiCodelab"
            android:isStatic="false"
            android:resourcesMap="@xml/sample_overlay"
            />
    </manifest>
    

    פעולה זו יוצרת שגיאה עם @xml/sample_overlay . קובץ resourcesMap ממפה שמות משאבים מחבילת היעד לחבילת RRO.

  3. העתק את גוש הקוד הבא אל …/res/xml/sample_overlay.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="string/sample_text" value="@string/sample_text"/>
    </overlay>
    
  4. הוסף sample_text אל …/res/values/strings.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">CarUiRRO</string>
        <string name="sample_text">Hello World RRO</string>
    </resources>
    
    יצר את מבנה Gradle של RRO
  5. כדי לבנות את יעד ה-RRO שלך, לחץ על כפתור ההפעלה הירוק כדי ליצור מבנה Gradle של ה-RRO שלך באמולטור או במכשיר האנדרואיד שלך.

  6. כדי לוודא שה-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 שלך מכיל שגיאות, ראה פתרון בעיות בשכבות-על של משאבי זמן ריצה לפני שתמשיך.

  7. כדי להפעיל את ה-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!
איור 4 : Hello World RRO!

מזל טוב! יצרת את ה-RRO הראשון שלך.

בעת שימוש ב-RROs, ייתכן שתרצה להשתמש בדגלי Android Asset Packaging Tool (AAPT2) --no-resource-deduping ו-- --no-resource-removal המתוארים באפשרויות קישור . אין צורך להוסיף את הדגלים במעבדת קוד זה, אך אנו ממליצים להשתמש בהם ב-RROs שלך כדי למנוע הסרה של משאבים (וכאבי ראש באגים). אתה יכול להוסיף אותם לקובץ build.gradle של ה-RRO שלך כך:

android {
    …
    aaptOptions {
        additionalParameters "--no-resource-deduping", "--no-resource-removal"
    }
}

למידע נוסף על דגלים אלה, ראה בניית החבילה ו- AAPT2 .

שנה רכיבי car-ui-lib באמצעות RROs באפליקציית Android שלך

דף זה מתאר כיצד אתה יכול להשתמש בשכבת-על של משאבי ריצה (RRO) כדי לשנות רכיבים מספריית car-ui-lib באפליקציית Android שלך.

הגדר את צבע הרקע של סרגל הכלים

משך: 15 דקות

כדי לשנות את צבע הרקע של סרגל הכלים:

  1. הוסף את הערך הבא לאפליקציית RRO שלך, והגדר את המשאב לירוק בהיר ( #0F0 ):

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <drawable name="car_ui_toolbar_background">#0F0</drawable>
    </resources>
    

    ספריית car-ui-lib מכילה משאב בשם car_ui_toolbar_background . כאשר משאב זה כלול בתצורה של RRO, סרגל הכלים אינו משתנה מכיוון שהערך השגוי ממוקד.

  2. ב- AndroidManifest.xml עבור ה-RRO שלך, עדכן את targetName כך שיצביע על car-ui-lib :

    …
    android:targetName="car-ui-lib"
    …
    

    עליך ליצור חבילת RRO חדשה עבור כל חבילת יעד שברצונך לבצע RRO. לדוגמה, בעת יצירת שכבות-על עבור שני יעדים שונים, עליך ליצור שני אפקסים של שכבת-על.

  3. בנה, אמת, התקן והפעל את ה-RRO באותו אופן כמו קודם.

האפליקציה שלך מופיעה כך:

צבע רקע חדש של סרגל הכלים
איור 5 : צבע רקע חדש של סרגל הכלים

פריסות וסגנונות RRO

משך: 15 דקות

בתרגיל זה אתה בונה אפליקציה חדשה בדומה לאפליקציה שבנית קודם לכן. אפליקציה זו מאפשרת שכבת-על של הפריסה. בצע את אותם השלבים כמו קודם, או שנה את האפליקציה הקיימת שלך.

  1. הקפד להוסיף את השורות הבאות ל- 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>
    
  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>
    
  3. באפליקציית RRO שלך, צור res/layout/activity_main.xml והוסף את הדברים הבאים:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
      <TextView
          android:id="@+id/textView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/sample_text"
          android:textAppearance="@style/TextAppearance.CarUi"
          android:layout_gravity="center_vertical|center_horizontal"/>
    </FrameLayout>
    
  4. עדכן את res/values/styles.xml כדי להוסיף את הסגנון שלנו ל-RRO:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="TextAppearance.CarUi" parent="android:TextAppearance.DeviceDefault">
            <item name="android:textColor">#0f0</item>
            <item name="android:textSize">100sp</item>
        </style>
    </resources>
    
  5. שנה את targetName ב- AndroidManifest.xml כדי להצביע על שם האפליקציה החדשה שלך:

    …
    android:targetName="CarUiCodelab"
    …
    
  6. הוסף את המשאבים לקובץ sample_overlay.xml ב-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>
    
  7. בנה והתקן את האפליקציה וה-RRO באותו אופן כמו קודם (לחצן הפעלה ירוק). הקפד להפעיל את ה-RRO שלך.

האפליקציה וה-RRO מוצגים כדלקמן. הטקסט Hello World RRO הוא ירוק וממורכז כפי שצוין בפריסה RRO.

שלום עולם RRO
איור 6 : Hello World RRO

הוסף את CarUiRecyclerView לאפליקציה שלך

משך: 15 דקות

ממשק CarUiRecyclerView מספק ממשקי API לגישה ל- RecyclerView המותאם אישית באמצעות משאבי car-ui-lib . לדוגמה, CarUiRecyclerView בודק דגל בזמן ריצה כדי לקבוע אם יש להפעיל את פס הגלילה או לא ובוחר את הפריסה המתאימה.

CarUiRecyclerViewContainer
איור 7. CarUiRecyclerViewContainer
  1. כדי להוסיף CarUiRecyclerView , הוסף אותו לקבצי activity_main.xml ו- MainActivity.java שלך. אתה יכול ליצור אפליקציה חדשה מאפס או לשנות את האפליקציה הקיימת. אם תשנה את האפליקציה הקיימת, הקפד להסיר משאבים לא מוכרזים מ- overlayable.xml .

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <com.android.car.ui.recyclerview.CarUiRecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    

    עלולה להופיע השגיאה הבאה, שתוכל להתעלם ממנה:

    Cannot resolve class com.android.car.ui.recyclerview.CarUiRecyclerView

    כל עוד הכיתה שלך מאויתת נכון והוספת car-ui-lib כתלות, אתה יכול לבנות ולהרכיב את ה-apk שלך. כדי להסיר את השגיאה, בחר File > Invalidate Caches ולאחר מכן לחץ על Invalidate and Restart.

    הוסף את הדברים הבאים ל- MainActivity.java

    package com.example.caruicodelab;
    
    import android.app.Activity;
    import android.os.Bundle;
    import com.android.car.ui.core.CarUi;
    import com.android.car.ui.recyclerview.CarUiContentListItem;
    import com.android.car.ui.recyclerview.CarUiListItem;
    import com.android.car.ui.recyclerview.CarUiListItemAdapter;
    import com.android.car.ui.recyclerview.CarUiRecyclerView;
    import com.android.car.ui.toolbar.ToolbarController;
    import java.util.ArrayList;
    
    /** Activity with a simple car-ui layout. */
    public class MainActivity extends Activity {
    
        private final ArrayList<CarUiListItem> mData = new ArrayList<>();
        private CarUiListItemAdapter mAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ToolbarController toolbar = CarUi.getToolbar(this);
            toolbar.setTitle(getTitle());
            toolbar.setLogo(R.mipmap.ic_launcher_round);
    
            CarUiRecyclerView recyclerView = findViewById(R.id.list);
            mAdapter = new CarUiListItemAdapter(generateSampleData());
            recyclerView.setAdapter(mAdapter);
        }
    
        private ArrayList<CarUiListItem> generateSampleData() {
            for (int i = 0; i < 20; i++) {
                CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.ICON);
                item.setTitle("Title " + i);
                item.setPrimaryIconType(CarUiContentListItem.IconType.CONTENT);
                item.setIcon(getDrawable(R.drawable.ic_launcher_foreground));
                item.setBody("body " + i);
                mData.add(item);
            }
            return mData;
    }
    
  2. בנה והתקן את האפליקציה שלך כמו קודם.

כעת אתה רואה CarUiRecyclerView :

CarUiRecyclerView
איור 7 : CarUiRecyclerView

השתמש ב-RRO כדי להסיר את פס הגלילה

משך: 10 דקות

תרגיל זה מראה לך כיצד להשתמש ב-RRO כדי להסיר את פס הגלילה מ- CarUiRecyclerView .

  1. ב-RRO שלך, הוסף ושנה את הקבצים הבאים:

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.caruirro">
    
        <application android:hasCode="false" />
    
        <uses-sdk
            android:minSdkVersion="29"
            android:targetSdkVersion="29"/>
    
        <overlay
            android:targetPackage="com.example.caruicodelab"
            android:targetName="car-ui-lib"
            android:isStatic="false"
            android:resourcesMap="@xml/sample_overlay"
            />
    </manifest>
    

    res/values/bools.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <bool name="car_ui_scrollbar_enable">false</bool>
    </resources>
    

    המשאב car_ui_scrollbar_enable הוא משאב בוליאני car-ui-lib , השולט אם פס הגלילה המותאם לרכב עם לחצני למעלה ולמטה ב- CarUiRecyclerView קיים או לא. כאשר מוגדר כ- false , CarUiRecyclerView פועל כמו AndroidX RecyclerView .

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
        <item target="bool/car_ui_scrollbar_enable" value="@bool/car_ui_scrollbar_enable"/>
    </overlay>
    

בנה והתקן את האפליקציה שלך כמו קודם. סרגל הגלילה הוסר כעת מ- CarUiRecyclerView :

CarUiRecyclerView ללא פס גלילה
איור 8. CarUiRecyclerView ללא פס גלילה

השתמש בפריסה כדי לשכב על פס הגלילה של CarUiRecyclerView

משך: 15 דקות

בתרגיל זה, אתה משנה את פריסת פס הגלילה CarUiRecyclerView .

  1. הוסף ושנה את הקבצים הבאים באפליקציית 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>
    

    כדי לשכב על קובץ פריסה, עליך להוסיף את כל המזהים ומאפייני מרחב השמות ל- overlay.xml של ה-RRO שלך. ראה את הקבצים למטה.

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
       <item target="drawable/car_ui_recyclerview_ic_down" value="@drawable/car_ui_recyclerview_ic_down"/>
       <item target="drawable/car_ui_recyclerview_ic_up" value="@drawable/car_ui_recyclerview_ic_up"/>
       <item target="drawable/car_ui_recyclerview_scrollbar_thumb" value="@drawable/car_ui_recyclerview_scrollbar_thumb"/>
       <item target="id/car_ui_scroll_bar" value="@id/car_ui_scroll_bar"/>
       <item target="id/car_ui_scrollbar_thumb" value="@id/car_ui_scrollbar_thumb"/>
       <item target="id/car_ui_scrollbar_track" value="@id/car_ui_scrollbar_track"/>
       <item target="id/car_ui_scrollbar_page_up" value="@id/car_ui_scrollbar_page_up"/>
       <item target="id/car_ui_scrollbar_page_down" value="@id/car_ui_scrollbar_page_down"/>
       <item target="layout/car_ui_recyclerview_scrollbar" value="@layout/car_ui_recyclerview_scrollbar"/>
    </overlay>
    

    res/drawable/car_ui_recyclerview_ic_up.xml

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="48.0"
        android:viewportHeight="48.0">
        <path
            android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z"
            android:fillColor="#0000FF"/>
    </vector>
    

    res/drawable/car_ui_recyclerview_ic_down.xml

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="48.0"
        android:viewportHeight="48.0">
        <path
            android:pathData="M14.83,16.42L24,25.59l9.17,-9.17L36,19.25l-12,12 -12,-12z"
            android:fillColor="#0000FF"/>
    </vector>
    

    res/drawable/car_ui_recyclerview_scrollbar_thumb.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <solid android:color="#0000FF" />
        <corners android:radius="100dp"/>
    </shape>
    

    מוצע לבחון כיצד קבצים אלה מתקשרים.

    למען הפשטות, מידות וצבעים מקודדים בצורה קשיחה. עם זאת, שיטה מומלצת היא להכריז על ערכים אלה ב- dimens.xml ו- colors.xml או אפילו מוגדרים כקובצי צבע בתיקיה res/color/ . למידע נוסף, ראה סגנון קוד Java של AOSP לתורמים .

  2. בנה והתקן את האפליקציה שלך כמו קודם. בנית את CarUiRecyclerView עם פס גלילה כחול ומסילות אפורות.

מזל טוב! שני החצים מופיעים לאורך החלק התחתון של סרגל הגלילה, החלת בהצלחה RRO על קובץ משאבים של פריסת car-ui-lib באמצעות מערכת הבנייה Gradle דרך Android Studio.

CarUiRecyclerView עם פס גלילה כחול עם מסילות אפורות
איור 9. CarUiRecyclerView עם פס גלילה כחול עם מסילות אפורות

RRO רשימת פריטים

משך: 15 דקות

עד לנקודה זו, החלת RRO על רכיבי car-ui-lib באמצעות רכיבי מסגרת (לא AndroidX). כדי להשתמש ברכיבי AndroidX ב-RRO, עליך להוסיף את התלות של רכיב זה הן לאפליקציה והן ל-RRO build.gradle. עליך להוסיף גם את attrs של הרכיב הזה ל- overlayable.xml באפליקציה שלך, כמו גם את sample_overlay.xml ב-RRO שלך.

הספרייה שלנו ( car-ui-lib ) משתמשת ConstraintLayout כמו גם ברכיבי AndroidX אחרים, כך שה- overlayable.xml שלה עשוי להיראות כך:

<?xml version='1.0' encoding='UTF-8'?>
<resources>
    <overlayable name="car-ui-lib">
        …
        <item type="attr" name="layout_constraintBottom_toBottomOf"/>
        <item type="attr" name="layout_constraintBottom_toTopOf"/>
        <item type="attr" name="layout_constraintCircle"/>
        <item type="attr" name="layout_constraintCircleAngle"/>
        <item type="attr" name="layout_constraintCircleRadius"/>
        <item type="attr" name="layout_constraintDimensionRatio"/>
        <item type="attr" name="layout_constraintEnd_toEndOf"/>
        <item type="attr" name="layout_constraintEnd_toStartOf"/>
        <item type="attr" name="layout_constraintGuide_begin"/>
        <item type="attr" name="layout_constraintGuide_end"/>
        <item type="attr" name="layout_constraintGuide_percent"/>
        <item type="attr" name="layout_constraintHeight_default"/>
        <item type="attr" name="layout_constraintHeight_max"/>
        <item type="attr" name="layout_constraintHeight_min"/>
        <item type="attr" name="layout_constraintHeight_percent"/>
        <item type="attr" name="layout_constraintHorizontal_bias"/>
        <item type="attr" name="layout_constraintHorizontal_chainStyle"/>
        <item type="attr" name="layout_constraintHorizontal_weight"/>
        <item type="attr" name="layout_constraintLeft_creator"/>
        <item type="attr" name="layout_constraintLeft_toLeftOf"/>
        <item type="attr" name="layout_constraintLeft_toRightOf"/>
        <item type="attr" name="layout_constraintRight_creator"/>
        <item type="attr" name="layout_constraintRight_toLeftOf"/>
        <item type="attr" name="layout_constraintRight_toRightOf"/>
        <item type="attr" name="layout_constraintStart_toEndOf"/>
        <item type="attr" name="layout_constraintStart_toStartOf"/>
        <item type="attr" name="layout_constraintTag"/>
        <item type="attr" name="layout_constraintTop_creator"/>
        <item type="attr" name="layout_constraintTop_toBottomOf"/>
        <item type="attr" name="layout_constraintTop_toTopOf"/>
        <item type="attr" name="layout_constraintVertical_bias"/>
        <item type="attr" name="layout_constraintVertical_chainStyle"/>
        …
    </overlayable>
</resources>
  1. שנה את הפריסה של פריטי הרשימה ב- CarUiRecyclerView באמצעות ConstraintLayout . הוסף או שנה את הקבצים הבאים ב-RRO שלך:

    res/xml/sample_overlay.xml

    <?xml version="1.0" encoding="utf-8"?>
    <overlay>
       <item target="id/car_ui_list_item_touch_interceptor" value="@id/car_ui_list_item_touch_interceptor"/>
       <item target="id/car_ui_list_item_reduced_touch_interceptor" value="@id/car_ui_list_item_reduced_touch_interceptor"/>
       <item target="id/car_ui_list_item_start_guideline" value="@id/car_ui_list_item_start_guideline"/>
       <item target="id/car_ui_list_item_icon_container" value="@id/car_ui_list_item_icon_container"/>
       <item target="id/car_ui_list_item_icon" value="@id/car_ui_list_item_icon"/>
       <item target="id/car_ui_list_item_content_icon" value="@id/car_ui_list_item_content_icon"/>
       <item target="id/car_ui_list_item_avatar_icon" value="@id/car_ui_list_item_avatar_icon"/>
       <item target="id/car_ui_list_item_title" value="@id/car_ui_list_item_title"/>
       <item target="id/car_ui_list_item_body" value="@id/car_ui_list_item_body"/>
       <item target="id/car_ui_list_item_action_container_touch_interceptor" value="@id/car_ui_list_item_action_container_touch_interceptor"/>
       <item target="id/car_ui_list_item_action_container" value="@id/car_ui_list_item_action_container"/>
       <item target="id/car_ui_list_item_action_divider" value="@id/car_ui_list_item_action_divider"/>
       <item target="id/car_ui_list_item_switch_widget" value="@id/car_ui_list_item_switch_widget"/>
       <item target="id/car_ui_list_item_checkbox_widget" value="@id/car_ui_list_item_checkbox_widget"/>
       <item target="id/car_ui_list_item_radio_button_widget" value="@id/car_ui_list_item_radio_button_widget"/>
       <item target="id/car_ui_list_item_supplemental_icon" value="@id/car_ui_list_item_supplemental_icon"/>
       <item target="id/car_ui_list_item_end_guideline" value="@id/car_ui_list_item_end_guideline"/>
       <item target="attr/layout_constraintBottom_toBottomOf" value="@attr/layout_constraintBottom_toBottomOf"/>
       <item target="attr/layout_constraintBottom_toTopOf" value="@attr/layout_constraintBottom_toTopOf"/>
       <item target="attr/layout_constraintEnd_toEndOf" value="@attr/layout_constraintEnd_toEndOf"/>
       <item target="attr/layout_constraintEnd_toStartOf" value="@attr/layout_constraintEnd_toStartOf"/>
       <item target="attr/layout_constraintGuide_begin" value="@attr/layout_constraintGuide_begin"/>
       <item target="attr/layout_constraintGuide_end" value="@attr/layout_constraintGuide_end"/>
       <item target="attr/layout_constraintHorizontal_bias" value="@attr/layout_constraintHorizontal_bias"/>
       <item target="attr/layout_constraintLeft_toLeftOf" value="@attr/layout_constraintLeft_toLeftOf"/>
       <item target="attr/layout_constraintLeft_toRightOf" value="@attr/layout_constraintLeft_toRightOf"/>
       <item target="attr/layout_constraintRight_toLeftOf" value="@attr/layout_constraintRight_toLeftOf"/>
       <item target="attr/layout_constraintRight_toRightOf" value="@attr/layout_constraintRight_toRightOf"/>
       <item target="attr/layout_constraintStart_toEndOf" value="@attr/layout_constraintStart_toEndOf"/>
       <item target="attr/layout_constraintStart_toStartOf" value="@attr/layout_constraintStart_toStartOf"/>
       <item target="attr/layout_constraintTop_toBottomOf" value="@attr/layout_constraintTop_toBottomOf"/>
       <item target="attr/layout_constraintTop_toTopOf" value="@attr/layout_constraintTop_toTopOf"/>
       <item target="attr/layout_goneMarginBottom" value="@attr/layout_goneMarginBottom"/>
       <item target="attr/layout_goneMarginEnd" value="@attr/layout_goneMarginEnd"/>
       <item target="attr/layout_goneMarginLeft" value="@attr/layout_goneMarginLeft"/>
       <item target="attr/layout_goneMarginRight" value="@attr/layout_goneMarginRight"/>
       <item target="attr/layout_goneMarginStart" value="@attr/layout_goneMarginStart"/>
       <item target="attr/layout_goneMarginTop" value="@attr/layout_goneMarginTop"/>
       <item target="attr/layout_constraintVertical_chainStyle" value="@attr/layout_constraintVertical_chainStyle"/>
       <item target="layout/car_ui_list_item" value="@layout/car_ui_list_item"/>
    </overlay>
    

    res/layout/car_ui_list_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:tag="carUiListItem"
        android:minHeight="@dimen/car_ui_list_item_height">
    
        <!-- The following touch interceptor views are sized to encompass the specific sub-sections of
        the list item view to easily control the bounds of a background ripple effects. -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <!-- This touch interceptor does not include the action container -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_reduced_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/car_ui_list_item_action_container"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/car_ui_list_item_start_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="@dimen/car_ui_list_item_start_inset" />
    
        <FrameLayout
            android:id="@+id/car_ui_list_item_icon_container"
            android:layout_width="@dimen/car_ui_list_item_icon_container_width"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="@+id/car_ui_list_item_start_guideline"
            app:layout_constraintTop_toTopOf="parent">
    
            <ImageView
                android:id="@+id/car_ui_list_item_icon"
                android:layout_width="@dimen/car_ui_list_item_icon_size"
                android:layout_height="@dimen/car_ui_list_item_icon_size"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_content_icon"
                android:layout_width="@dimen/car_ui_list_item_content_icon_width"
                android:layout_height="@dimen/car_ui_list_item_content_icon_height"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_avatar_icon"
                android:background="@drawable/car_ui_list_item_avatar_icon_outline"
                android:layout_width="@dimen/car_ui_list_item_avatar_icon_width"
                android:layout_height="@dimen/car_ui_list_item_avatar_icon_height"
                android:layout_gravity="center"
                android:visibility="gone"
                android:scaleType="fitCenter" />
        </FrameLayout>
    
        <CarUiTextView
            android:id="@+id/car_ui_list_item_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
            android:singleLine="@bool/car_ui_list_item_single_line_title"
            android:textAppearance="@style/TextAppearance.CarUi.ListItem"
            android:layout_gravity="right"
            android:gravity="right"
            android:textAlignment="viewEnd"
            app:layout_constraintBottom_toTopOf="@+id/car_ui_list_item_body"
            app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container"
            app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
        <CarUiTextView
            android:id="@+id/car_ui_list_item_body"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/car_ui_list_item_text_start_margin"
            android:textAppearance="@style/TextAppearance.CarUi.ListItem.Body"
            android:layout_gravity="right"
            android:gravity="right"
            android:textAlignment="viewEnd"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/car_ui_list_item_action_container"
            app:layout_constraintStart_toEndOf="@+id/car_ui_list_item_icon_container"
            app:layout_constraintTop_toBottomOf="@+id/car_ui_list_item_title"
            app:layout_goneMarginStart="@dimen/car_ui_list_item_text_no_icon_start_margin" />
    
        <!-- This touch interceptor is sized and positioned to encompass the action container   -->
        <com.android.car.ui.SecureView
            android:id="@+id/car_ui_list_item_action_container_touch_interceptor"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@drawable/car_ui_list_item_background"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="@id/car_ui_list_item_action_container"
            app:layout_constraintEnd_toEndOf="@id/car_ui_list_item_action_container"
            app:layout_constraintStart_toStartOf="@id/car_ui_list_item_action_container"
            app:layout_constraintTop_toTopOf="@id/car_ui_list_item_action_container" />
    
        <FrameLayout
            android:id="@+id/car_ui_list_item_action_container"
            android:layout_width="wrap_content"
            android:minWidth="@dimen/car_ui_list_item_icon_container_width"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@+id/car_ui_list_item_end_guideline"
            app:layout_constraintTop_toTopOf="parent">
    
            <View
                android:id="@+id/car_ui_list_item_action_divider"
                android:layout_width="@dimen/car_ui_list_item_action_divider_width"
                android:layout_height="@dimen/car_ui_list_item_action_divider_height"
                android:layout_gravity="start|center_vertical"
                android:background="@drawable/car_ui_list_item_divider" />
    
            <Switch
                android:id="@+id/car_ui_list_item_switch_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <CheckBox
                android:id="@+id/car_ui_list_item_checkbox_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <RadioButton
                android:id="@+id/car_ui_list_item_radio_button_widget"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:clickable="false"
                android:focusable="false" />
    
            <ImageView
                android:id="@+id/car_ui_list_item_supplemental_icon"
                android:layout_width="@dimen/car_ui_list_item_supplemental_icon_size"
                android:layout_height="@dimen/car_ui_list_item_supplemental_icon_size"
                android:layout_gravity="center"
                android:scaleType="fitCenter" />
        </FrameLayout>
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/car_ui_list_item_end_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="@dimen/car_ui_list_item_end_inset" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. car_ui_list_item.xml מפנה למספר הפניות למספר רכיבים/משאבים שאינם כלולים כתלות באפליקציה. אלו משאבי car-ui-lib . אתה יכול לתקן זאת על ידי הוספת car-ui-lib כתלות באפליקציית RRO שלך ב- 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'
    }
    

הכותרת והגוף מיושרים כעת לימין במקום מיושרים לשמאל.

כותרת וגוף מיושרים לימין
איור 10. כותרת וגוף מיושרים לימין

החלנו RRO על car-ui-lib רק באמצעות רכיבי AndroidX ( ConstraintLayout ) כאשר התכונות שלו היו קיימות בקובץ car-ui-lib בשם overlayable.xml וכן ב-RRO sample_overlay.xml . אפשר לעשות משהו דומה באפליקציה משלך. פשוט הוסף את כל attrs המתאימות overlayable.xml של האפליקציה שלך, בדומה ל- car-ui-lib .

עם זאת, לא ניתן לבצע RRO אפליקציה באמצעות רכיבי AndroidX כאשר לאפליקציה יש car-ui-lib כתלות ב- build.gradle שלה (כאשר האפליקציה משתמשת ברכיבי car-ui-lib ). מכיוון שמיפוי המאפיינים כבר הוגדרו בספריית car-ui-lib overlayable.xml , הוספתם ל- overlayable.xml של האפליקציה שלך עם car-ui-lib כתלות תגרום לשגיאה של mergeDebugResources כמו זו למטה. הסיבה לכך היא שתכונות אלה קיימות במספר קובצי overlayable.xml :

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugResources'