אם הבקשה מחייבת ברכיב של תצוגה בהתאמה אישית עליך להפוך את התצוגה לנגישה יותר. השלבים הבאים יכולים לשפר את התצוגה המותאמת אישית נגישות, כפי שמתואר בדף הזה:
- טיפול בקליקים מכוונים של השלט רחוק.
- הטמעת שיטות של ממשק 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()
TYPE_VIEW_CLICKED
TYPE_VIEW_FOCUSED
TYPE_VIEW_HOVER_ENTER
TYPE_VIEW_HOVER_EXIT
TYPE_VIEW_LONG_CLICKED
TYPE_VIEW_SCROLLED
- צריך ליצור
AccessibilityEvent
מתאים לפעולת הקליק המפוענחת. - יש להפעיל את שירותי הנגישות כדי לבצע את פעולת הקליק המותאמת אישית עבור משתמשים שלא יכולים להשתמש במסך מגע.
כדי לתמוך בנגישות, ניתן לבטל ולהטמיע את שיטות הנגישות הקודמות ישירות את הכיתה בהתאמה אישית של התצוגה.
לכל הפחות, צריך להטמיע את שיטות הנגישות הבאות עבור המחלקה של התצוגה המפורטת בהתאמה אישית:
למידע נוסף על יישום השיטות האלה, עיינו בקטע על אכלוס אירועי נגישות.
שליחת אירועי נגישות
בהתאם לפרטים של התצוגה המותאמת אישית, ייתכן שיהיה צורך לשלוח
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, כל היומן מוצג כתצוגה אחת, לכן הנגישות השירותים אינם מקבלים מספיק מידע על תוכן התצוגה ועל בחירת המשתמש בתצוגה, אלא אם המפתח מספק מידע נוסף. לדוגמה, אם משתמש לוחץ ביום 17, מסגרת הנגישות תקבל רק את פרטי התיאור לכל פקד היומן. במקרה כזה, שירות הנגישות TalkBack יכריז יומן או "יומן אפריל", והמשתמש לא יודע איזה יום נבחר.
כדי לספק הקשר הולם לשירותי הנגישות במצבים כאלה, ה-framework מאפשר לציין היררכיית תצוגה וירטואלית. היררכיית תצוגה וירטואלית היא שמאפשרת למפתחי אפליקציות לספק היררכיית תצוגה משלימה לשירותי הנגישות, תואם במידה רבה למידע על המסך. הגישה הזו מאפשרת לשירותי הנגישות לספק יותר מידע שימושי על ההקשר למשתמשים.
מצב נוסף שבו ייתכן שיהיה צורך בהיררכיית תצוגה וירטואלית הוא ממשק משתמש שכולל
קבוצה של פקדים מסוג View
שיש להם פונקציות בעלות קשר הדוק, כאשר פעולה על אחת מהן
משפיעה על התוכן של רכיב אחד או יותר, כמו בוחר מספרים עם
ולמטה. במקרה כזה, שירותי הנגישות לא יכולים לקבל מידע הולם כי
פעולה בבקרה אחת משנה תוכן בבקרה אחרת, וייתכן שהקשר בין אמצעי הבקרה האלה לא ישתנה
יהיה ברור לשירות.
כדי לטפל במצב הזה, צריך לקבץ את הפקדים הקשורים באמצעות תצוגה מכילה ולספק ערך וירטואלי את ההיררכיה של מאגר התגים הזה כדי לייצג בבירור את המידע וההתנהגות שמסופקים הפקדים בנגן.
כדי לספק היררכיית תצוגה וירטואלית לתצוגה מפורטת, מבטלים את
getAccessibilityNodeProvider()
בתצוגה המותאמת אישית או בקבוצת התצוגה המפורטת, ולהחזיר יישום של
AccessibilityNodeProvider
.
אפשר להשתמש בספריית התמיכה כדי להטמיע היררכיית תצוגה וירטואלית,
ViewCompat.getAccessibilityNodeProvider()
ונספק הטמעה באמצעות
AccessibilityNodeProviderCompat
.
כדי לפשט את המשימה של מתן מידע לשירותי נגישות וניהול
את התמקדות בנגישות, אפשר במקום זאת
ExploreByTouchHelper
היא מספקת AccessibilityNodeProviderCompat
וניתן לצרף אותה כתצוגה מפורטת
AccessibilityDelegateCompat
בהתקשרות
setAccessibilityDelegate
.
לדוגמה, אפשר להיכנס אל
ExploreByTouchHelperActivity
המאפיין ExploreByTouchHelper
משמש גם בווידג'טים של framework כמו
CalendarView
, דרך
תצוגת צאצא
SimpleMonthView
.
טיפול באירועי מגע בהתאמה אישית
ייתכן שכדי להשתמש בפקדי התצוגה בהתאמה אישית יש צורך בהתנהגות לא סטנדרטית של אירועי מגע, כמו שאפשר לראות בדוגמאות הבאות.
הגדרת פעולות מבוססות-קליקים
אם בווידג'ט נעשה שימוש
OnClickListener
או
OnLongClickListener
הוא יטפל
ACTION_CLICK
וגם
ACTION_LONG_CLICK
פעולות מסוימות. אם האפליקציה שלך משתמשת בווידג'ט מותאם אישית המסתמך על
בממשק של OnTouchListener
,
להגדיר handlers מותאמים אישית לפעולות הנגישות שמבוססות על קליקים. כדי לעשות זאת,
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)
שיטת ה-listener לזיהוי
ACTION_DOWN
והקבוצה
ACTION_UP
אירועים ו-
שיפעיל אירוע קליק מיוחד. כדי לשמור על תאימות לשירותי נגישות, הקוד
מטפל באירוע קליק מותאם אישית זה חייב לבצע את הפעולות הבאות:
כדי לטפל בדרישות האלה ביעילות, הקוד צריך לבטל את
אמצעי תשלום אחד (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()
כדי ליצור אירוע נגישות
לספק נקודת כניסה לשירותי הנגישות לפעול בשם המשתמש שמבצע את ההגדרה
אירוע מסוג קליק.