برای کمک به کاربران در رفع نیازهای دسترسی، چارچوب اندروید به شما امکان میدهد یک سرویس دسترسی ایجاد کنید که بتواند محتوا را از برنامهها به کاربران ارائه دهد و همچنین برنامهها را از طرف آنها اجرا کند.
اندروید چندین سرویس دسترسی به سیستم ارائه میدهد، از جمله موارد زیر:
- TalkBack : به افراد کمبینا یا نابینا کمک میکند. این برنامه محتوا را از طریق صدای ترکیبی اعلام میکند و در پاسخ به حرکات کاربر، اقداماتی را در برنامه انجام میدهد.
- دسترسی سوئیچ : به افرادی که دارای معلولیتهای حرکتی هستند کمک میکند. این قابلیت عناصر تعاملی را برجسته میکند و در پاسخ به فشار دادن یک دکمه توسط کاربر، اقداماتی را انجام میدهد. این قابلیت امکان کنترل دستگاه را تنها با استفاده از یک یا دو دکمه فراهم میکند.
برای کمک به افرادی که نیازهای دسترسیپذیری دارند تا بتوانند با موفقیت از برنامه شما استفاده کنند، برنامه شما باید از بهترین شیوههای شرح داده شده در این صفحه پیروی کند، که بر اساس دستورالعملهای شرح داده شده در «برنامهها را دسترسپذیرتر کنید» بنا شدهاند.
هر یک از این بهترین شیوهها، که در بخشهای بعدی توضیح داده شدهاند، میتوانند دسترسیپذیری برنامه شما را بیشتر بهبود بخشند:
- عناصر برچسب
- کاربران باید بتوانند محتوا و هدف هر عنصر رابط کاربری تعاملی و معنادار را در برنامه شما درک کنند.
- افزودن اقدامات دسترسیپذیری
- با افزودن اقدامات دسترسی، میتوانید به کاربران سرویسهای دسترسی این امکان را بدهید که جریانهای کاربری حیاتی را در برنامه شما تکمیل کنند.
- از ویژگیهای دسترسی داخلی استفاده کنید
- Compose به طور پیشفرض رفتارهای دسترسیپذیری زیادی ارائه میدهد. از رفتارهای دسترسیپذیری از پیش تعریفشده برای دسترسیپذیر کردن اجزای خود با کمترین یا بدون هیچ کار اضافی استفاده کنید. Compose همچنین راههایی برای پشتیبانی از الزامات دسترسیپذیری خاصتری که توسط ویژگیهای پیشفرض پوشش داده نمیشوند، ارائه میدهد.
- از نشانههایی غیر از رنگ استفاده کنید
- کاربران باید بتوانند به وضوح بین دستههای عناصر در یک رابط کاربری تمایز قائل شوند. برای انجام این کار، از الگوها و موقعیتها، همراه با رنگ، برای بیان این تفاوتها استفاده کنید.
- محتوای رسانهای را در دسترستر کنید
- به محتوای ویدیویی یا صوتی برنامه خود توضیحات اضافه کنید تا کاربرانی که این محتوا را مصرف میکنند، نیازی به تکیه بر نشانههای کاملاً بصری یا شنیداری نداشته باشند.
عناصر برچسب
ارائه برچسبهای مفید و توصیفی برای هر عنصر رابط کاربری تعاملی در برنامه شما به کاربران بسیار مهم است. هر برچسب باید معنای یک عنصر خاص - یعنی معنی و هدف آن عنصر - را توضیح دهد. برنامههای صفحهخوان مانند TalkBack میتوانند این برچسبها را به کاربران اعلام کنند.
در بیشتر موارد، APIهای Compose و Material از پشتیبانی پیشفرض برای دسترسیپذیری برخوردارند. با این حال، اگر نیاز دارید که ویژگیهای معنایی یک عنصر رابط کاربری را به صورت دستی مشخص کنید، از اصلاحکننده semantics و ویژگی contentDescription استفاده کنید. برای اطلاعات بیشتر در مورد semantics، به Semantics مراجعه کنید.
بخشهای بعدی چندین تکنیک برچسبگذاری دیگر را شرح میدهند.
عناصر قابل ویرایش
هنگام برچسبگذاری عناصر قابل ویرایش، مانند فیلدهای متنی، نمایش متنی که نمونهای از ورودی معتبر در خود عنصر را ارائه میدهد، علاوه بر در دسترس قرار دادن این متن نمونه برای خوانندگان صفحه، مفید است. در این شرایط، میتوانید از متن جایگزین، که متن راهنما نیز نامیده میشود، استفاده کنید.
در مثال زیر، TextField یک پارامتر placeholder دارد که متن راهنما را ارائه میدهد.
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
همچنین رایج است که یک فیلد متنی دارای یک برچسب توصیفی متناظر باشد که آنچه کاربران باید به عنوان ورودی وارد کنند را توصیف میکند.
در مثال زیر، TextField یک پارامتر label دارد که توضیحاتی در مورد قابلیت دسترسی ارائه میدهد.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
برای اطلاعات بیشتر در مورد متن و ورودی کاربر، به پیکربندی فیلدهای متنی مراجعه کنید.
عناصر موجود در یک مجموعه
هنگام افزودن برچسبها به عناصر یک مجموعه، هر برچسب باید منحصر به فرد باشد. به این ترتیب، سرویسهای دسترسی سیستم میتوانند هنگام اعلام یک برچسب، دقیقاً به یک عنصر روی صفحه اشاره کنند. این تطابق به کاربران اجازه میدهد تا بدانند چه زمانی در رابط کاربری میچرخند یا چه زمانی تمرکز خود را به عنصری که قبلاً کشف کردهاند، منتقل میکنند.
برای مثال، وقتی یک LazyColumn یا LazyRow دارید، از اصلاحکننده semantics برای اختصاص یک collectionItemInfo منحصر به فرد به هر آیتم استفاده کنید، همانطور که در قطعه کد زیر نشان داده شده است:
MilkyWayList( modifier = Modifier .semantics { collectionInfo = CollectionInfo( rowCount = milkyWay.count(), columnCount = 1 ) } ) { milkyWay.forEachIndexed { index, text -> Text( text = text, modifier = Modifier.semantics { collectionItemInfo = CollectionItemInfo(index, 0, 0, 0) } ) } }
برای اطلاعات بیشتر در مورد ویژگیهای معنایی لیستها و شبکهها، به اطلاعات لیست و آیتم مراجعه کنید.
گروههای محتوای مرتبط
اگر برنامه شما چندین عنصر رابط کاربری را نمایش میدهد که یک گروه طبیعی را تشکیل میدهند، مانند جزئیات یک آهنگ یا ویژگیهای یک پیام، این عناصر را درون یک کانتینر والد (مانند Column ، Row یا Box ) مرتب کنید. از اصلاحکننده semantics کانتینر والد برای تنظیم mergeDescendants به true استفاده کنید.
به این ترتیب، سرویسهای دسترسی میتوانند توضیحات محتوای عناصر داخلی را یکی پس از دیگری، در یک اعلان واحد ارائه دهند. ادغام عناصر مرتبط به کاربران فناوری کمکی کمک میکند تا اطلاعات روی صفحه را به طور مؤثرتری کشف کنند.
در قطعه کد زیر، Row composable به عنوان ظرف والد عمل میکند. درون Row عناصر مرتبطی وجود دارند که فرادادههای یک پست وبلاگ را نشان میدهند - آواتار نویسنده، نام نویسنده و زمان تقریبی مطالعه. تنظیم mergeDescendants روی true این عناصر داخلی را گروهبندی میکند، بنابراین سرویسهای دسترسی میتوانند با آنها به عنوان یک واحد رفتار کنند.
@Composable private fun PostMetadata(metadata: Metadata) { // Merge elements below for accessibility purposes Row(modifier = Modifier.semantics(mergeDescendants = true) {}) { Image( imageVector = Icons.Filled.AccountCircle, contentDescription = null // decorative ) Column { Text(metadata.author.name) Text("${metadata.date} • ${metadata.readTimeMinutes} min read") } } }
هنگام گروهبندی عناصر مرتبط مانند مثال قبلی، فقط کانتینر والد را تعاملی کنید. از اضافه کردن اصلاحکنندههای clickable یا focusable به عناصر فرزند درونی خودداری کنید. در عوض، اصلاحکنندهها را به Row یا Column والد اعمال کنید.
از آنجا که سرویسهای دسترسیپذیری توضیحات عناصر داخلی را در یک جمله اعلام میکنند، مهم است که هر توضیح تا حد امکان کوتاه باشد و در عین حال معنای عنصر را نیز منتقل کند.
توجه: به طور کلی، هنگام ایجاد توضیحات محتوا برای یک گروه، از تجمیع متن فرزندان آن گروه خودداری کنید. انجام این کار باعث میشود توضیحات گروه شکننده شود و وقتی متن فرزند تغییر کند، ممکن است توضیحات گروه دیگر با متن قابل مشاهده مطابقت نداشته باشد.
در یک فهرست یا یک زمینه شبکهای، یک صفحهخوان ممکن است متن گرههای متنی فرزند یک فهرست یا عنصر شبکهای را تجمیع کند. بهتر است از اصلاح این اعلان خودداری کنید.
برای اطلاعات بیشتر در مورد ادغام معنایی، به ادغام و پاکسازی مراجعه کنید.
عنوانهای درون متن
برخی از برنامهها از سرتیترها برای خلاصه کردن گروههای متنی که روی صفحه نمایش داده میشوند استفاده میکنند. اگر یک عنصر خاص نشاندهنده یک سرتیتر است، میتوانید با تنظیم heading در اصلاحکننده semantics ، هدف آن را برای سرویسهای دسترسیپذیری مشخص کنید.
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
کاربران سرویسهای دسترسی میتوانند به جای پیمایش بین پاراگرافها یا بین کلمات، بین سرتیترها پیمایش کنند. این انعطافپذیری، تجربه پیمایش متن را بهبود میبخشد.
برای اطلاعات بیشتر در مورد ویژگی معنایی heading ، به Headings مراجعه کنید.
عناوین پنل دسترسیپذیری
در اندروید ۹ (سطح API 28) و بالاتر، میتوانید عناوینی متناسب با دسترسیپذیری برای پنلهای صفحه نمایش ارائه دهید. برای اهداف دسترسیپذیری، یک پنل بخشی از یک پنجره است که از نظر بصری متمایز است.
برای اینکه سرویسهای دسترسی بتوانند رفتار شبهپنجرهای یک پنل را درک کنند، عناوین توصیفی به پنلهای برنامه خود بدهید. سپس سرویسهای دسترسی میتوانند اطلاعات جزئیتری را در صورت تغییر ظاهر یا محتوای یک پنل به کاربران ارائه دهند.
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
برای اطلاعات بیشتر در مورد ویژگی معنایی paneTitle ، به اجزای شبهپنجره مراجعه کنید.
عناصر تزئینی
اگر عنصری در رابط کاربری شما فقط برای فاصلهگذاری بصری یا اهداف ظاهری وجود دارد، ویژگیهای مناسب را روی عنصر تنظیم کنید تا نشان دهد سرویسهای دسترسی میتوانند آن را نادیده بگیرند.
برای ترکیبهای Image یا Icon ، contentDescription = null قرار دهید. برای سایر عناصر صرفاً تزئینی که هیچ زمینه یا عملکردی ارائه نمیدهند، میتوانید hideFromAccessibility استفاده کنید. این ویژگی معنایی به سرویسهای دسترسی میگوید که آیتم را نادیده بگیرند.
اگر یک کامپوننت تعاملی شامل عناصر فرزند تزئینی و غیر تعاملی است، از clearAndSetSemantics استفاده کنید تا مطمئن شوید که سرویسهای دسترسیپذیری از آنها عبور نمیکنند. توجه داشته باشید که clearAndSetSemantics معنای پیشفرض یک عنصر و فرزندانش را به طور کامل پاک میکند. این به شما امکان میدهد یک عنصر دسترسیپذیری جدید و یکپارچه تعریف کنید. معمولاً از این رویکرد برای کامپوننتهای سفارشی پیچیده استفاده میکنید.
در مثال زیر، Icon و Text عناصر فرزند تزئینی درون یک toggle سفارشی هستند. برای جلوگیری از پیمایش جداگانه این فرزندان توسط سرویسهای دسترسی، میتوانید با استفاده از clearAndSetSemantics روی Row والد، معنای آنها را پاک کنید. این به سرویسهای دسترسی میگوید که کل Row به عنوان یک toggle قابل پیمایش در نظر بگیرند:
// Developer might intend this to be a toggleable. // Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied, // a custom description is set, and a Role is applied. @Composable fun FavoriteToggle() { val checked = remember { mutableStateOf(true) } Row( modifier = Modifier .toggleable( value = checked.value, onValueChange = { checked.value = it } ) .clearAndSetSemantics { stateDescription = if (checked.value) "Favorited" else "Not favorited" toggleableState = ToggleableState(checked.value) role = Role.Switch }, ) { Icon( imageVector = Icons.Default.Favorite, contentDescription = null // not needed here ) Text("Favorite?") } }
برای اطلاعات بیشتر در مورد پاکسازی معانی، به Clear و set semantics مراجعه کنید.
افزودن اقدامات دسترسیپذیری
مهم است که مطمئن شوید کاربران سرویسهای دسترسی، راهی برای تکمیل تمام جریانهای کاربری در برنامه شما دارند.
اگر تعامل کامپوننت سفارشی شما وضعیت برنامه را به شکلی که واضح نیست تغییر میدهد، با استفاده از پارامترهایی مانند onClickLabel یا onLongClickLabel در Modifier.clickable یا Modifier.combinedClickable ، برچسبهای توصیفی برای اقدامات ضربه استاندارد ارائه دهید.
برای تعاملات پیچیدهای که با tapهای استاندارد قابل نگاشت نیستند، از customActions استفاده کنید.
برای مثال، اگر برنامه شما به کاربران اجازه میدهد یک آیتم را به مکان دیگری بکشند یا روی یک آیتم در یک لیست انگشت خود را بکشند، میتوانید با قرار دادن این عمل در معرض سرویسهای دسترسی، روش جایگزینی برای تکمیل این جریانهای کاربری ارائه دهید. به این ترتیب، کاربران TalkBack، Voice Access یا Switch Access میتوانند اقداماتی را انجام دهند که در غیر این صورت فقط از طریق حرکات در دسترس هستند.
در Compose، میتوانید اقدامات دسترسی سفارشی را از طریق ویژگی customActions در اصلاحکننده semantics ، با استفاده از CustomAccessibilityAction تعریف کنید.
برای مثال، اگر برنامه شما به کاربران اجازه میدهد برای رد کردن یک آیتم، آن را با کشیدن انگشت روی آن ببندند، میتوانید این قابلیت را از طریق یک اقدام دسترسی سفارشی در معرض نمایش قرار دهید:
SwipeToDismissBox( modifier = Modifier.semantics { // Represents the swipe to dismiss for accessibility customActions = listOf( CustomAccessibilityAction( label = "Remove article from list", action = { removeArticle() true } ) ) }, state = rememberSwipeToDismissBoxState(), backgroundContent = {} ) { ArticleListItem() }
با پیادهسازی اکشن دسترسی سفارشی، کاربران میتوانند از طریق منوی اکشنها به اکشن دسترسی پیدا کنند.
برای اطلاعات بیشتر در مورد اقدامات سفارشی، به اقدامات سفارشی مراجعه کنید.
اقدامات موجود را قابل فهم کنید
وقتی یک عنصر رابط کاربری از عملکردهایی مانند لمس و نگهداشتن پشتیبانی میکند، یک سرویس دسترسی مانند TalkBack آن را به صورت «دو بار ضربه زدن و نگهداشتن برای فشار طولانی» اعلام میکند.
این اعلان عمومی هیچ توضیحی در مورد عملکرد لمس و نگهداشتن به کاربر نمیدهد.
برای مفیدتر کردن این اعلان، توضیح معناداری برای این اقدام مشخص کنید.
در Compose، اصلاحکنندههای تعامل استاندارد مانند clickable و combinedClickable پارامترهای داخلی (به نامهای onClickLabel و onLongClickLabel ) دارند که میتوانید از آنها برای ارائه توضیحات برای اقدامات استفاده کنید، مانند مثال زیر:
var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) } val haptics = LocalHapticFeedback.current LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) { items(photos, { it.id }) { photo -> ImageItem( photo, Modifier .combinedClickable( onClick = { activePhotoId = photo.id }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) contextMenuPhotoId = photo.id }, onLongClickLabel = stringResource(R.string.open_context_menu) ) ) } } if (contextMenuPhotoId != null) { PhotoActionsSheet( photo = photos.first { it.id == contextMenuPhotoId }, onDismissSheet = { contextMenuPhotoId = null } ) }
این منجر به اعلام «باز کردن منوی زمینه» توسط TalkBack میشود و به کاربران کمک میکند تا هدف از این اقدام را درک کنند.
همچنین میتوانید یک برچسب را مستقیماً در اصلاحکنندهی semantics مشخص کنید.
برای اطلاعات بیشتر در مورد پاسخ به ضربهها و کلیکها، به «ضربه زدن و فشار دادن» و «عناصر تعاملی» مراجعه کنید.
از ویژگیهای دسترسی داخلی استفاده کنید
هنگام طراحی رابط کاربری برنامه خود، از ویژگیهای دسترسیپذیری داخلی بهره ببرید تا از پیادهسازی مجدد قابلیتهای موجود جلوگیری کنید. APIهای Material، Compose UI و Foundation به طور پیشفرض بسیاری از شیوههای دسترسیپذیری را پیادهسازی و ارائه میدهند.
در Jetpack Compose، از کامپوننتهای داخلی مانند Button ، Switch و Checkbox برای ایجاد رابطهای کاربری قابل دسترس استفاده کنید. این کامپوننتها به صورت پیشفرض با اصلاحکنندههای semantics مانند role و stateDescription ارائه میشوند که میتوانید از آنها برای افزایش قابلیت دسترسی برنامههای خود استفاده کنید.
اعمال معناشناسی به اجزای سفارشی
هنگام ایجاد یک کامپوننت سفارشی، به این نکته توجه داشته باشید که این کامپوننت برای انجام نقش خود به چه نوع پشتیبانی دسترسی نیاز دارد. اغلب، APIهای استاندارد Compose که از قبل استفاده میکنید - مانند clickable ، toggleable یا selectable - کافی هستند زیرا به طور خودکار درخت معنایی را برای شما پر میکنند.
با این حال، برخی از کامپوننتها به اطلاعات خاصتری نسبت به اصلاحکنندههای استاندارد نیاز دارند. در این موارد، به دنبال اصلاحکنندههای تخصصی (مانند triStateToggleable ) باشید یا اگر هیچکدام وجود ندارند، با استفاده از Modifier.semantics سطح پایین، به صراحت معانی را ارائه دهید.
برای مثال، یک TriStateSwitch را در نظر بگیرید، یک سوئیچ با سه حالت (روشن، خاموش و نامشخص).
در حالی که یک اصلاحکنندهی استاندارد toggleable دو حالت را در نظر میگیرد، اصلاحکنندهی triStateToggleable پیچیدگی حالت سوم را مدیریت میکند. این اصلاحکننده به طور خودکار Role دسترسی ( Switch ) و State را تنظیم میکند. به این ترتیب، سرویسهای دسترسی اطلاعات دقیقی دریافت میکنند و نیازی به تعریف دستی معانی (semantics) نیست.
قطعه کد زیر یک TriStateSwitch را با استفاده از این رویکرد نشان میدهد:
@Composable fun TriStateSwitch( state: ToggleableState, onClick: () -> Unit, modifier: Modifier = Modifier ) { // A real implementation would include custom drawing for the switch. // This example uses a Box to demonstrate the semantics. Box( modifier = modifier .size(width = 64.dp, height = 40.dp) // triStateToggleable handles the semantics (Role and State) // automatically, so explicit Modifier.semantics is not needed here. .triStateToggleable( state = state, onClick = onClick, role = Role.Switch ) // Add visual feedback based on the state .background( when (state) { ToggleableState.On -> Color.Green ToggleableState.Off -> Color.Gray ToggleableState.Indeterminate -> Color.Yellow } ) ) } // Usage within another composable: var state by remember { mutableStateOf(ToggleableState.Off) } TriStateSwitch( state = state, onClick = { state = when (state) { ToggleableState.Off -> ToggleableState.Indeterminate ToggleableState.Indeterminate -> ToggleableState.On ToggleableState.On -> ToggleableState.Off } } )
هنگام ساخت یک کامپوننت سفارشی، مطمئن شوید که تمام ویژگیهای معنایی مرتبط را برای اهداف دسترسیپذیری ارائه میدهید. برای مثال، اگر کامپوننت شما از یک کنترل استاندارد مانند یک سوئیچ یا دکمه تقلید میکند، این ویژگیها شامل نقش کامپوننت (مانند Role.Switch یا Role.Button )، stateDescription (مانند "روشن"، "خاموش"، "بررسی شده" یا "بررسی نشده") و هرگونه برچسب اقدام مرتبط میشود. برای اطلاعات بیشتر، به کامپوننتهای سفارشی مراجعه کنید.
از نشانههایی غیر از رنگ استفاده کنید
برای کمک به کاربرانی که دچار نقص بینایی رنگ هستند، از نشانههایی غیر از رنگ برای تشخیص عناصر رابط کاربری در صفحات برنامه خود استفاده کنید. این تکنیکها میتوانند شامل استفاده از اشکال یا اندازههای مختلف، ارائه الگوهای متنی یا بصری یا افزودن بازخورد صوتی یا لمسی (لمسی) برای مشخص کردن تفاوت عناصر باشند.
شکل ۱ دو نسخه از یک فعالیت را نشان میدهد. یک نسخه فقط از رنگ برای تمایز بین دو اقدام ممکن در یک گردش کار استفاده میکند. نسخه دیگر از بهترین شیوه شامل کردن شکلها و متن علاوه بر رنگ برای برجسته کردن تفاوتهای بین دو گزینه استفاده میکند:
محتوای رسانهای را در دسترستر کنید
اگر در حال توسعه برنامهای هستید که شامل محتوای رسانهای، مانند کلیپ ویدیویی یا ضبط صدا است، سعی کنید از کاربران با انواع مختلف نیازهای دسترسی در درک مطالب پشتیبانی کنید. به طور خاص، سعی کنید موارد زیر را انجام دهید:
- شامل کنترلهایی باشد که به کاربران امکان مکث یا توقف پخش رسانه، تغییر صدا و تغییر زیرنویسها (کپشنها) را میدهد.
- اگر ویدیویی اطلاعاتی را ارائه میدهد که برای تکمیل یک گردش کار حیاتی است، همان محتوا را در قالبی جایگزین، مانند متن، ارائه دهید.
منابع اضافی
برای اطلاعات بیشتر در مورد افزایش دسترسیپذیری برنامهتان، به منابع اضافی زیر مراجعه کنید: