עקרונות לשיפור הנגישות של אפליקציות

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

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

  • TalkBack: היא עוזרת לאנשים עם ליקויי ראייה או עיוורים. היא מכריזה על תוכן קול מסונתז ומבצע פעולות באפליקציה בתגובה לתנועות של משתמשים.
  • גישה באמצעות מתג: שעוזר לאנשים עם מוגבלויות מוטוריות. הוא מדגיש רכיבים אינטראקטיביים ומבצע פעולות בתגובה ללחיצה של המשתמש על לחצן. היא מאפשרת לשלוט במכשיר באמצעות לחצן אחד או שניים בלבד.

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

כל אחת מהשיטות המומלצות הבאות מתוארת בסעיפים הבאים, יכול לשפר עוד יותר את הנגישות של האפליקציה:

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

רכיבי תווית

חשוב לספק למשתמשים תוויות שימושיות ותיאוריות לכל רכיב בממשק משתמש אינטראקטיבי באפליקציה שלך. כל תווית צריכה להסביר את המשמעות למטרה של אלמנט מסוים. קוראי מסך כמו TalkBack יכולים להכריז את התוויות האלה למשתמשים.

ברוב המקרים, מציינים תיאור של רכיב בממשק המשתמש בפריסה קובץ המשאב שמכיל את הרכיב. בדרך כלל מוסיפים תוויות באמצעות המאפיין 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" ... />

רכיבים באוסף

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

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

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

Kotlin

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

Java

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

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

לדוגמה, אם האפליקציה מאפשרת למשתמשים להחליק על פריט, אפשר גם לחשוף את הפונקציונליות באמצעות פעולת נגישות מותאמת אישית, כמו:

Kotlin

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
}

Java

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 action’s 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
)

Java

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 בכיתה. כך, הנגישות ב-Android framework מספק את רוב יכולות הנגישות המחלקה TriSwitch צריך:

  • פעולות בנושא נגישות: מידע למערכת לגבי אופן הנגישות שירותים יכולים לחקות כל קלט אפשרי של משתמש שמבוצע ב-TriSwitch לאובייקט. (עברה בירושה מ-View).
  • אירועי נגישות: מידע לגבי שירותי נגישות לגבי כל הדרך שבה המראה של אובייקט TriSwitch יכול להשתנות כאשר המסך מתבצע רענון או עדכונים. (עברה בירושה מ-View).
  • מאפיינים: פרטים על כל אובייקט TriSwitch, כמו תוכן של כל טקסט שמוצג. (עברה בירושה מ-TextView).
  • פרטי מצב: תיאור המצב הנוכחי של אובייקט TriSwitch, כמו 'סומן' או 'לא מסומן'. (עברה בירושה מ-CompoundButton).
  • תיאור טקסט של מדינה: הסבר מבוסס-טקסט לגבי כל מדינה שמייצגת. (עברה בירושה מ-Switch).

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

הגדרת אירועים מותאמים אישית

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

הנחיה כללית היא שעבור כל קריאה חוזרת מבוססת-תצוגה שמבטלים, צריך גם להגדיר מחדש את פעולת הנגישות המתאימה על ידי ביטול ViewCompat.replaceAccessibilityAction() בבדיקות של האפליקציה, אפשר לאמת את ההתנהגות של הפעולות האלה שהוגדרו מחדש על ידי שיחות ViewCompat.performAccessibilityAction()

איך העיקרון הזה יכול לפעול באובייקטים של TriSwitch

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

Kotlin

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

Java

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

שימוש ברמזים שאינם צבע

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

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

איור 1. דוגמאות ליצירת רכיבי ממשק משתמש באמצעות צבע בלבד (בצד ימין) ושימוש בצבע, בצורות ובטקסט (בצד ימין).

שיפור הנגישות של תוכן מדיה

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

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

מקורות מידע נוספים

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

שיעורי Lab

פוסטים בבלוגים