اصولی برای بهبود دسترسی به اپلیکیشن

برای کمک به کاربران با نیازهای دسترس‌پذیری، چارچوب Android به شما امکان می‌دهد یک سرویس دسترس‌پذیری ایجاد کنید که می‌تواند محتوا را از برنامه‌ها به کاربران ارائه کند و همچنین برنامه‌ها را از طرف آنها اجرا کند.

Android چندین سرویس دسترسی به سیستم را ارائه می دهد، از جمله موارد زیر:

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

برای کمک به افرادی که نیازهای دسترس‌پذیری دارند از برنامه شما با موفقیت استفاده کنند، برنامه شما باید از بهترین شیوه‌های شرح‌داده‌شده در این صفحه پیروی کند که بر اساس دستورالعمل‌های توضیح‌داده‌شده در دسترسی بیشتر برنامه‌ها است .

هر یک از این بهترین شیوه‌ها که در بخش‌های بعدی توضیح داده شده‌اند، می‌توانند دسترسی برنامه شما را بیشتر بهبود بخشند:

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

عناصر برچسب

مهم است که برچسب‌های مفید و توصیفی را برای هر عنصر رابط کاربری تعاملی در برنامه خود در اختیار کاربران قرار دهید. هر برچسب باید معنی و هدف یک عنصر خاص را توضیح دهد. صفحه‌خوان‌هایی مانند TalkBack می‌توانند این برچسب‌ها را به کاربران اعلام کنند.

در بیشتر موارد، توضیحات یک عنصر UI را در فایل منبع طرح‌بندی که حاوی عنصر است، مشخص می‌کنید. معمولاً، همانطور که در راهنمای در دسترس‌تر کردن برنامه‌ها توضیح داده شده است، برچسب‌ها را با استفاده از ویژگی contentDescription اضافه می‌کنید. چندین تکنیک برچسب گذاری دیگر نیز در بخش های زیر توضیح داده شده است.

عناصر قابل ویرایش

هنگام برچسب‌گذاری عناصر قابل ویرایش، مانند اشیاء EditText ، نشان دادن متنی که نمونه‌ای از ورودی معتبر را در خود عنصر ارائه می‌دهد، مفید است، علاوه بر این که این متن نمونه در دسترس خوانندگان صفحه نمایش قرار می‌گیرد. در این مواقع، همانطور که در قطعه زیر نشان داده شده است، می توانید از ویژگی android:hint استفاده کنید:

<!-- The hint text for en-US locale would be
     "Apartment, suite, or building". -->
<EditText
   android:id="@+id/addressLine2"
   android:hint="@string/aptSuiteBuilding" ... />

در این شرایط، شی View باید ویژگی android:labelFor خود را روی شناسه عنصر EditText تنظیم کند. برای جزئیات بیشتر به بخش زیر مراجعه کنید.

جفت عناصری که یکی دیگری را توصیف می کند

معمول است که یک عنصر EditText یک شی View متناظر داشته باشد که توصیف می کند کاربران باید چه چیزی را در عنصر EditText وارد کنند. می توانید این رابطه را با تنظیم ویژگی android:labelFor شیء View نشان دهید.

نمونه ای از برچسب زدن چنین جفت عناصر در قطعه زیر ظاهر می شود:

<!-- Label text for en-US locale would be "Username:" -->
<TextView
   android:id="@+id/usernameLabel" ...
   android:text="@string/username"
   android:labelFor="@+id/usernameEntry" />

<EditText
   android:id="@+id/usernameEntry" ... />

<!-- Label text for en-US locale would be "Password:" -->
<TextView
   android:id="@+id/passwordLabel" ...
   android:text="@string/password
   android:labelFor="@+id/passwordEntry" />

<EditText
   android:id="@+id/passwordEntry"
   android:inputType="textPassword" ... />

عناصر در یک مجموعه

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

به طور خاص، متن اضافی یا اطلاعات متنی را در عناصر موجود در طرح‌بندی‌های مورد استفاده مجدد - مانند اشیاء RecyclerView - بگنجانید تا هر عنصر فرزند به‌طور منحصربه‌فرد شناسایی شود.

برای انجام این کار، شرح محتوا را به عنوان بخشی از اجرای آداپتور خود تنظیم کنید، همانطور که در قطعه کد زیر نشان داده شده است:

کاتلین

data class MovieRating(val title: String, val starRating: Integer)

class MyMovieRatingsAdapter(private val myData: Array<MovieRating>):
        RecyclerView.Adapter<MyMovieRatingsAdapter.MyRatingViewHolder>() {

    class MyRatingViewHolder(val ratingView: ImageView) :
            RecyclerView.ViewHolder(ratingView)

    override fun onBindViewHolder(holder: MyRatingViewHolder, position: Int) {
        val ratingData = myData[position]
        holder.ratingView.contentDescription = "Movie ${position}: " +
                "${ratingData.title}, ${ratingData.starRating} stars"
    }
}

جاوا

public class MovieRating {
    private String title;
    private int starRating;
    // ...
    public String getTitle() { return title; }
    public int getStarRating() { return starRating; }
}

public class MyMovieRatingsAdapter
        extends RecyclerView.Adapter<MyAdapter.MyRatingViewHolder> {
    private MovieRating[] myData;


    public static class MyRatingViewHolder extends RecyclerView.ViewHolder {
        public ImageView ratingView;
        public MyRatingViewHolder(ImageView iv) {
            super(iv);
            ratingView = iv;
        }
    }

    @Override
    public void onBindViewHolder(MyRatingViewHolder holder, int position) {
        MovieRating ratingData = myData[position];
        holder.ratingView.setContentDescription("Movie " + position + ": " +
                ratingData.getTitle() + ", " + ratingData.getStarRating() +
                " stars")
    }
}

گروه های محتوای مرتبط

اگر برنامه شما چندین عنصر رابط کاربری را نشان می‌دهد که یک گروه طبیعی را تشکیل می‌دهند، مانند جزئیات یک آهنگ یا ویژگی‌های یک پیام، این عناصر را در یک ظرف مرتب کنید که معمولاً زیر کلاس ViewGroup است. ویژگی android:screenReaderFocusable شی ظرف را روی true و ویژگی android:focusable هر شیء داخلی را روی false تنظیم کنید. به این ترتیب، سرویس‌های دسترسی می‌توانند توضیحات محتوای عناصر درونی را یکی پس از دیگری در یک اعلامیه ارائه دهند. این ادغام عناصر مرتبط به کاربران فناوری کمکی کمک می کند تا اطلاعات روی صفحه را به طور موثرتری کشف کنند.

قطعه زیر حاوی تکه‌هایی از محتوا است که به یکدیگر مربوط می‌شوند، بنابراین عنصر کانتینر، نمونه‌ای از ConstraintLayout ، دارای android:screenReaderFocusable است که روی true تنظیم شده است و عناصر TextView داخلی هر کدام دارای ویژگی android:focusable که روی false تنظیم شده‌اند:

<!-- In response to a single user interaction, accessibility services announce
     both the title and the artist of the song. -->
<ConstraintLayout
    android:id="@+id/song_data_container" ...
    android:screenReaderFocusable="true">

    <TextView
        android:id="@+id/song_title" ...
        android:focusable="false"
        android:text="@string/my_song_title" />
    <TextView
        android:id="@+id/song_artist"
        android:focusable="false"
        android:text="@string/my_songwriter" />
</ConstraintLayout>

از آنجایی که سرویس‌های دسترس‌پذیری توصیفات عناصر درونی را در یک گفتار اعلام می‌کنند، مهم است که هر توضیحی را تا حد امکان کوتاه نگه دارید و در عین حال معنای عنصر را منتقل کنید.

توجه: به طور کلی، باید از ایجاد توضیحات محتوایی برای یک گروه با تجمیع متن فرزندان آن اجتناب کنید. انجام این کار باعث می شود توضیحات گروه شکننده باشد و وقتی متن فرزند تغییر می کند، ممکن است توضیحات گروه دیگر با متن قابل مشاهده مطابقت نداشته باشد.

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

گروه های تو در تو

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

قطعه کد زیر یک روش برای برچسب زدن گروه ها در داخل گروه های بزرگتر را نشان می دهد:

<!-- In response to a single user interaction, accessibility services
     announce the events for a single stage only. -->
<ConstraintLayout
    android:id="@+id/festival_event_table" ... >
    <ConstraintLayout
        android:id="@+id/stage_a_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage A. -->

    </ConstraintLayout>
    <ConstraintLayout
        android:id="@+id/stage_b_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage B. -->

    </ConstraintLayout>
</ConstraintLayout>

عنوان در متن

برخی از برنامه ها از عناوین برای خلاصه کردن گروه های متنی که روی صفحه نمایش ظاهر می شوند استفاده می کنند. اگر یک عنصر View خاص یک عنوان را نشان می‌دهد، می‌توانید با تنظیم ویژگی android:accessibilityHeading عنصر، هدف آن را برای خدمات دسترس‌پذیری true کنید.

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

عناوین قاب دسترسی

در Android 9 (سطح API 28) و بالاتر، می‌توانید عناوین سازگار با قابلیت دسترسی را برای صفحه‌های صفحه ارائه کنید. برای اهداف دسترس‌پذیری، یک صفحه یک بخش بصری مجزا از یک پنجره است، مانند محتوای یک قطعه. برای اینکه سرویس‌های دسترس‌پذیری رفتار پنجره‌مانند یک صفحه را درک کنند، عناوین توصیفی را به پنجره‌های برنامه خود بدهید. هنگامی که ظاهر یا محتوای یک صفحه تغییر می کند، سرویس های دسترسی می توانند اطلاعات دقیق تری را به کاربران ارائه دهند.

برای تعیین عنوان یک صفحه، از ویژگی android:accessibilityPaneTitle استفاده کنید، همانطور که در قطعه زیر نشان داده شده است:

<!-- Accessibility services receive announcements about content changes
     that are scoped to either the "shopping cart view" section (top) or
     "browse items" section (bottom) -->
<MyShoppingCartView
     android:id="@+id/shoppingCartContainer"
     android:accessibilityPaneTitle="@string/shoppingCart" ... />

<MyShoppingBrowseView
     android:id="@+id/browseItemsContainer"
     android:accessibilityPaneTitle="@string/browseProducts" ... />

عناصر تزئینی

اگر عنصری در رابط کاربری شما فقط برای فاصله بصری یا اهداف ظاهری بصری وجود دارد، ویژگی android:importantForAccessibility آن را روی "no" تنظیم کنید.

اقدامات دسترس‌پذیری را اضافه کنید

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

همه اقدامات را در دسترس قرار دهید

ممکن است کاربر TalkBack، Voice Access یا Switch Access به روش‌های جایگزینی برای تکمیل جریان‌های کاربر خاص در برنامه نیاز داشته باشد. برای اقدامات مرتبط با حرکات مانند کشیدن و رها کردن یا کشیدن انگشت، برنامه شما می‌تواند عملکردها را به گونه‌ای نمایش دهد که برای کاربران سرویس‌های دسترس‌پذیری قابل دسترسی باشد.

با استفاده از کنش‌های دسترس‌پذیری ، برنامه می‌تواند راه‌های جایگزینی برای تکمیل یک اقدام برای کاربران فراهم کند.

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

کاتلین

ViewCompat.addAccessibilityAction(
    // View to add accessibility action
    itemView,
    // Label surfaced to user by an accessibility service
    getText(R.id.archive)
) { _, _ ->
    // Same method executed when swiping on itemView
    archiveItem()
    true
}

جاوا

ViewCompat.addAccessibilityAction(
    // View to add accessibility action
    itemView,
    // Label surfaced to user by an accessibility service
    getText(R.id.archive),
    (view, arguments) -> {
        // Same method executed when swiping on itemView
        archiveItem();
        return true;
    }
);

With the custom accessibility action implemented, users can access the action through the actions menu.

Make available actions understandable

When a view supports actions such as touch & hold, an accessibility service such as TalkBack announces it as "Double tap and hold to long press."

This generic announcement doesn't give the user any context about what a touch & hold action does.

To make this announcement more descriptive, you can replace the accessibility actions announcement like so:

Kotlin

ViewCompat.replaceAccessibilityAction(
    // View that contains touch & hold action
    itemView,
    AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_LONG_CLICK,
    // Announcement read by TalkBack to surface this action
    getText(R.string.favorite),
    null
)

جاوا

ViewCompat.replaceAccessibilityAction(
    // View that contains touch & hold action
    itemView,
    AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_LONG_CLICK,
    // Announcement read by TalkBack to surface this action
    getText(R.string.favorite),
    null
);

This results in TalkBack announcing "Double tap and hold to favorite," helping users understand the purpose of the action.

Extend system widgets

Note: When you design your app's UI, use or extend system-provided widgets that are as far down Android's class hierarchy as possible. System-provided widgets that are far down the hierarchy already have most of the accessibility capabilities your app needs. It's easier to extend these system-provided widgets than to create your own from the more generic View, ViewCompat, Canvas, and CanvasCompat classes.

If you must extend View or Canvas directly, which might be necessary for a highly customized experience or a game level, see Make custom views more accessible.

This section uses the example of implementing a special type of Switch called TriSwitch while following best practices around extending system widgets. A TriSwitch object works similarly to a Switch object, except that each instance of TriSwitch allows the user to toggle among three possible states.

Extend from far down the class hierarchy

The Switch object inherits from several framework UI classes in its hierarchy:

View
 TextView
   Button
     CompoundButton
       Switch

بهتر است کلاس جدید TriSwitch مستقیماً از کلاس Switch گسترش یابد. به این ترتیب، چارچوب دسترس‌پذیری اندروید بیشتر قابلیت‌های دسترسی مورد نیاز کلاس TriSwitch را فراهم می‌کند:

  • اقدامات دسترس‌پذیری: اطلاعاتی برای سیستم در مورد اینکه چگونه سرویس‌های دسترسی می‌توانند هر ورودی احتمالی کاربر را که روی یک شی TriSwitch انجام می‌شود شبیه‌سازی کنند. (به ارث رسیده از View .)
  • رویدادهای دسترس‌پذیری: اطلاعاتی برای سرویس‌های دسترس‌پذیری درباره هر راه ممکنی که ظاهر یک شی TriSwitch می‌تواند در هنگام تازه‌سازی یا به‌روزرسانی صفحه تغییر کند. (به ارث رسیده از View .)
  • ویژگی ها: جزئیات مربوط به هر شی TriSwitch ، مانند محتوای هر متنی که نمایش می دهد. (به ارث رسیده از TextView .)
  • اطلاعات وضعیت: شرح وضعیت فعلی یک شی TriSwitch ، مانند "تیک خورده" یا "برگزیده نشده". (به ارث رسیده از CompoundButton .)
  • شرح متنی حالت: توضیحی مبتنی بر متن از آنچه هر حالت نشان می دهد. (به ارث رسیده از Switch .)

این رفتار از Switch و سوپرکلاس های آن تقریباً همان رفتار اشیاء TriSwitch است. بنابراین، اجرای شما می تواند بر گسترش تعداد حالت های ممکن از دو به سه تمرکز کند.

تعریف رویدادهای سفارشی

هنگامی که ویجت سیستم را گسترش می دهید، احتمالاً جنبه ای از نحوه تعامل کاربران با آن ویجت را تغییر می دهید. بسیار مهم است که این تغییرات تعاملی را تعریف کنید تا سرویس‌های دسترس‌پذیری بتوانند ویجت برنامه شما را به‌روزرسانی کنند، گویی کاربر مستقیماً با ویجت تعامل دارد.

یک دستورالعمل کلی این است که برای هر بازخوانی مبتنی بر view که لغو می‌کنید، همچنین باید با نادیده گرفتن ViewCompat.replaceAccessibilityAction() ، عملکرد دسترسی مربوطه را دوباره تعریف کنید. در آزمایش‌های برنامه‌تان، می‌توانید با فراخوانی ViewCompat.performAccessibilityAction() رفتار این اقدامات بازتعریف شده را تأیید کنید.

چگونه این اصل می تواند برای اشیاء TriSwitch کار کند

بر خلاف یک شی Switch معمولی، ضربه زدن روی یک شی TriSwitch در سه حالت ممکن چرخه می‌شود. بنابراین، عملکرد دسترسی ACTION_CLICK مربوطه باید به‌روزرسانی شود:

کاتلین

class TriSwitch(context: Context) : Switch(context) {
    // 0, 1, or 2
    var currentState: Int = 0
        private set

    init {
        updateAccessibilityActions()
    }

    private fun updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label) {
            view, args -> moveToNextState()
        })
    }

    private fun moveToNextState() {
        currentState = (currentState + 1) % 3
    }
}

جاوا

public class TriSwitch extends Switch {
    // 0, 1, or 2
    private int currentState;

    public int getCurrentState() {
        return currentState;
    }

    public TriSwitch() {
        updateAccessibilityActions();
    }

    private void updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label, (view, args) -> moveToNextState());
    }

    private void moveToNextState() {
        currentState = (currentState + 1) % 3;
    }
}

از نشانه هایی غیر از رنگ استفاده کنید

برای کمک به کاربران با کمبود دید رنگی، از نشانه هایی غیر از رنگ برای تشخیص عناصر UI در صفحه نمایش برنامه خود استفاده کنید. این تکنیک‌ها می‌تواند شامل استفاده از اشکال یا اندازه‌های مختلف، ارائه الگوهای متنی یا بصری، یا افزودن بازخورد صوتی یا لمسی (هپتیک) برای مشخص کردن تفاوت‌های عناصر باشد.

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

شکل 1. نمونه هایی از ایجاد عناصر UI فقط با استفاده از رنگ (سمت چپ) و با استفاده از رنگ، اشکال و متن (راست).

محتوای رسانه ای را در دسترس تر کنید

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

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

منابع اضافی

برای کسب اطلاعات بیشتر در مورد دسترسی بیشتر برنامه خود، به منابع اضافی زیر مراجعه کنید:

Codelabs

پست های وبلاگ