כברירת מחדל, ממשק המשתמש של Material, Compose API וממשקי Foundation API כוללים שיטות נגישות רבות. הם מכילים סמנטיקה מובנית שתואמת לתפקיד ולפונקציה הספציפיים שלהם, כך שרוב התמיכה בנגישות ניתנת ללא צורך בעבודה נוספת או כמעט ללא צורך בעבודה נוספת.
השימוש בממשקי ה-API המתאימים למטרה המתאימה בדרך כלל כולל רכיבים עם התנהגויות מוגדרות מראש של נגישות שמכסות תרחישים לדוגמה רגילים, אבל חשוב לבדוק שוב אם הגדרות ברירת המחדל האלה מתאימות לצרכים שלכם בנושא נגישות. אם לא, אפשר להשתמש ב-Compose גם כדי לעמוד בדרישות ספציפיות יותר.
מומלץ להכיר את סמנטיקה ודפוסי ברירת המחדל של הנגישות בממשקי ה-API של Compose, כדי להבין איך להשתמש בהם תוך התחשבות בנגישות, וגם כדי לתמוך בנגישות ברכיבים מותאמים אישית יותר.
גדלים מינימליים של יעדי מגע
כל אלמנט שמופיע במסך שמשתמשים יכולים ללחוץ עליו, לגעת בו או לבצע איתו אינטראקציה, צריך להיות גדול מספיק כדי לאפשר אינטראקציה אמינה. כשמגדירים את הגודל של הרכיבים האלה, חשוב להגדיר את הגודל המינימלי ל-48dp כדי לפעול בהתאם להנחיות הנגישות של Material Design.
רכיבי Material – כמו Checkbox
, RadioButton
, Switch
, Slider
ו-Surface
– מגדירים את הגודל המינימלי הזה באופן פנימי, אבל רק כשהרכיב יכול לקבל פעולות של משתמשים. לדוגמה, כשהפרמטר onCheckedChange
של תג Checkbox
מוגדר לערך שאינו null, תיבת הסימון כוללת ריפוד כך שהרוחב והגובה שלה יהיו לפחות 48dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

כשהפרמטר onCheckedChange
מוגדר כ-null, המילוי לא נכלל כי אי אפשר לבצע אינטראקציה ישירה עם הרכיב.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

כשמטמיעים אמצעי בקרה לבחירה כמו Switch
, RadioButton
או Checkbox
, בדרך כלל מעבירים את ההתנהגות הקליקבילית לקונטיינר הורה על ידי הגדרת הפונקציה הלא סטטית (callback) של הקליק בתוכן הקומפוזבילי ל-null
, והוספת המשתנה toggleable
או selectable
לתוכן הקומפוזבילי ההורה.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }

אם הגודל של רכיב קומפוזיציה שניתן ללחוץ עליו קטן מהגודל המינימלי של יעד המגע, Compose עדיין מגדיל את גודל יעד המגע. כדי לעשות זאת, המערכת מרחיבה את גודל היעד למגע מחוץ לגבולות של הרכיב הניתן לקישור.
הדוגמה הבאה מכילה Box
קטן מאוד שניתן ללחוץ עליו. אזור היעד למגע מורחב באופן אוטומטי מעבר לגבולות של Box
, כך שהקשה ליד Box
עדיין מפעילה את אירוע הקליק.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }

כדי למנוע חפיפה אפשרית בין אזורי המגע של רכיבים מורכבים שונים, תמיד צריך להשתמש בגודל מינימלי גדול מספיק לרכיב המורכב. בדוגמה הזו, המשמעות היא שימוש במשתנה המשנה sizeIn
כדי להגדיר את הגודל המינימלי של התיבה הפנימית:
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }

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

על סמך הסמל בלבד, מסגרת Android לא יכולה לתאר אותו למשתמש עם לקות ראייה. ל-Android Framework נדרש תיאור טקסטואלי נוסף של הסמל.
הפרמטר contentDescription
מתאר אלמנט גרפי. צריך להשתמש במחרוזת מותאמת לאזור, כי היא גלויה למשתמש.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
חלק מהאלמנטים הגרפיים הם פשוט דקורטיביים, ויכול להיות שלא תרצו להעביר אותם למשתמש. כשמגדירים את הפרמטר contentDescription
לערך null
, מציינים למסגרת Android שאין לאלמנט הזה פעולות או מצב משויכים.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription
מיועד בעיקר לשימוש ברכיבים גרפיים, כמו תמונות. רכיבי Material, כמו Button
או Text
, והתנהגויות שניתן לבצע עליהן פעולה, כמו clickable
או toggleable
, מגיעים עם סמנטיקה מוגדרת מראש שמתארת את ההתנהגות המובנית שלהם, ואפשר לשנות אותה באמצעות ממשקי API אחרים של Compose.
אלמנטים אינטראקטיביים
ממשקי ה-API של Material ו-Foundation Compose יוצרים רכיבי ממשק משתמש שמשתמשים יכולים לקיים איתם אינטראקציה דרך ממשקי ה-API של המשתנים clickable
ו-toggleable
. מכיוון שרכיבים שניתן לקיים איתם אינטראקציה עשויים להכיל כמה אלמנטים, clickable
ו-toggleable
ממזגים את הסמנטיקה של הצאצאים שלהם כברירת מחדל, כך שהרכיב מטופל כישות לוגית אחת.
לדוגמה, חומר Button
עשוי להכיל סמל של צאצא וטקסט כלשהו.
במקום להתייחס לצאצאים כפרטים נפרדים, לחצן Material ממזג את הסמנטיקה של הצאצאים כברירת מחדל, כדי ששירותי הנגישות יוכלו לקבץ אותם בהתאם:

באופן דומה, שימוש במערך הערכים של המאפיין clickable
גורם גם ליצירת רכיב מורכב שממזג את הסמנטיקה של הצאצאים שלו לישות אחת, שנשלחת לשירותי הנגישות עם ייצוג פעולה תואם:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
אפשר גם להגדיר onClickLabel
ספציפי ברכיב ההורה שניתן ללחוץ עליו כדי לספק מידע נוסף לשירותי הנגישות ולהציג ייצוג משופר של הפעולה:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
לדוגמה, אם משתמשים ב-TalkBack, מקש השינוי clickable
והתוויות של הקליקים שלו יאפשרו ל-TalkBack לספק טיפים לפעולות, כמו 'הקשה כפולה כדי לפתוח את המאמר הזה', במקום משוב ברירת המחדל הכללי יותר 'הקשה כפולה כדי להפעיל'.
המשוב הזה משתנה בהתאם לסוג הפעולה. לחיצה ארוכה תספק טיפ של TalkBack עם הכיתוב 'לחיצה כפולה והחזקה כדי', ואחריו תווית:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
במקרים מסוימים, יכול להיות שאין לכם גישה ישירה למשתנה clickable
(לדוגמה, אם הוא מוגדר בשכבה עטופה נמוכה יותר),אבל אתם עדיין רוצים לשנות את תווית ההודעה מהברירת המחדל. כדי לעשות זאת, צריך לפצל את ההגדרה של clickable
מהשינוי של ההודעה באמצעות המשתנה semantics
ולהגדיר את תווית הקליק שם, כדי לשנות את ייצוג הפעולה:
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
במקרה כזה, אין צורך להעביר את פעולת הקליק פעמיים, כי ממשקי ה-Compose API הקיימים, כמו clickable
או Button
, מטפלים בזה בשבילכם. הסיבה לכך היא שלוגיק השילוב מבטיח שהתוויות והפעולות של המשנה החיצוני ביותר יילקחו בחשבון לגבי המידע הקיים.
בדוגמה הקודמת, פעולת הלחיצה openArticle()
מועברת באופן אוטומטי על ידי NestedArticleListItem
לסמנטיקה clickable
שלה, וניתן להשאיר אותה null בפעולה השנייה של שינוי הסמנטיקה. עם זאת, תווית הקליק נלקחת ממשנה הסמנטיקה השני onClick(label = "Open this article")
, כי היא לא הייתה קיימת במשנה הראשון.
יכול להיות שתתקלו בתרחישים שבהם אתם מצפים שסמנטיקה של צאצאים תתמזג עם סמנטיקה של הורה, אבל זה לא קורה. מידע מפורט יותר זמין במאמר מיזוג וניקוי.
רכיבים בהתאמה אישית
לגבי רכיבים מותאמים אישית, ככלל, כדאי לבדוק את ההטמעה של רכיב דומה בספריית Material או בספריות אחרות של Compose, ולהעתיק או לשנות את התנהגות הנגישות שלו במקרים שבהם זה הגיוני.
לדוגמה, אם מחליפים את רכיב Checkbox
של Material בהטמעה משלכם, הצגת ההטמעה הקיימת של תיבת הסימון תזכיר לכם להוסיף את המשתנה triStateToggleable
, שמטפל במאפייני הנגישות של הרכיב הזה.
בנוסף, כדאי להשתמש הרבה במודיפיקציות של Foundation, כי הן כוללות שיקולים של נגישות מוכנים לשימוש, וגם שיטות קיימות של Compose שמפורטות בקטע הזה.
דוגמה לרכיב מתג בהתאמה אישית מופיעה גם בקטע 'ניקוי והגדרה של סמנטיקה', ומידע מפורט יותר על תמיכה בנגישות ברכיבים מותאמים אישית זמין בהנחיות ל-API.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- נגישות ב-Compose
- [Material Design 2 ב-Compose][19]
- בדיקת הפריסה של 'כתיבה'