برای کمک به کاربرانی که نیاز به دسترسپذیری دارند، چارچوب Android به شما امکان میدهد خدمات دسترسپذیری ایجاد کنید که بتواند محتوای برنامهها را به کاربران ارائه دهد و همچنین برنامهها را ازطرف آنها اجرا کند.
Android چندین سرویس دسترسپذیری سیستم ارائه میدهد، ازجمله موارد زیر:
- TalkBack: به افراد کمبینا یا نابینا کمک میکند. این ویژگی محتوا را ازطریق صدای ترکیبی اعلام میکند و در پاسخ به اشارههای کاربر، در برنامهای کنش انجام میدهد.
- دسترسی با کلید: به افرادی که ناتوانی حرکتی دارند کمک میکند. عناصر تعاملی را برجسته میکند و در پاسخ به فشار دادن دکمه توسط کاربر، کنشهایی را انجام میدهد. این ویژگی امکان کنترل دستگاه را تنها بااستفاده از یک یا دو دکمه فراهم میکند.
برای کمک به افرادی که نیازهای دسترسپذیری دارند تا بتوانند با موفقیت از برنامه شما استفاده کنند، برنامه شما باید از روالهای مطلوب شرحدادهشده در این صفحه پیروی کند، که براساس دستورالعملهای شرحدادهشده در دسترسیپذیرتر کردن برنامهها ساخته شده است.
هریک از این رویههای مطلوب که در بخشهای زیر توضیح داده شده است، میتواند دسترسیپذیری برنامه شما را بیشتر بهبود دهد:
- عناصر برچسب
- کاربران باید بتوانند محتوا و هدف هر عنصر واسط کاربر تعاملی و معنادار را در برنامه شما درک کنند.
- افزودن کنشهای دسترسپذیری
- با افزودن کنشهای دسترسپذیری، میتوانید به کاربران خدمات دسترسپذیری اجازه دهید جریانهای کاربری مهم را در برنامهتان تکمیل کنند.
- استفاده از ویژگیهای دسترسپذیری داخلی
- «نوشتن» بهطور پیشفرض رفتارهای دسترسپذیری زیادی ارائه میدهد. از عملکردهای دسترسپذیری ازپیشتعریفشده استفاده کنید تا با کار اضافی کم یا بدون کار اضافی، عناصرتان را دسترسپذیر کنید. «نوشتن» همچنین روشهایی برای پشتیبانی از الزامات دسترسپذیری خاصتری که ویژگیهای پیشفرض پوشش نمیدهند ارائه میدهد.
- استفاده از نشانههایی غیراز رنگ
- کاربران باید بتوانند بهوضوح بین دستههای عناصر در واسط کاربر تمایز قائل شوند. برای انجام این کار، از الگوها و موقعیت، همراه با رنگ، برای بیان این تفاوتها استفاده کنید.
- دسترسپذیرتر کردن محتوای رسانهای
- به محتوای ویدیویی یا صوتی برنامهتان شرح اضافه کنید تا کاربرانی که این محتوا را مصرف میکنند مجبور نباشند کاملاً به نشانههای دیداری یا شنیداری تکیه کنند.
عناصر برچسب
مهم است که برای هر عنصر میانای کاربری تعاملی در برنامهتان برچسبهای مفید و توصیفی ارائه دهید. هر برچسب باید معناشناسی عنصر خاصی را توضیح دهد، یعنی معنا و هدف عنصر. صفحهخوانهایی مثل TalkBack میتوانند این برچسبها را به کاربران اعلام کنند.
در اکثر موارد، «میاناهای برنامهسازی کاربردی Compose» و Material دارای
پشتیبانی دسترسپذیری پیشفرض هستند. بااینحال، اگر نیاز دارید ویژگیهای معنایی عنصر میانای کاربر را بهصورت دستی مشخص کنید، از اصلاحگر semantics و ویژگی contentDescription استفاده کنید. برای اطلاعات بیشتر درباره معناشناسی، به
معناشناسی مراجعه کنید.
بخشهای زیر چندین تکنیک برچسبگذاری دیگر را شرح میدهند.
عناصر قابلویرایش
هنگام برچسبگذاری عناصر قابلویرایش، مانند فیلدهای نوشتاری، بهتر است نوشتاری نشان داده شود که علاوهبر دردسترس قرار دادن این نوشتار نمونه برای صفحهخوانها، نمونهای از ورودی معتبر را در خود عنصر ارائه دهد. در این شرایط، میتوانید از نوشتار جایبان، که نوشتار اشاره نیز نامیده میشود، استفاده کنید.
در مثال زیر، 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 بهعنوان محتوی والد عمل میکند.
در 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، به سرصفحهها مراجعه کنید.
عنوانهای قاب دسترسپذیری
در Android 9 (سطح 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 عناصر فرزند تزئینی
در یک دکمه روشن/خاموش سفارشی هستند. برای جلوگیری از اینکه خدمات دسترسپذیری
این فرزندان را بهصورت جداگانه پیمایش کنند، میتوانید بااستفاده از
clearAndSetSemantics در Row ولی، معنای آنها را پاک کنید. این کار به خدمات دسترسپذیری میگوید
کل Row را بهعنوان یک دکمه تغییر وضعیت پیمایشپذیر درنظر بگیرد:
// 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?") } }
برای اطلاعات بیشتر درباره پاک کردن معناشناسی، به پاک کردن و تنظیم معناشناسی مراجعه کنید.
افزودن کنشهای دسترسپذیری
مهم است که مطمئن شوید کاربران خدمات دسترسپذیری راهی برای تکمیل همه جریانهای کاربر در برنامه شما دارند.
اگر تعامل عنصر ترکیبی سفارشی شما وضعیت برنامه را به روشی تغییر میدهد که
واضح نیست، بااستفاده از پارامترهایی مثل onClickLabel یا onLongClickLabel در Modifier.clickable
یا Modifier.combinedClickable، برچسبهای توصیفی برای کنشهای استاندارد تکضرب ارائه دهید.
برای تعاملات پیچیدهای که به ضربههای استاندارد قابلتخصیص نیستند، از customActions استفاده کنید.
برای مثال، اگر برنامه شما به کاربران اجازه میدهد موردی را به مکان دیگری بکشند یا روی موردی در فهرست تند بکشند، میتوانید با آشکار کردن کنش برای خدمات دسترسپذیری، روش جایگزینی برای تکمیل این جریانهای کاربر ارائه دهید. به این ترتیب، کاربران TalkBack، دسترسی صوتی، یا «دسترسی با کلید» میتوانند کنشهایی را انجام دهند که درغیراینصورت فقط ازطریق اشارهها دردسترس هستند.
در «نوشتن»، میتوانید کنشهای دسترسپذیری سفارشی را ازطریق
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 آن را بهصورت «برای فشار طولانی، دوتکضرب بزنید و نگه دارید» اعلام میکند.
این اعلامیه عمومی هیچ زمینهای درباره عملکرد اقدام لمس و نگه داشتن به کاربر ارائه نمیدهد.
برای مفیدتر کردن این اعلامیه، شرح معناداری برای این کنش مشخص کنید.
در «نوشتن»، اصلاحگرهای تعامل استاندارد مثل 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 مشخص کنید.
برای اطلاعات بیشتر درباره پاسخ دادن به تکضربها و کلیکها، تکضرب و فشار و عناصر تعاملی را ببینید.
استفاده از ویژگیهای دسترسپذیری داخلی
هنگام طراحی واسط کاربر برنامهتان، از ویژگیهای دسترسپذیری داخلی استفاده کنید تا از پیادهسازی مجدد عملکردی که ازقبل وجود دارد جلوگیری کنید. «طراحی مواد»، «واسط کاربر Compose»، و «میاناهای برنامهسازی کاربردی پایه» بهطور پیشفرض بسیاری از روشهای دسترسپذیر را پیادهسازی و ارائه میکنند.
در Jetpack Compose، از عناصر ترکیبی داخلی مانند Button، Switch، و
Checkbox برای ایجاد میاناهای کاربر دسترسپذیر استفاده کنید. این عناصر ازپیش بستهبندیشده با
semantics اصلاحکننده، مثل role و stateDescription، ارائه میشوند که میتوانید از آنها
برای دسترسپذیرتر کردن برنامههایتان استفاده کنید.
اعمال معناشناسی به عناصر سفارشی
هنگام ایجاد یک عنصر سفارشی، به این توجه داشته باشید که این عنصر برای انجام نقش خود به چه نوع پشتیبانی از دسترسپذیری نیاز دارد. اغلب، «میاناهای برنامهسازی کاربردی Compose» استاندارد که ازقبل استفاده میکنید—مثل clickable، toggleable، یا selectable—کافی هستند زیرا درخت معنایی را بهطور خودکار برایتان تکمیل میکنند.
بااینحال، برخیاز عناصر به اطلاعات دقیقتری نسبتبه اصلاحکنندههای استاندارد نیاز دارند. در این موارد، بهدنبال اصلاحکنندههای تخصصی (مثل
triStateToggleable) بگردید یا، اگر وجود ندارد، بااستفاده از
Modifier.semantics سطح پایین، معناشناسی را بهطور صریح ارائه دهید.
برای مثال، TriStateSwitch را درنظر بگیرید، کلیدی با سه وضعیت (روشن،
خاموش، و نامشخص).
درحالیکه اصلاحگر استاندارد toggleable دو وضعیت را فرض میکند، اصلاحگر triStateToggleable پیچیدگی وضعیت سوم را مدیریت میکند. بهطور خودکار دسترسپذیری Role (Switch) و State را تنظیم میکند. به این ترتیب، خدمات دسترسپذیری اطلاعات دقیق دریافت میکنند و نیازی نیست معناشناسی را بهصورت دستی تعریف کنید.
تکهکد زیر 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 (مثل «روشن»، «خاموش»، «علامتگذاریشده»، یا «علامتگذارینشده»)، و هر برچسب کنش مرتبط میشود. برای اطلاعات بیشتر، عناصر سفارشی را ببینید.
استفاده از نشانههایی غیراز رنگ
برای کمک به کاربران مبتلا به کوررنگی، از نشانههایی غیراز رنگ برای تشخیص عناصر میانای کاربر در صفحههای برنامهتان استفاده کنید. این تکنیکها میتواند شامل استفاده از اشکال یا اندازههای مختلف، ارائه نوشتار یا الگوهای دیداری، یا افزودن بازخورد صوتی یا لمسی (حسی) برای نشان دادن تفاوتهای عناصر باشد.
شکل ۱ دو نسخه از یک فعالیت را نشان میدهد. یک نسخه فقط از رنگ برای تمایز بین دو کنش ممکن در گردش کار استفاده میکند. نسخه دیگر از روال مطلوب استفاده میکند و علاوه بر رنگ، شکل و نوشتار را نیز دربرمیگیرد تا تفاوتهای بین دو گزینه را برجسته کند:
دسترسی به محتوای رسانهای را آسانتر کنید
اگر برنامهای توسعه میدهید که شامل محتوای رسانهای، مانند کلیپ ویدیویی یا ضبط صوتی است، سعی کنید از کاربران با انواع مختلف نیازهای دسترسیپذیری در درک مطلب پشتیبانی کنید. بهطور خاص، سعی کنید موارد زیر را انجام دهید:
- کنترلهایی را اضافه کنید که به کاربران اجازه میدهد رسانه را موقتاً متوقف یا متوقف کنند، میزان صدا را تغییر دهند، و زیرنویس ناشنوایان (زیرنویس) را روشن/خاموش کنند.
- اگر ویدیویی اطلاعاتی را ارائه میدهد که برای تکمیل یک گردش کار حیاتی است، همان محتوا را در قالب جایگزین، مانند ترانویسی، ارائه دهید.
منابع بیشتر
برای کسب اطلاعات بیشتر درباره دسترسپذیرتر کردن برنامهتان، منابع تکمیلی زیر را ببینید: