تطوير التطبيقات

المواد التالية مخصّصة لمطوّري التطبيقات.

لإتاحة استخدام التطبيق بشكل منتظم، يجب:

  1. ضَع "FocusParkingView" في تنسيق النشاط المعنيّ.
  2. التأكّد من أنّ المشاهدات التي يمكن التركيز عليها (أو التي لا يمكن التركيز عليها)
  3. استخدِم FocusArea للالتفاف حول كل العروض القابلة للتركيز، باستثناء FocusParkingView

يتم تفصيل كل من هذه المهام أدناه، بعد إعداد بيئتك من أجل تطوير التطبيقات التي تتيح وحدة تحكُّم دورانية.

إعداد وحدة تحكّم دوّارة

قبل أن تتمكّن من البدء في تطوير التطبيقات التي تستخدم دوّارًا، يجب استخدام وحدة تحكّم دوّارة أو احتياطي. تتوفر لك الخيارات الموضحة أدناه.

المحاكي

source build/envsetup.sh && lunch car_x86_64-userdebug
m -j
emulator -wipe-data -no-snapshot -writable-system

ويمكنك أيضًا استخدام aosp_car_x86_64-userdebug.

للوصول إلى وحدة التحكّم الدوّارة التي تمّت محاكاتها:

  1. انقر على النقاط الثلاث أسفل شريط الأدوات:

    الوصول إلى وحدة التحكّم الدوارة التي يمكن محاكاتها
    الشكل 1. الوصول إلى وحدة التحكّم الدوّارة التي تتم محاكاتها
  2. اختَر دوّارة سيارة في نافذة عناصر التحكّم الموسّعة:

    اختيار وحدة تدوير للسيارة
    الشكل 2. اختيار كرسي دوار للسيارة

لوحة مفاتيح USB

  • عليك توصيل لوحة مفاتيح USB بجهازك الذي يعمل بنظام التشغيل Android Automotive (AAOS). في بعض الحالات، يمنع هذا الإجراء ظهور لوحة المفاتيح على الشاشة.
  • يجب استخدام الإصدار userdebug أو eng.
  • تفعيل فلترة الأحداث الرئيسية:
    adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
    
  • انظر الجدول أدناه للعثور على المفتاح المقابل لكل إجراء:
    المفتاح وظيفة دورانية
    Q تدوير عكس عقارب الساعة
    E تدوير في اتجاه عقارب الساعة
    A دفع إلى اليسار
    D دفع لليمين
    W دفع لأعلى
    S دفع إلى الأسفل
    F أو فاصلة الزر الأوسط
    R أو Esc زر الرجوع

أوامر ADB

يمكنك استخدام أوامر car_service لإدخال أحداث الإدخال باستخدام وحدة تحكُّم دورانية. وهذه الأوامر يمكن تشغيلها على الأجهزة التي تعمل بنظام التشغيل Android Automotive (AAOS) أو على محاكي.

أوامر Car_service إدخال البيانات عبر وحدة تحكُّم دورانية
adb shell cmd car_service inject-rotary تدوير عكس عقارب الساعة
adb shell cmd car_service inject-rotary -c true تدوير في اتجاه عقارب الساعة
adb shell cmd car_service inject-rotary -dt 100 50 تدوير عدة مرات عكس اتجاه عقارب الساعة (قبل 100 ملي ثانية و50 ملي ثانية)
adb shell cmd car_service inject-key 282 دفع إلى اليسار
adb shell cmd car_service inject-key 283 دفع لليمين
adb shell cmd car_service inject-key 280 دفع لأعلى
adb shell cmd car_service inject-key 281 دفع إلى الأسفل
adb shell cmd car_service inject-key 23 النقر على الزر الأوسط
adb shell input keyevent inject-key 4 النقر على زر الرجوع

وحدة تحكّم دوّارة للمصنّع الأصلي للجهاز

عندما تكون وحدة التحكم الدوارة قيد التشغيل، فهذه هي واقعيًا. وهو مفيد بشكل خاص لاختبار الدوران السريع.

عرض التركيز في موقف السيارات

FocusParkingView هو عرض شفاف في مكتبة واجهة مستخدم السيارة (car-ui-library). تستخدِمه خدمة RotaryService لإتاحة التنقّل باستخدام وحدة التحكّم الدوّارة. يجب أن يكون FocusParkingView هو العرض الأول القابل للتركيز في التخطيط. يجب وضعه خارج جميع FocusArea. يجب أن تحتوي كل نافذة على علامة FocusParkingView إذا كنت تستخدم بالفعل التخطيط الأساسي لمكتبة السيارة، الذي يحتوي على FocusParkingView، لا حاجة إلى إضافة علامة أخرى. FocusParkingView يظهر أدناه مثال على FocusParkingView في RotaryPlayground

<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <com.android.car.ui.FocusParkingView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
   <FrameLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
</FrameLayout>

في ما يلي أسباب احتياجك إلى FocusParkingView:

  1. لا يمحو Android التركيز تلقائيًا عند ضبط التركيز في نافذة أخرى. إذا كنت حاول إزالة التركيز في النافذة السابقة، سيعيد Android تركيز طريقة العرض في تلك النافذة، يؤدي إلى التركيز على نافذتين في وقت واحد. جارٍ إضافة FocusParkingView مع كل نافذة إلى حل هذه المشكلة. طريقة العرض هذه شفافة وإبراز تركيزها التلقائي. ويتم إيقافه، حتى لا يظهر للمستخدم سواء تم التركيز عليه أم لا. بإمكان "RotaryService" التركيز على الفيديو ليتمكّن "RotaryService" من إيقاف التركيز عليه. لإزالة تمييز التركيز.
  2. في حال وجود FocusArea واحد فقط في النافذة الحالية، يؤدي ذلك إلى تدوير وحدة التحكّم. في FocusArea إلى نقل التركيز من خلال RotaryService من العرض على اليمين إلى العرض على اليسار (والعكس صحيح). جارٍ إضافة هذا العرض إلى كل نافذة إلى حل المشكلة. عندما يتم تحديد التركيز من قِبل "RotaryService" هو FocusParkingView، فيمكن أن يحدد الالتفاف المرصود وعند هذه النقطة، يتم تجنب الالتفاف من خلال عدم تحريك التركيز.
  3. عندما يشغِّل عنصر التحكّم الدوار أحد التطبيقات، يركّز Android على أول عرض يمكن التركيز عليه، وهو دائمًا FocusParkingView. FocusParkingView ويحدد العرض الأمثل للتركيز عليه ثم يطبق التركيز.

طرق العرض التي يمكن التركيز عليها

يعتمد RotaryService على إطار عمل Android الحالي مفهوم تركيز الرؤية، يعود تاريخه إلى الوقت الذي كانت فيه الهواتف مزودة بلوحات مفاتيح خارجية ولوحات D. تمّت إعادة استخدام سمة android:nextFocusForward الحالية كوحدة تحكّم دورانية. (يُرجى الاطّلاع على تخصيص FocusArea)، ولكن android:nextFocusLeft، android:nextFocusRight، android:nextFocusUp وandroid:nextFocusDown ليسا كذلك.

يركّز RotaryService فقط على المشاهدات التي يمكن التركيز عليها. تتميز بعض طرق العرض مثل Button يمكن التركيز عليها عادةً. سمات أخرى، مثل TextView وViewGroup عادةً لا يتم ذلك. يمكن التركيز تلقائيًا على مرات العرض القابلة للنقر، ويتم تلقائيًا قابل للنقر عندما يكون لديهم مستمع للنقرة. إذا نتج عن هذا المنطق التلقائي البيانات لن تحتاج إلى ضبط قابلية التركيز في العرض بشكل صريح. إذا لم يكن المنطق التلقائي إلى إمكانية التركيز المطلوبة، اضبط السمة android:focusable على true أو false، أو ضبط إمكانية تركيز العرض آليًا باستخدام View.setFocusable(boolean) لكي يتمكن RotaryService من التركيز عليه، يجب أن استيفاء المتطلبات التالية:

  • يمكن التركيز عليه
  • مفعّلة
  • المراجعات المعروضة
  • أن تشتمل على قيم غير صفرية للعرض والارتفاع

إذا كانت طريقة العرض لا تستوفي كل هذه المتطلبات، مثل زر يمكن التركيز عليه ولكنه غير مفعّل، لا يمكن للمستخدم استخدام التحكم الدوار للتركيز عليها. إذا كنت تريد التركيز على طرق العرض غير المفعّلة، ننصحك باستخدام حالة مخصّصة بدلاً من android:state_enabled للتحكّم في كيفية بدون الإشارة إلى أنّ نظام التشغيل Android يجب أن يعتبره غير مفعّل. يمكن لتطبيقك إبلاغ المستخدم بسبب تعطيل العرض عند النقر عليه. ويوضّح القسم التالي كيفية إجراء ذلك.

حالة مخصَّصة

لإضافة حالة مخصّصة:

  1. لإضافة سمة مخصّصة على طريقة العرض على سبيل المثال، لإضافة حالة state_rotary_enabled مخصّصة إلى صف واحد (CustomView) لعرض الصف، استخدام:
    <declare-styleable name="CustomView">
        <attr name="state_rotary_enabled" format="boolean" />
    </declare-styleable>
    
  2. لتتبع هذه الحالة، أضف متغير مثيل إلى العرض مع طرق الموصّل:
    private boolean mRotaryEnabled;
    public boolean getRotaryEnabled() { return mRotaryEnabled; }
    public void setRotaryEnabled(boolean rotaryEnabled) {
        mRotaryEnabled = rotaryEnabled;
    }
    
  3. لقراءة قيمة السمة عند إنشاء طريقة العرض:
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
    mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
    
  4. في فئة العرض، يمكنك إلغاء طريقة onCreateDrawableState()، ثم وإضافة الحالة المخصصة، عندما يكون ذلك مناسبًا. مثل:
    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mRotaryEnabled) extraSpace++;
        int[] drawableState = super.onCreateDrawableState(extraSpace);
        if (mRotaryEnabled) {
            mergeDrawableStates(drawableState, { R.attr.state_rotary_enabled });
        }
        return drawableState;
    }
    
  5. ضبط أداء معالج النقرات في طريقة العرض بشكل مختلف حسب حالته على سبيل المثال، قد لا يفعل معالج النقرات أي شيء أو قد ينبثق عندما تم false ميزة mRotaryEnabled.
  6. لجعل الزر يبدو غير مفعّل، استخدِم إمكانية رسم خلفية العرض في app:state_rotary_enabled بدلاً من android:state_enabled وإذا لم يكن متوفّرًا لديك من قبل، عليك إضافة ما يلي:
    xmlns:app="http://schemas.android.com/apk/res-auto"
    
  7. إذا تم إيقاف العرض في أي تنسيقات، استبدِل android:enabled="false" بـ app:state_rotary_enabled="false" ثم أضِف مساحة الاسم app على النحو الوارد أعلاه.
  8. إذا كان العرض غير مفعَّل آليًا، يمكنك استبدال المكالمات إلى setEnabled(). مع مكالمات إلى setRotaryEnabled().

منطقة التركيز

استخدِم "FocusAreas" لتقسيم طرق العرض التي يمكن التركيز عليها إلى كتل من أجل تسهيل التنقّل أسهل وأن تكون متسقة مع التطبيقات الأخرى. على سبيل المثال، إذا كان تطبيقك يحتوي على شريط أدوات، فإن شريط الأدوات يجب أن يكون في FocusArea منفصل عن باقي التطبيق. أشرطة علامات التبويب يجب أيضًا فصل عناصر التنقل الأخرى عن بقية التطبيق. القوائم الكبيرة يجب أن يكون لها FocusArea خاصة بها بشكل عام. وإذا لم يكن كذلك، يجب على المستخدمين عرض الإعلانات بالتناوب. القائمة بأكملها للوصول إلى بعض طرق العرض.

FocusArea هي فئة فرعية من LinearLayout في مكتبة واجهة المستخدم للسيارات. عند تفعيل هذه الميزة، يبرز FocusArea بشكل بارز عندما تكون إحدى والأحفاد لدينا التركيز. لمزيد من المعلومات، يُرجى مراجعة التركيز على تخصيص اللحظات المميّزة.

عند إنشاء كتلة تنقل في ملف التخطيط، إذا كنت تنوي استخدام LinearLayout كحاوية لتلك المجموعة، استخدِم FocusArea بدلاً منها. في الحالات الأخرى، يمكنك لف المربّع باستخدام FocusArea.

لا تدمج FocusArea في FocusArea آخر. يؤدي القيام بذلك إلى سلوك تنقل غير محدد. تأكد من أن جميع طرق العرض التي يمكن التركيز عليها متداخلة في FocusArea.

مثال على FocusArea في يتم عرض RotaryPlayground أدناه:

<com.android.car.ui.FocusArea
       android:layout_margin="16dp"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">
       <EditText
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:singleLine="true">
       </EditText>
   </com.android.car.ui.FocusArea>

يعمل FocusArea على النحو التالي:

  1. عند التعامل مع إجراءات التدوير والتذكير، يبحث RotaryService عن مثيلات من FocusArea في التدرج الهرمي لطريقة العرض.
  2. عند تلقّي حدث تدوير، ينقل RotaryService التركيز إلى حدث آخر. الملف الشخصي الذي يمكن التركيز عليه في FocusArea نفسها
  3. عند تلقّي تذكير تلقائي، يتم نقل التركيز من قِبل "RotaryService" إلى طريقة عرض أخرى. يمكن أن يركّز على عنصر FocusArea آخر (متجاور عادةً).

إذا لم تُدرِج أي FocusAreas في التنسيق، تتم معالجة طريقة العرض الجذر. كمجال تركيز ضمني لا يمكن للمستخدم الوكز للتنقل داخل التطبيق. بدلاً من ذلك، التنقل عبر كل طرق العرض القابلة للتركيز، والتي قد تكون ملائمة لمربعات الحوار.

تخصيص FocusArea

يمكن استخدام سمتَين عاديتَين في ميزة "العرض" لتخصيص التنقّل الدوّار:

  • يسمح android:nextFocusForward لمطوِّري التطبيقات بتحديد عرض الإعلانات بالتناوب. بالترتيب في مجال التركيز. هذه هي السمة نفسها المستخدمة للتحكم في ترتيب التنقل بـ Tab التنقل باستخدام لوحة المفاتيح. لا تستخدم هذه السمة لإنشاء حلقة تكرار. بدلاً من ذلك، يمكنك استخدام app:wrapAround (انظر أدناه) لإنشاء حلقة.
  • يسمح android:focusedByDefault لمطوّري التطبيقات بتحديد عرض التركيز الافتراضي في النافذة. لا تستخدم هذه السمة app:defaultFocus (انظر أدناه) في FocusArea نفسه.

تحدِّد السمة FocusArea أيضًا بعض السمات لتخصيص نظام التنقُّل الدوّار. لا يمكن تخصيص مجالات التركيز الضمنية باستخدام هذه السمات.

  1. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    يمكن استخدام app:defaultFocus للأغراض التالية: تحديد رقم تعريف ملف شخصي تابع يمكن التركيز عليه، والذي يجب التركيز عليه عندما ينقر المستخدم يشير إلى "FocusArea" كتذكير تلقائي.
  2. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    app:defaultFocusOverridesHistory يمكن ضبطها على true لجعل طريقة العرض المحدّدة أعلاه تركِّز حتى إذا كان السابقة للإشارة إلى وجهة نظر أخرى في هذه FocusArea التي تم التركيز عليها.
  3. (نظام التشغيل Android 12)
    استخدِم app:nudgeLeftShortcut وapp:nudgeRightShortcut app:nudgeUpShortcut وapp:nudgeDownShortcut لتحديد رقم تعريف ملف شخصي تابع يمكن التركيز عليه، والذي يجب التركيز عليه عند يقوم المستخدم بتذكيرك في اتجاه معين. لمزيد من المعلومات، يمكنك الاطّلاع على محتوى ادفع الاختصارات أدناه.

    (Android 11 QPR3 وAndroid 11 Car، متوقّفة نهائيًا في نظام التشغيل Android 12) app:nudgeShortcut وapp:nudgeShortcutDirection يتوافق مع اختصار تذكير تلقائي واحد فقط.

  4. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    لتفعيل ميزة التدوير أثناء الدوران في FocusArea، app:wrapAround يمكن ضبطها على true. وتُستخدم هذه الطريقة عادةً عندما يتمّ ترتيب المشاهد في أو بيضاوي الشكل.
  5. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    لضبط المساحة المتروكة للتمييز في هذه FocusArea، استخدام app:highlightPaddingStart، app:highlightPaddingEnd وapp:highlightPaddingTop app:highlightPaddingBottom، app:highlightPaddingHorizontal، وapp:highlightPaddingVertical.
  6. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    لضبط الحدود المرصودة للسمة FocusArea هذه لإيجاد هدف دفعة، استخدام app:startBoundOffset أو app:endBoundOffset app:topBoundOffset، app:bottomBoundOffset، app:horizontalBoundOffset وapp:verticalBoundOffset.
  7. (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    لتحديد معرّف FocusArea المتجاورة (أو المناطق) في الاتجاهات المحددة، استخدم app:nudgeLeft وapp:nudgeRight وapp:nudgeUp و app:nudgeDown استخدِم هذا الخيار عند استخدام بحث هندسي بشكل تلقائي لم يتمكن من العثور على الهدف المطلوب.

يؤدي الدفع عادةً إلى التنقل بين FocusAreas. ولكن مع اختصارات التحفيز، أحيانًا، يؤدي الدفع كتذكير ينتقل لأول مرة داخل FocusArea بحيث قد يحتاج المستخدم إلى على التوجيه مرتين للانتقال إلى FocusArea التالية. اختصارات التذكيرات التلقائية مفيدة عندما يحتوي FocusArea على قائمة طويلة متبوعة زر الإجراء العائم، كما في المثال أدناه:

تذكير تلقائي
الشكل 3. تذكير تلقائي

بدون اختصار التذكير التلقائي، سيتعين على المستخدم التدوير خلال القائمة بأكملها للوصول إلى FAB.

التركيز على تخصيص اللحظات المميّزة

كما هو موضح أعلاه، تستند RotaryService إلى المفهوم الحالي لإطار عمل Android عرض التركيز. عندما يجري المستخدم تدويرًا وتنبيهًا، يتم نقل التركيز باستخدام RotaryService، التركيز على وجهة نظر واحدة وعدم التركيز على أخرى. في نظام التشغيل Android، عند التركيز على العرض، في حال كان العرض:

  • يتضمّن نظام Android نقطة تركيز خاصة به، ويرسم نقطة التركيز في طريقة العرض.
  • لا يتم تحديد تمييز التركيز، ولا يتم إيقاف ميزة التركيز التلقائي، في نظام Android لرسم تمييز التركيز الافتراضي للعرض.

أما التطبيقات المصممة للعمل باللمس، فهي لا تحدد عادةً النقاط البارزة المناسبة.

يتوفّر إبراز التركيز التلقائي من خلال إطار عمل Android ويمكن تجاهله. المصنّع الأصلي للجهاز. يحصل مطوّرو التطبيقات على هذا المظهر عندما يكون المظهر الذي يستخدمونه مشتقًا من Theme.DeviceDefault

لتقديم تجربة مستخدِم متّسقة، يمكنك الاعتماد على التركيز التلقائي على التركيز كلما أمكن ذلك. إذا كنت بحاجة إلى تسليط الضوء على بؤرة مخصّصة (على سبيل المثال، شكل دائري أو شكل دوّار)، أو إذا كنت باستخدام مظهر غير مشتق من Theme.DeviceDefault، استخدِم مكتبة واجهة مستخدم السيارة. والموارد لتحديد تمييز التركيز الخاص بك لكل طريقة عرض.

لتحديد تمييز تركيز مخصّص لإحدى طرق العرض، يمكنك تغيير الخلفية أو المقدّمة للرسم. من العرض إلى عنصر قابل للرسم يختلف عند تركيز العرض. عادةً ما ستغير الخلفية. العناصر التالية القابلة للرسم، إذا تم استخدامها كخلفية للعرض المربع، تُنتج تسليط الضوء على التركيز الدائري:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_focused="true" android:state_pressed="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width"
            android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/>
      </shape>
   </item>
   <item android:state_focused="true">
      <shape android:shape="oval">
         <solid android:color="@color/car_ui_rotary_focus_fill_color"/>
         <stroke
            android:width="@dimen/car_ui_rotary_focus_stroke_width"
            android:color="@color/car_ui_rotary_focus_stroke_color"/>
      </shape>
   </item>
   <item>
      <ripple...>
         ...
      </ripple>
   </item>
</selector>

(Android 11 QPR3 وAndroid 11 Car، Android 12) مراجع موارد غامقة في النموذج أعلاه لتحديد الموارد المحددة في مكتبة واجهة المستخدم. يلغي المصنّع الأصلي للجهاز هذه الإعدادات لتكون متسقة باستخدام تمييز التركيز الافتراضي الذي يحددونه. يضمن ذلك أن يكون لون تمييز التركيز عرض خط الرسم، وما إلى ذلك، لا تتغير عندما يتنقل المستخدم بين طريقة عرض بتركيز مخصص التمييز وطريقة عرض بتمييز التركيز التلقائي. العنصر الأخير هو تموّج يُستخدم للمس. تظهر القيم التلقائية المستخدمة للموارد الغامقة كما يلي:

القيم التلقائية للموارد التي تظهر بخط غامق
الشكل 4. القيم التلقائية للموارد العريضة

بالإضافة إلى ذلك، يتم استدعاء ميزة إبراز تركيز مخصَّص عند منح زر محدَّد لون الخلفية لجذب انتباه المستخدم، كما في المثال أدناه. هذا يمكن أن يصعب رؤية تمييز التركيز. في هذه الحالة، حدد تمييز تركيز مخصص باستخدام الألوان الثانوية:

لون الخلفية الخالصة
  • (Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
    car_ui_rotary_focus_fill_secondary_color
    car_ui_rotary_focus_stroke_secondary_color
  • (نظام التشغيل Android 12)
    car_ui_rotary_focus_pressed_fill_secondary_color
    car_ui_rotary_focus_pressed_stroke_secondary_color

مثلاً:

تركيز، غير مضغوط تركيز، مضغوط
التركيز وليس المضغوط التركيز والضغط

التمرير الدوري

إذا كان تطبيقك يستخدم RecyclerView، يجب استخدام CarUiRecyclerView بدلاً من ذلك. يضمن ذلك أن تكون واجهة المستخدم متوافقة مع أخرى لأنّ تخصيص المصنّع الأصلي للجهاز ينطبق على جميع CarUiRecyclerView.

إذا كانت جميع العناصر في قائمتك قابلة للتركيز، لن تحتاج إلى اتخاذ أي إجراء. ينقل "التنقل عبر الدوران" التركيز بين العناصر في القائمة ويتم تمرير القائمة لجعل العنصر الذي تم التركيز عليه حديثًا مرئيًا.

(Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
إذا كان هناك مزيج من التركيز وغير القابل للتركيز الأخرى، أو إذا كانت جميع العناصر غير قابلة للتركيز، يمكنك تفعيل التمرير الدوري، وهو ما يتيح استخدام المستخدم لوحدة التحكم الدوارة للتمرير تدريجيًا في القائمة دون تخطي والعناصر غير القابلة للتركيز. لتفعيل التمرير الدوري، يجب ضبط app:rotaryScrollEnabled. إلى true.

(Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
يمكنك تفعيل التمرير الدوري في أي عرض قابل للتمرير، بما في ذلك avCarUiRecyclerView، مع طريقة واحدة (setRotaryScrollEnabled()) في CarUiUtils. إذا قمت بذلك، عليك إجراء ما يلي:

  • جعل العرض القابل للتمرير قابلاً للتركيز عليه بحيث يمكن التركيز عليه عندما لا تكون يكون طرق العرض التابعة التي يمكن التركيز عليها مرئية،
  • إيقاف ميزة إبراز التركيز التلقائي في العرض القابل للتمرير من خلال استدعاء setDefaultFocusHighlightEnabled(false) حتى يظهر العرض القابل للتمرير لا يبدو أنه مركز،
  • التأكد من التركيز على العرض القابل للتمرير قبل العناصر التابعة له من خلال استدعاء setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
  • الاستماع إلى MotionEvents باستخدام SOURCE_ROTARY_ENCODER AXIS_VSCROLL أو AXIS_HSCROLL للإشارة إلى المسافة التي يجب الانتقال إليها الاتجاه (من خلال العلامة).

عند تفعيل ميزة "التمرير الدوار" على CarUiRecyclerView وتدوير المستخدم إلى منطقة لا تتوفّر فيها طرق عرض قابلة للتركيز، يتغيّر شريط التمرير من اللون الرمادي إلى الأزرق، كما لو للإشارة إلى التركيز على شريط التمرير. يمكنك تنفيذ تأثير مماثل إذا أردت.

أحداث Motion Events هي مثل تلك التي يتم إنشاؤها بواسطة عجلة تمرير على الماوس، باستثناء المصدر.

وضع التلاعب المباشر

عادةً، يتم نقل التذكيرات التلقائية والتدوير عبر واجهة المستخدم، بينما يضغط الزر الأوسط اتخذ إجراءً، على الرغم من أن هذا ليس هو الحال دائمًا. على سبيل المثال، إذا أراد أحد المستخدمين تعديل مستوى صوت المنبّه، فقد يستخدمون وحدة التحكّم الدوارة للانتقال إلى شريط تمرير مستوى الصوت الزر الأوسط، يجب تدوير وحدة التحكّم لضبط مستوى صوت المنبّه، ثم الضغط على زر الرجوع. للعودة إلى التنقل. ويُشار إلى ذلك بوضع التلاعب المباشر (DM). في هذه الدورة، يتم استخدام وحدة التحكم الدوارة للتفاعل مع العرض مباشرةً بدلاً من التنقل.

يمكنك تنفيذ الرسالة المباشرة بإحدى طريقتَين. إذا كنت تريد التعامل مع التدوير والعرض الذي تريده فقط لمعالجة الردود على ACTION_SCROLL_FORWARD ACTION_SCROLL_BACKWARD AccessibilityEvent بشكل مناسب، استخدِم آلية بسيطة. وإذا لم تكن كذلك، يمكنك استخدام الآلية المتقدّمة.

والطريقة البسيطة هي الخيار الوحيد في نوافذ النظام؛ يمكن للتطبيقات استخدام أي من الطريقتين.

آلية بسيطة

(Android 11 QPR3 وAndroid 11 Car، نظام التشغيل Android 12)
يجب أن يتصل التطبيق DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable) يتعرّف RotaryService عندما يكون المستخدم في وضع الرسالة المباشرة، ويدخل في وضع الرسالة المباشرة عندما يكون المستخدم. يضغط على الزر الأوسط أثناء التركيز على العرض. عندما تكون في وضع الرسالة المباشرة، يتم تنفيذ عمليات التدوير ACTION_SCROLL_FORWARD أو ACTION_SCROLL_BACKWARD ويخرج من وضع الرسالة المباشرة عندما يضغط المستخدم على زر الرجوع. تعمل الآلية البسيطة على تبديل حالة طريقة العرض عند الدخول إلى وضع الرسالة المباشرة والخروج منه.

لتوفير إشارة مرئية بأنّ المستخدم في وضع الرسالة المباشرة، يجب أن يظهر العرض بشكل مختلف عند اختياره على سبيل المثال، يمكنك تغيير الخلفية عند تم true ميزة android:state_selected.

الآلية المتقدّمة

يحدّد التطبيق وقت دخول "RotaryService" إلى وضع الرسالة المباشرة والخروج منه. للحصول على تجربة المستخدم، سيؤدي الضغط على زر "المركز" مع التركيز على طريقة عرض الرسالة المباشرة إلى الانتقال إلى وضع الرسالة المباشرة. ويجب أن يخرج زر "الرجوع" من وضع الرسالة المباشرة. إذا لم يكن زر التوسيط و/أو التذكير التلقائي قيد الاستخدام، يمكن أن تكون طرقًا بديلة للخروج من وضع الرسالة المباشرة. بالنسبة إلى تطبيقات مثل "خرائط Google"، يتوفّر زر لتمثيل يمكن استخدام الرسالة المباشرة للدخول إلى وضع الرسالة المباشرة.

لإتاحة وضع الرسالة المباشرة المتقدّم، يمكن استخدام طريقة العرض التالية:

  1. (Android 11 QPR3 وAndroid 11 Car، Android 12) يجب أن يستجيب إلى KEYCODE_DPAD_CENTER هو حدث للدخول في وضع الرسالة المباشرة والاستماع إلى حدث KEYCODE_BACK للخروج من وضع الرسالة المباشرة الاتصال بـ DirectManipulationHelper.enableDirectManipulationMode() في كل حالة. للاستماع إلى هذه الأحداث، نفِّذ أحد الإجراءات التالية:
    • تسجيل OnKeyListener
    • أو
    • يمكنك تمديد العرض ثم إلغاء طريقة dispatchKeyEvent().
  2. يجب الاستماع إلى التذكيرات التلقائية (KEYCODE_DPAD_UP وKEYCODE_DPAD_DOWN و KEYCODE_DPAD_LEFT، أو KEYCODE_DPAD_RIGHT) إذا كان ينبغي أن تكون طريقة العرض التعامل مع التذكيرات التلقائية.
  3. يجب الاستماع إلى MotionEvent والحصول على عدد التدوير خلال AXIS_SCROLL إذا أرادت طريقة العرض التعامل مع الدوران. وهناك العديد من الطرق لإجراء ذلك:
    1. تسجيل OnGenericMotionListener
    2. يمكنك تمديد العرض وإلغاء طريقة dispatchTouchEvent().
  4. لتجنُّب التوقّف في وضع الرسالة المباشرة، يجب الخروج من وضع الرسالة المباشرة عند عرض القسم "جزء" أو "النشاط". التي تنتمي إليها ليست تفاعلية.
  5. يجب توفير إشارة مرئية للإشارة إلى أنّ العرض في وضع الرسالة المباشرة.

فيما يلي نموذج من طريقة عرض مخصصة تستخدم وضع DM لتحريك وتكبير/تصغير الخريطة:

/** Whether this view is in DM mode. */
private boolean mInDirectManipulationMode;

/** Initializes the view. Called by the constructors. */ private void init() { setOnKeyListener((view, keyCode, keyEvent) -> { boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP; switch (keyCode) { // Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK events. case KeyEvent.KEYCODE_DPAD_CENTER: if (!mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = true; DirectManipulationHelper.enableDirectManipulationMode(this, true); setSelected(true); // visually indicate DM mode } return true; case KeyEvent.KEYCODE_BACK: if (mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); setSelected(false); } return true; // Consume controller nudge events only when in DM mode. // When in DM mode, nudges pan the map. case KeyEvent.KEYCODE_DPAD_UP: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, -10f); return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, 10f); return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(-10f, 0f); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(10f, 0f); return true; // Don't consume other key events. default: return false; } });
// When in DM mode, rotation zooms the map. setOnGenericMotionListener(((view, motionEvent) -> { if (!mInDirectManipulationMode) return false; float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); zoom(10 * scroll); return true; })); }
@Override public void onPause() { if (mInDirectManipulationMode) { // To ensure that the user doesn't get stuck in DM mode, disable DM mode // when the fragment is not interactive (e.g., a dialog shows up). mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); } super.onPause(); }

يمكن العثور على مزيد من الأمثلة في مشروع واحد (RotaryPlayground).

عرض النشاط

عند استخدام ActivityView:

  • يجب ألّا يكون التركيز على ActivityView.
  • (Android 11 QPR3 وAndroid 11 Car، متوقفة نهائيًا في نظام التشغيل Android 11)
    يجب أن يشتمل محتوى ActivityView على FocusParkingView كأول عرض يمكن التركيز عليه، وapp:shouldRestoreFocus يجب أن تكون السمة false.
  • يجب ألا يحتوي محتوى ActivityView على android:focusByDefault مشاهدة

بالنسبة إلى المستخدم، من المفترض ألا يكون لفئات ActivityView أي تأثير في التنقُّل باستثناء التركيز لا يمكن للمناطق تضمين مشاهدات النشاط. بعبارة أخرى، لا يمكن أن يكون لديك مجال تركيز واحد يشتمل على محتوى داخل وخارج ActivityView. إذا لم تضِف أي FocusAreas إلى ActivityView، وهو جذور التدرج الهرمي لطريقة العرض في يُعدّ ActivityView أحد مجالات التركيز الضمني.

الأزرار التي تعمل عند الضغط مع الاستمرار

تؤدي معظم الأزرار إلى تنفيذ بعض الإجراءات عند النقر عليها. تعمل بعض الأزرار عند الضغط مع الاستمرار بدلاً من ذلك. على سبيل المثال، عادةً ما يعمل زرا التقديم السريع و الترجيع عند الضغط مع الاستمرار. لإجراء ذلك أزرار دعم الدوران، الاستماع إلى KEYCODE_DPAD_CENTER KeyEvents على النحو التالي:

mButton.setOnKeyListener((v, keyCode, event) ->
{
    if (keyCode != KEYCODE_DPAD_CENTER) {
        return false;
    }
    if (event.getAction() == ACTION_DOWN) {
        mButton.setPressed(true);
        mHandler.post(mRunnable);
    } else {
        mButton.setPressed(false);
        mHandler.removeCallbacks(mRunnable);
    }
    return true;
});

يتم من خلاله اتخاذ إجراء من قِبل "mRunnable" (مثل ترجيع الفيديو) وتحديد موعد عرضه أن يتم تنفيذها بعد تأخير.

وضع اللمس

يمكن للمستخدمين استخدام وحدة تحكم دوّارة للتفاعل مع الوحدة الرئيسية في السيارة بطريقتين، إما باستخدام وحدة التحكم الدوارة أو عن طريق لمس الشاشة. عند استخدام وحدة التحكم الدوارة، حيث يتم تمييز إحدى طرق العرض التي يمكن التركيز عليها. لا يتم تمييز التركيز عند لمس الشاشة. تظهر. يمكن للمستخدم التبديل بين أوضاع الإدخال التالية في أي وقت:

  • مفتاح دوران → لمسة عندما يلمس المستخدم الشاشة، يختفي تمييز التركيز.
  • انقر على ← زر دوار. عندما يضغط المستخدم على زر "المركز" أو يحرّكه أو يضغط عليه، فإن يظهر تمييز التركيز.

ولا يكون لزرَي الرجوع والصفحة الرئيسية أي تأثير في وضع الإدخال.

العلامات المترابطة الدوارة حول المفهوم الحالي لنظام Android وضع اللمس. يمكنك استخدام View.isInTouchMode() لتحديد وضع الإدخال الذي يستخدمه المستخدم. يمكنك استخدام OnTouchModeChangeListener من الاستماع إلى التغييرات. وعلى الرغم من إمكانية استخدامه لتخصيص واجهة المستخدم الحالية، وضع الإدخال، تجنب أي تغييرات كبيرة لأنها قد تكون مربكة.

تحديد المشاكل وحلّها

في تطبيق مصمم للمس، من الشائع أن يكون هناك طرق عرض متداخلة يمكن التركيز عليها. على سبيل المثال، قد يكون هناك FrameLayout حول ImageButton، وكلاهما يمكن التركيز عليه. لا يضر هذا اللمس، ولكن يمكن أن يؤدي إلى تجربة المستخدم للدوران لأن المستخدم يجب أن يقوم بتدوير وحدة التحكم مرتين للانتقال إلى العرض التفاعلي التالي. لتقديم تجربة جيدة للمستخدمين، تنصحك Google بإجراء أيّ مما يلي: يمكن التركيز على العرض الخارجي أو الرؤية الداخلية، ولكن ليس كليهما.

إذا فقد أحد الأزرار أو المفاتيح التركيز عند الضغط على وحدة التحكم الدوارة، فإن أحد قد تنطبق هذه الشروط:

  • يتم إيقاف الزر أو مفتاح التحكّم (لفترة قصيرة أو إلى أجل غير مسمى) بسبب عند الضغط عليها. في كلتا الحالتين، هناك طريقتان لمعالجة هذا الأمر:
    • ترك حالة android:enabled على true واستخدام حالة مخصصة التبديل إلى اللون الرمادي للزر أو التبديل كما هو موضح في الحالة المخصَّصة:
    • استخدِم حاوية لإحاطة الزر أو مفتاح التحكّم وجعل الحاوية قابلة للتركيز بدلاً من الزر أو المفتاح. (يجب أن يكون مستمع النقر في الحاوية.)
  • يتم استبدال الزر أو مفتاح التحكّم. على سبيل المثال، الإجراء الذي يتم اتخاذه عند النقر على الزر قد يؤدي الضغط على مفتاح التبديل أو تفعيل مفتاح التبديل إلى إعادة تحميل الإجراءات المتاحة مما يتسبب في استبدال الأزرار الجديدة بالأزرار الموجودة. هناك طريقتان لمعالجة هذا الأمر:
    • وبدلاً من إنشاء زر أو مفتاح جديد، يمكنك تعيين رمز و/أو نص الزر أو مفتاح التبديل الحالي.
    • كما هو موضح أعلاه، أضِف حاوية يمكن التركيز عليها حول الزر أو مفتاح التحكّم.

ملعب دوّار

"RotaryPlayground" هو تطبيق مرجعي لنظام التشغيل الدوّار. يمكنك استخدامه لمعرفة كيفية دمج الميزات الدورية في تطبيقاتك. تم تضمين RotaryPlayground في إصدارات المحاكي وفي للإصدارات المخصصة للأجهزة التي تعمل بنظام التشغيل Android Automotive (AAOS).

  • مستودع واحد (RotaryPlayground): packages/apps/Car/tests/RotaryPlayground/
  • الإصدارات: Android 11 QPR3، Android 11 Car، وAndroid 12

يعرض تطبيق "RotaryPlayground" علامات التبويب التالية على اليمين:

  • البطاقات: اختبار التنقل حول مناطق التركيز، وتخطي العناصر غير القابلة للتركيز وإدخال النص.
  • التلاعب المباشر: اختبار التطبيقات المصغّرة التي تتوافق مع التطبيقات البسيطة والمتقدّمة أسلوب التحكم المباشر. علامة التبويب هذه مخصصة للتلاعب المباشر داخل نافذة التطبيق.
  • معالجة واجهة مستخدم النظام (Sys) اختبار التطبيقات المصغّرة التي تتيح التحكّم المباشر في نوافذ النظام التي يتوفر فيها وضع التلاعب المباشر البسيط فقط.
  • "الشبكة": اختبِر التنقّل الدوّار على شكل حرف z من خلال التمرير.
  • الإشعار. يمكنك اختبار ميزة الدفع من داخل الإشعارات المُرسَلة وخارجها.
  • التمرير اختبار التنقّل بين عناصر يمكن التركيز عليها وتلك التي لا يمكن التركيز عليها المحتوى.
  • WebView: اختبار التنقّل بين الروابط في WebView
  • مخصّص FocusArea. اختبار تخصيص FocusArea:
    • التفاف.
    • android:focusedByDefault وapp:defaultFocus
    • .
    • أهداف التذكير التلقائي الصريح
    • تذكير تلقائي بالاختصارات.
    • FocusArea بدون أي مشاهدات يمكن التركيز عليها