تسهيل الوصول إلى طرق العرض المخصّصة

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

  • التعامل مع النقرات على وحدة التحكّم الاتجاهات
  • تنفيذ طرق واجهة برمجة التطبيقات Accessibility API
  • إرسال AccessibilityEvent الكائنات الخاصة بطريقة العرض المخصصة.
  • تعبئة AccessibilityEvent و AccessibilityNodeInfo لعرضك

التعامل مع النقرات على وحدة التحكّم الاتجاهات

في معظم الأجهزة، يؤدي النقر على عرض باستخدام وحدة تحكم الاتجاهات إلى إرسال KeyEvent باستخدام KEYCODE_DPAD_CENTER بطريقة العرض محل التركيز حاليًا. الاسم المعرِّف العادي لكل طرق العرض على Android KEYCODE_DPAD_CENTER بشكل ملائم عند إنشاء تخصيص View تأكد من أن هذا الحدث له نفس تأثير النقر على طريقة العرض على الشاشة التي تعمل باللمس.

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

تنفيذ طرق واجهة برمجة التطبيقات Accessibility API

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

dispatchPopulateAccessibilityEvent()
يستدعي النظام هذه الطريقة عندما تنشئ طريقة العرض المخصّصة حدث إمكانية وصول. الإعداد التلقائي يستدعي تنفيذ هذه الطريقة onPopulateAccessibilityEvent() لهذا الملف الشخصي ثم الطريقة dispatchPopulateAccessibilityEvent() لكل فرع من هذه القيم مشاهدة.
onInitializeAccessibilityEvent()
يستدعي النظام هذه الطريقة للحصول على معلومات إضافية عن حالة العرض خارج المحتوى النصي. إذا كانت طريقة العرض المخصّصة توفّر تحكّمًا تفاعليًا خارج نطاق TextView أو Button، إلغاء هذه الطريقة وضبط المعلومات الإضافية حول طريقة العرض، مثل نوع حقل كلمة المرور ومربّع الاختيار أو حالات تقدم تفاعل المستخدم أو ملاحظات حول الحدث — باستخدام . في حال تجاوز هذه الطريقة، يجب استدعاء تنفيذها المميّز وتعديل المواقع فقط التي لا تحددها الفئة الفائقة.
onInitializeAccessibilityNodeInfo()
توفّر هذه الطريقة لخدمات تسهيل الاستخدام معلومات عن حالة العرض. تشير رسالة الأشكال البيانية عملية تنفيذ View التلقائية تتضمّن مجموعة عادية من خصائص الملف الشخصي، ولكن إذا كان توفر طريقة العرض المخصصة تحكمًا تفاعليًا خارج نطاق TextView أو Button، يمكنك إلغاء هذه الطريقة وضبط المعلومات الإضافية حول طريقة العرض مع الكائن AccessibilityNodeInfo الذي تتم معالجته بهذه الطريقة.
onPopulateAccessibilityEvent()
تضبط هذه الطريقة طلب النص الشفهي لـ AccessibilityEvent في مشاهدة. ويُطلق عليها أيضًا اسم طريقة العرض إذا كانت طريقة العرض تابعة لطريقة العرض التي تنشئ إمكانية وصول. فعالية.
onRequestSendAccessibilityEvent()
يستدعي النظام هذه الطريقة عندما ينشئ عنصر ثانوي في ملفك الشخصي AccessibilityEvent تتيح هذه الخطوة لطريقة العرض الرئيسية تعديل إعدادات تسهيل الاستخدام. الحدث مع معلومات إضافية. لا يتم تنفيذ هذه الطريقة إلا إذا كان من الممكن أن تشتمل طريقة العرض المخصّصة على ما إذا كانت طريقة العرض تتيح للوالدَين توفير معلومات حول السياق وهو حدث مفيد لخدمات إمكانية الوصول.
sendAccessibilityEvent()
يستدعي النظام هذه الطريقة عندما يتخذ أحد المستخدمين إجراءً بشأن إحدى المشاهدات. تم تصنيف الحدث كما يلي: نوع إجراء المستخدم، مثل TYPE_VIEW_CLICKED. بوجه عام، يجب إرسال AccessibilityEvent كلما تغيّر محتوى طريقة العرض المخصّصة.
sendAccessibilityEventUnchecked()
تُستخدم هذه الطريقة عندما يحتاج رمز الاتصال إلى التحكم مباشرةً في عملية التحقق من تفعيل إمكانية الوصول على الجهاز (AccessibilityManager.isEnabled()). إذا نفذت هذه الطريقة، فأجرِ الاتصال كما لو كانت إمكانية الوصول مُفعَّلة، بغض النظر عن إعداد النظام الأساسي. لا تحتاج عادةً إلى تنفيذ هذه الطريقة لطريقة عرض مخصّصة.

لدعم إمكانية الوصول، يجب إلغاء طرق الوصول السابقة وتنفيذها مباشرةً في فئة طريقة العرض المخصصة.

على الأقل، نفِّذ طرق تسهيل الاستخدام التالية لفئة طريقة العرض المخصّصة:

  • dispatchPopulateAccessibilityEvent()
  • onInitializeAccessibilityEvent()
  • onInitializeAccessibilityNodeInfo()
  • onPopulateAccessibilityEvent()

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

إرسال أحداث تسهيل الاستخدام

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

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

Kotlin

override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
    return when(keyCode) {
        KeyEvent.KEYCODE_DPAD_LEFT -> {
            currentValue--
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED)
            true
        }
        ...
    }
}

Java

@Override
public boolean onKeyUp (int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
        currentValue--;
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
        return true;
    }
    ...
}

تعبئة أحداث تسهيل الاستخدام

ولكل AccessibilityEvent مجموعة من السمات المطلوبة التي تصف السمة الحالية. وضع العرض. وتشمل هذه الخصائص عناصر مثل اسم فئة العرض والمحتوى والوصف والحالة المحددة. يتم توضيح السمات المحدّدة المطلوبة لكل نوع من الأحداث في AccessibilityEvent الوثائق المرجعية.

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

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

بالإضافة إلى ذلك، نفِّذ onInitializeAccessibilityNodeInfo() . تستخدم خدمات تسهيل الاستخدام العناصر AccessibilityNodeInfo التي تمت تعبئتها من خلال هذا العنصر للتحقق من التسلسل الهرمي طرق العرض الذي ينشئ حدث إمكانية الوصول بعد تلقيه وتقديم الملاحظات المناسبة للمستخدمين.

يوضح مثال الرمز التالي كيفية تجاوز هذه الطرق الثلاث في طريقة العرض:

Kotlin

override fun onPopulateAccessibilityEvent(event: AccessibilityEvent?) {
    super.onPopulateAccessibilityEvent(event)
    // Call the super implementation to populate its text for the
    // event. Then, add text not present in a super class.
    // You typically only need to add the text for the custom view.
    if (text?.isNotEmpty() == true) {
        event?.text?.add(text)
    }
}

override fun onInitializeAccessibilityEvent(event: AccessibilityEvent?) {
    super.onInitializeAccessibilityEvent(event)
    // Call the super implementation to let super classes
    // set appropriate event properties. Then, add the new checked
    // property that is not supported by a super class.
    event?.isChecked = isChecked()
}

override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo?) {
    super.onInitializeAccessibilityNodeInfo(info)
    // Call the super implementation to let super classes set
    // appropriate info properties. Then, add the checkable and checked
    // properties that are not supported by a super class.
    info?.isCheckable = true
    info?.isChecked = isChecked()
    // You typically only need to add the text for the custom view.
    if (text?.isNotEmpty() == true) {
        info?.text = text
    }
}

Java

@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
    super.onPopulateAccessibilityEvent(event);
    // Call the super implementation to populate its text for the
    // event. Then, add the text not present in a super class.
    // You typically only need to add the text for the custom view.
    CharSequence text = getText();
    if (!TextUtils.isEmpty(text)) {
        event.getText().add(text);
    }
}

@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
    super.onInitializeAccessibilityEvent(event);
    // Call the super implementation to let super classes
    // set appropriate event properties. Then, add the new checked
    // property that is not supported by a super class.
    event.setChecked(isChecked());
}

@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
    super.onInitializeAccessibilityNodeInfo(info);
    // Call the super implementation to let super classes set
    // appropriate info properties. Then, add the checkable and checked
    // properties that are not supported by a super class.
    info.setCheckable(true);
    info.setChecked(isChecked());
    // You typically only need to add the text for the custom view.
    CharSequence text = getText();
    if (!TextUtils.isEmpty(text)) {
        info.setText(text);
    }
}

يمكنك تنفيذ هذه الطرق مباشرةً في فئة طريقة العرض المخصّصة.

توفير سياق مخصّص لتسهيل الاستخدام

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

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

الشكل 1. عرض تقويم مخصص مع عناصر يوم يمكن اختيارها.

في المثال في الشكل 1، يتم تنفيذ التقويم بأكمله كطريقة عرض واحدة، وبالتالي عند تلقّي الخدمات معلومات كافية عن محتوى طريقة العرض واختيار المستخدم ضمن العرض ما لم يقدّم مطور البرامج معلومات إضافية. على سبيل المثال، إذا نقر أحد المستخدمين في اليوم الذي يحمل التصنيف 17، لن يتلقّى إطار عمل تسهيل الاستخدام إلا المعلومات الوصفية للتحكّم في التقويم بالكامل في هذه الحالة، تُعلن خدمة تسهيل الاستخدام TalkBack "التقويم" أو "تقويم أبريل" ولا يعرف المستخدم اليوم الذي يتم اختياره.

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

هناك حالة أخرى قد تكون فيها الحاجة إلى تسلسل هرمي لطريقة العرض الافتراضية هي واجهة مستخدم تحتوي على مجموعة من عناصر التحكم في View التي تتضمن دوالاً وثيقة الصلة، حيث يؤدي الإجراء على أحد العناصر يؤثر عنصر التحكم في محتويات عنصر واحد أو أكثر — مثل منتقي الأرقام الذي يتم فصله وأسفل الشاشة. في هذه الحالة، لا يمكن لخدمات تسهيل الاستخدام الحصول على معلومات كافية بسبب أحد الإجراءات على عنصر تحكم يؤدي إلى تغيير المحتوى في عنصر آخر، وقد لا تؤدي العلاقة بين عناصر التحكم هذه بوضوح للخدمة.

للتعامل مع هذا الموقف، عليك تجميع عناصر التحكم ذات الصلة مع طريقة عرض شاملة وتوفير عنصر تحكم افتراضي العرض الهرمي من هذه الحاوية لتمثيل المعلومات والسلوك اللذين تقدمهما والتحكم المستمر.

لتوفير تسلسل هرمي لطريقة عرض افتراضية لأحد طرق العرض، يمكنك إلغاء getAccessibilityNodeProvider() في طريقة العرض المخصصة أو مجموعة طرق العرض المخصصة وعرض تنفيذ AccessibilityNodeProvider يمكنك تنفيذ عرض هرمي لطريقة العرض الافتراضية باستخدام "مكتبة الدعم" مع ViewCompat.getAccessibilityNodeProvider() وتقديم طريقة تنفيذ AccessibilityNodeProviderCompat

لتبسيط مهمة تقديم المعلومات لخدمات إمكانية الوصول وإدارة تركيز سهولة الوصول، يمكنك بدلاً من ذلك تنفيذ ExploreByTouchHelper وتوفر AccessibilityNodeProviderCompat ويمكن إرفاقها كملف شخصي AccessibilityDelegateCompat عن طريق الاتصال setAccessibilityDelegate على سبيل المثال، راجع ExploreByTouchHelperActivity يتم استخدام ExploreByTouchHelper أيضًا من خلال التطبيقات المصغّرة الخاصة بإطار العمل، مثل CalendarView، من خلال عرض ملف الطفل SimpleMonthView

التعامل مع أحداث اللمس المخصّصة

قد تتطلب عناصر التحكّم في العرض المخصّص سلوك حدث لمس غير عادي، كما هو موضّح في الأمثلة التالية.

تحديد الإجراءات المستندة إلى النقرات

إذا كان تطبيقك المصغّر يستخدم OnClickListener أو OnLongClickListener سيتعامل النظام مع ACTION_CLICK أو ACTION_LONG_CLICK إجراءات مناسبة لك. إذا كان تطبيقك يستخدم أداة أكثر تخصيصًا تعتمد على OnTouchListener تحديد معالجات مخصصة لإجراءات إمكانية الوصول المستندة إلى النقرات. لإجراء ذلك، اتصل بـ replaceAccessibilityAction() لكل إجراء، كما هو موضح في مقتطف الرمز التالي:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    // Assumes that the widget is designed to select text when tapped, and selects
    // all text when tapped and held. In its strings.xml file, this app sets
    // "select" to "Select" and "select_all" to "Select all".
    ViewCompat.replaceAccessibilityAction(
        binding.textSelectWidget,
        ACTION_CLICK,
        getString(R.string.select)
    ) { view, commandArguments ->
        selectText()
    }

    ViewCompat.replaceAccessibilityAction(
        binding.textSelectWidget,
        ACTION_LONG_CLICK,
        getString(R.string.select_all)
    ) { view, commandArguments ->
        selectAllText()
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    // Assumes that the widget is designed to select text when tapped, and select
    // all text when tapped and held. In its strings.xml file, this app sets
    // "select" to "Select" and "select_all" to "Select all".
    ViewCompat.replaceAccessibilityAction(
            binding.textSelectWidget,
            ACTION_CLICK,
            getString(R.string.select),
            (view, commandArguments) -> selectText());

    ViewCompat.replaceAccessibilityAction(
            binding.textSelectWidget,
            ACTION_LONG_CLICK,
            getString(R.string.select_all),
            (view, commandArguments) -> selectAllText());
}

إنشاء أحداث نقرات مخصّصة

يمكن لعنصر تحكّم مخصّص استخدام السمة onTouchEvent(MotionEvent) المستمع لاكتشاف ACTION_DOWN و هناك ACTION_UP من الأحداث و إلى تشغيل حدث نقرة خاصة. للحفاظ على التوافق مع خدمات سهولة الوصول، فإن الرمز الذي معالجة حدث النقر المخصّص هذا، يجب إجراء ما يلي:

  1. أنشئ قيمة AccessibilityEvent مناسبة لإجراء النقرة المفسَّر.
  2. تفعيل خدمات تسهيل الاستخدام من أجل تنفيذ إجراء النقر المخصّص للمستخدمين غير القادرين على استخدام شاشة تعمل باللمس.

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

Kotlin

class CustomTouchView(context: Context) : View(context) {

    var downTouch = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        super.onTouchEvent(event)

        // Listening for the down and up touch events.
        return when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                downTouch = true
                true
            }

            MotionEvent.ACTION_UP -> if (downTouch) {
                downTouch = false
                performClick() // Call this method to handle the response and
                // enable accessibility services to
                // perform this action for a user who can't
                // tap the touchscreen.
                true
            } else {
                false
            }

            else -> false  // Return false for other touch events.
        }
    }

    override fun performClick(): Boolean {
        // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any.
        super.performClick()

        // Handle the action for the custom click here.

        return true
    }
}

Java

class CustomTouchView extends View {

    public CustomTouchView(Context context) {
        super(context);
    }

    boolean downTouch = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        // Listening for the down and up touch events
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downTouch = true;
                return true;

            case MotionEvent.ACTION_UP:
                if (downTouch) {
                    downTouch = false;
                    performClick(); // Call this method to handle the response and
                                    // enable accessibility services to
                                    // perform this action for a user who can't
                                    // tap the touchscreen.
                    return true;
                }
        }
        return false; // Return false for other touch events.
    }

    @Override
    public boolean performClick() {
        // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any.
        super.performClick();

        // Handle the action for the custom click here.

        return true;
    }
}

يساعد النمط السابق على ضمان توافق حدث النقر المخصّص مع تسهيل الاستخدام باستخدام طريقة performClick() لإنشاء حدث تسهيل الاستخدام لتوفير نقطة دخول لخدمات تسهيل الاستخدام للتصرف نيابةً عن المستخدم الذي ينفذ حدث النقر.