نمایش های سفارشی را در دسترس تر کنید

اگر برنامه شما به یک مؤلفه نمای سفارشی نیاز دارد، باید نما را در دسترس تر کنید. مراحل زیر می تواند دسترسی نمای سفارشی شما را، همانطور که در این صفحه توضیح داده شده است، بهبود بخشد:

  • کنترل کلیک های کنترل کننده جهت دار
  • پیاده سازی روش های دسترسی به API.
  • اشیاء AccessibilityEvent مخصوص نمای سفارشی شما را ارسال کنید.
  • AccessibilityEvent و AccessibilityNodeInfo را برای نمای خود پر کنید.

کنترل کلیک های کنترل کننده جهت دار

در اکثر دستگاه‌ها، کلیک کردن روی یک نما با استفاده از یک کنترل‌کننده جهت، یک KeyEvent با KEYCODE_DPAD_CENTER به نمای فعلی در فوکوس ارسال می‌کند. همه نماهای استاندارد Android KEYCODE_DPAD_CENTER به درستی مدیریت می کنند. هنگام ساختن یک کنترل View سفارشی، مطمئن شوید که این رویداد همان اثر ضربه زدن به نمای روی صفحه لمسی را دارد.

کنترل سفارشی شما باید با رویداد KEYCODE_ENTER مانند KEYCODE_DPAD_CENTER رفتار کند. این کار تعامل با صفحه کلید کامل را برای کاربران آسان تر می کند.

پیاده سازی روش های دسترسی به API

رویدادهای دسترس‌پذیری پیام‌هایی درباره تعامل کاربران با اجزای رابط بصری برنامه شما هستند. این پیام‌ها توسط سرویس‌های دسترس‌پذیری مدیریت می‌شوند که از اطلاعات این رویدادها برای تولید بازخورد و درخواست‌های تکمیلی استفاده می‌کنند. متدهای دسترسی بخشی از کلاس های View و View.AccessibilityDelegate هستند. روش ها به شرح زیر است:

dispatchPopulateAccessibilityEvent()
هنگامی که نمای سفارشی شما یک رویداد دسترس‌پذیری ایجاد می‌کند، سیستم این روش را فراخوانی می‌کند. اجرای پیش‌فرض این متد onPopulateAccessibilityEvent() برای این view و سپس متد dispatchPopulateAccessibilityEvent() برای هر فرزند این view فراخوانی می‌کند.
onInitializeAccessibilityEvent()
سیستم این روش را برای به دست آوردن اطلاعات اضافی در مورد وضعیت نمای فراتر از محتوای متن فراخوانی می کند. اگر نمای سفارشی شما کنترل تعاملی فراتر از یک TextView یا Button ساده ارائه می‌کند، این روش را نادیده بگیرید و اطلاعات اضافی در مورد نمای خود را تنظیم کنید - مانند نوع فیلد رمز عبور، نوع کادر انتخاب یا حالت‌هایی که تعامل یا بازخورد کاربر را برای رویداد ارائه می‌دهند - با استفاده از این روش. . اگر این متد را لغو کردید، اجرای super آن را فراخوانی کنید و فقط ویژگی هایی را تغییر دهید که توسط کلاس super تنظیم نشده اند.
onInitializeAccessibilityNodeInfo()
این روش خدمات دسترسی را با اطلاعاتی در مورد وضعیت نما ارائه می دهد. اجرای View پیش‌فرض دارای یک مجموعه استاندارد از ویژگی‌های view است، اما اگر نمای سفارشی شما کنترل تعاملی فراتر از یک TextView یا Button ساده ارائه می‌کند، این روش را لغو کنید و اطلاعات اضافی درباره نمای خود را در شی AccessibilityNodeInfo که توسط این روش مدیریت می‌شود، تنظیم کنید.
onPopulateAccessibilityEvent()
این روش اعلان متن گفتاری AccessibilityEvent را برای نمای شما تنظیم می کند. همچنین اگر نمای فرزند نمای است که یک رویداد دسترس‌پذیری ایجاد می‌کند، نامیده می‌شود.
onRequestSendAccessibilityEvent()
سیستم زمانی این روش را فراخوانی می کند که فرزندی از دیدگاه شما یک AccessibilityEvent ایجاد کند. این مرحله به نمای والدین امکان می‌دهد رویداد دسترس‌پذیری را با اطلاعات اضافی اصلاح کند. این روش را فقط در صورتی اجرا کنید که نمای سفارشی شما بتواند نماهای فرزند داشته باشد و اگر نمای والد بتواند اطلاعات زمینه را برای رویداد دسترس‌پذیری ارائه دهد که برای سرویس‌های دسترس‌پذیری مفید است.
sendAccessibilityEvent()
سیستم زمانی این روش را فراخوانی می کند که کاربر روی یک view اقدام کند. رویداد با یک نوع اقدام کاربر، مانند TYPE_VIEW_CLICKED طبقه‌بندی می‌شود. به طور کلی، هر زمان که محتوای نمای سفارشی شما تغییر کرد، باید یک AccessibilityEvent ارسال کنید.
sendAccessibilityEventUnchecked()
این روش زمانی استفاده می‌شود که کد فراخوانی نیاز به کنترل مستقیم بررسی دسترس‌پذیری در دستگاه دارد ( AccessibilityManager.isEnabled() ). اگر این روش را اجرا می کنید، بدون توجه به تنظیمات سیستم، تماس را طوری انجام دهید که گویی دسترسی فعال است. شما معمولاً برای یک نمای سفارشی نیازی به پیاده سازی این روش ندارید.

برای پشتیبانی از دسترس‌پذیری، روش‌های دسترس‌پذیری قبلی را مستقیماً در کلاس view سفارشی خود لغو و پیاده‌سازی کنید.

حداقل، روش‌های دسترسی زیر را برای کلاس view سفارشی خود پیاده‌سازی کنید:

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

برای اطلاعات بیشتر در مورد اجرای این روش‌ها، بخش مربوط به پر کردن رویدادهای دسترسی را ببینید.

رویدادهای دسترسی را ارسال کنید

بسته به مشخصات نمای سفارشی شما، ممکن است نیاز باشد که اشیاء AccessibilityEvent در زمان‌های مختلف یا برای رویدادهایی که توسط پیاده‌سازی پیش‌فرض مدیریت نمی‌شوند ارسال شود. کلاس View یک پیاده سازی پیش فرض برای این انواع رویداد ارائه می دهد:

به طور کلی، هر زمان که محتوای نمای سفارشی شما تغییر کرد، باید یک AccessibilityEvent ارسال کنید. برای مثال، اگر یک نوار لغزنده سفارشی را پیاده‌سازی می‌کنید که به کاربر امکان می‌دهد با فشار دادن کلید پیکان چپ یا راست، یک مقدار عددی را انتخاب کند، نمای سفارشی شما باید هر زمان که مقدار لغزنده تغییر کرد، یک رویداد TYPE_VIEW_TEXT_CHANGED منتشر کند. نمونه کد زیر استفاده از متد sendAccessibilityEvent() برای گزارش این رویداد نشان می دهد.

کاتلین

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

جاوا

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

رویدادهای دسترسی را پر کنید

هر AccessibilityEvent دارای مجموعه ای از ویژگی های مورد نیاز است که وضعیت فعلی نما را توصیف می کند. این ویژگی ها شامل مواردی مانند نام کلاس view، توضیحات محتوا و وضعیت علامت گذاری شده است. ویژگی های خاص مورد نیاز برای هر نوع رویداد در مستندات مرجع AccessibilityEvent توضیح داده شده است.

پیاده سازی View مقادیر پیش فرض را برای این ویژگی های مورد نیاز ارائه می دهد. بسیاری از این مقادیر، از جمله نام کلاس و مهر زمانی رویداد، به صورت خودکار ارائه می شوند. اگر در حال ایجاد یک کامپوننت نمای سفارشی هستید، باید اطلاعاتی در مورد محتوا و ویژگی های نما ارائه دهید. این اطلاعات می تواند به سادگی یک برچسب دکمه باشد و می تواند شامل اطلاعات وضعیت اضافی باشد که می خواهید به رویداد اضافه کنید.

از متدهای onPopulateAccessibilityEvent() و onInitializeAccessibilityEvent() برای پر کردن یا تغییر اطلاعات در AccessibilityEvent استفاده کنید. از روش onPopulateAccessibilityEvent() به طور خاص برای افزودن یا اصلاح محتوای متنی رویداد استفاده کنید، که توسط سرویس‌های دسترس‌پذیری مانند TalkBack به پیام‌های شنیداری تبدیل می‌شود. از متد onInitializeAccessibilityEvent() برای پر کردن اطلاعات اضافی درباره رویداد، مانند حالت انتخاب view استفاده کنید.

علاوه بر این، متد onInitializeAccessibilityNodeInfo() را پیاده سازی کنید. سرویس‌های دسترس‌پذیری از اشیاء AccessibilityNodeInfo پر شده توسط این روش برای بررسی سلسله‌مراتب view استفاده می‌کنند که یک رویداد دسترسی را پس از دریافت آن ایجاد می‌کند و بازخورد مناسب را برای کاربران ارائه می‌کند.

مثال کد زیر نشان می دهد که چگونه می توان این سه روش را در نمای خود نادیده گرفت:

کاتلین

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
    }
}

جاوا

@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);
    }
}

می توانید این متدها را مستقیماً در کلاس view سفارشی خود پیاده سازی کنید.

زمینه دسترسی سفارشی شده را ارائه دهید

سرویس‌های دسترس‌پذیری می‌توانند سلسله‌مراتب نمای یک مؤلفه رابط کاربری را که یک رویداد دسترس‌پذیری ایجاد می‌کند، بررسی کنند. این به خدمات دسترسی امکان می دهد اطلاعات متنی غنی تری را برای کمک به کاربران ارائه دهند.

مواردی وجود دارد که سرویس‌های دسترسی نمی‌توانند اطلاعات کافی را از سلسله مراتب مشاهده دریافت کنند. یک مثال از این یک کنترل رابط سفارشی است که دارای دو یا چند ناحیه جداگانه قابل کلیک است، مانند یک کنترل تقویم. در این حالت، سرویس‌ها نمی‌توانند اطلاعات کافی را دریافت کنند زیرا بخش‌های فرعی قابل کلیک بخشی از سلسله مراتب مشاهده نیستند.

شکل 1. نمای تقویم سفارشی با عناصر روز قابل انتخاب.

در مثال شکل 1، کل تقویم به صورت یک نمای واحد پیاده‌سازی شده است، بنابراین سرویس‌های دسترس‌پذیری اطلاعات کافی در مورد محتوای نما و انتخاب کاربر در نما دریافت نمی‌کنند، مگر اینکه توسعه‌دهنده اطلاعات اضافی ارائه دهد. به عنوان مثال، اگر کاربر روی روزی که دارای برچسب 17 است کلیک کند، چارچوب دسترس‌پذیری فقط اطلاعات توضیحات را برای کل کنترل تقویم دریافت می‌کند. در این مورد، سرویس دسترس‌پذیری TalkBack «تقویم» یا «تقویم آوریل» را اعلام می‌کند و کاربر نمی‌داند چه روزی انتخاب شده است.

برای ارائه اطلاعات زمینه کافی برای خدمات دسترسی در شرایطی مانند این، چارچوب راهی برای تعیین سلسله مراتب نمای مجازی ارائه می دهد. سلسله مراتب نمای مجازی راهی برای توسعه دهندگان برنامه است تا سلسله مراتب نمای تکمیلی را برای سرویس های دسترسی ارائه کنند که بیشتر با اطلاعات روی صفحه مطابقت دارد. این رویکرد به خدمات دسترس پذیری اجازه می دهد تا اطلاعات زمینه مفیدتری را به کاربران ارائه دهند.

موقعیت دیگری که در آن ممکن است به یک سلسله مراتب نمای مجازی نیاز باشد، یک رابط کاربری حاوی مجموعه ای از کنترل های View است که عملکردهای نزدیک به هم دارند، جایی که یک عمل بر روی یک کنترل بر محتویات یک یا چند عنصر تأثیر می گذارد - مانند جمع کننده اعداد با جدا کردن و دکمه های پایین در این مورد، سرویس‌های دسترس‌پذیری نمی‌توانند اطلاعات کافی را دریافت کنند، زیرا یک عملکرد روی یک کنترل، محتوا را در کنترل دیگر تغییر می‌دهد و ممکن است ارتباط آن کنترل‌ها برای سرویس آشکار نباشد.

برای رسیدگی به این وضعیت، کنترل‌های مرتبط را با یک نمای شامل گروه‌بندی کنید و یک سلسله‌مراتب نمای مجازی از این کانتینر ارائه کنید تا اطلاعات و رفتار ارائه‌شده توسط کنترل‌ها را به وضوح نشان دهد.

برای ارائه یک سلسله مراتب نمای مجازی برای یک view، متد getAccessibilityNodeProvider() را در نمای سفارشی یا گروه view خود لغو کنید و پیاده سازی AccessibilityNodeProvider را برگردانید. شما می توانید یک سلسله مراتب نمای مجازی را با استفاده از کتابخانه پشتیبانی با متد ViewCompat.getAccessibilityNodeProvider() پیاده سازی کنید و یک پیاده سازی با AccessibilityNodeProviderCompat ارائه دهید.

برای ساده کردن کار ارائه اطلاعات به سرویس‌های دسترس‌پذیری و مدیریت تمرکز دسترس‌پذیری، می‌توانید در عوض ExploreByTouchHelper پیاده‌سازی کنید. این یک AccessibilityNodeProviderCompat را ارائه می‌کند و می‌تواند با فراخوانی setAccessibilityDelegate به عنوان AccessibilityDelegateCompat یک View پیوست شود. برای مثال، ExploreByTouchHelperActivity را ببینید. ExploreByTouchHelper همچنین توسط ویجت های چارچوب مانند CalendarView از طریق نمای فرزند SimpleMonthView استفاده می شود.

رویدادهای لمسی سفارشی را مدیریت کنید

کنترل‌های نمای سفارشی ممکن است به رفتار رویداد لمسی غیر استاندارد نیاز داشته باشند، همانطور که در مثال‌های زیر نشان داده شده است.

اقدامات مبتنی بر کلیک را تعریف کنید

اگر ویجت شما از رابط OnClickListener یا OnLongClickListener استفاده می کند، سیستم عملکردهای ACTION_CLICK و ACTION_LONG_CLICK را برای شما انجام می دهد. اگر برنامه شما از ویجت سفارشی‌سازی‌شده‌تری استفاده می‌کند که به رابط OnTouchListener متکی است، کنترل‌کننده‌های سفارشی را برای اقدامات دسترسی مبتنی بر کلیک تعریف کنید. برای انجام این کار، همانطور که در قطعه کد زیر نشان داده شده است، متد replaceAccessibilityAction() را برای هر عمل فراخوانی کنید:

کاتلین

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()
    }
}

جاوا

@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() شما را فراخوانی کند. مثال کد زیر این الگو را نشان می دهد.

کاتلین

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
    }
}

جاوا

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() برای ایجاد یک رویداد دسترس‌پذیری و ارائه یک نقطه ورودی برای سرویس‌های دسترس‌پذیری که از طرف کاربری که رویداد کلیک سفارشی را انجام می‌دهد، عمل کنند.