برای کمک به افرادی که نیازهای دسترسی دارند از برنامه شما با موفقیت استفاده کنند، برنامه خود را طوری طراحی کنید که از الزامات دسترسی کلیدی پشتیبانی کند.
حداقل اندازه های هدف لمسی را در نظر بگیرید
هر عنصر روی صفحهای که کسی میتواند روی آن کلیک کند، لمس کند یا با آن تعامل داشته باشد باید به اندازه کافی بزرگ باشد تا تعامل قابل اعتمادی داشته باشد. هنگام اندازهگیری این عناصر، مطمئن شوید که حداقل اندازه را روی 48dp تنظیم کنید تا به درستی از دستورالعملهای دسترسی طراحی مواد پیروی کنید.
اجزای متریال - مانند Checkbox
، RadioButton
، Switch
، Slider
و Surface
- این حداقل اندازه را به صورت داخلی تنظیم میکنند، اما فقط زمانی که مؤلفه بتواند اقدامات کاربر را دریافت کند. به عنوان مثال، هنگامی که یک Checkbox
پارامتر onCheckedChange
خود را روی یک مقدار غیر تهی تنظیم می کند، چک باکس شامل padding می شود که عرض و ارتفاع حداقل 48 dp داشته باشد.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }
هنگامی که پارامتر onCheckedChange
روی null تنظیم می شود، padding شامل نمی شود، زیرا نمی توان مستقیماً با مؤلفه تعامل کرد.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }
هنگام اجرای کنترلهای انتخابی مانند Switch
، RadioButton
، یا Checkbox
، معمولاً رفتار قابل کلیک را به یک محفظه والد برمیدارید، بازگشت تماس کلیکی را در composable روی null
تنظیم میکنید و یک اصلاحکننده toggleable
یا selectable
به Composable والد اضافه میکنید.
@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) ) } }
برچسب های کلیک را اضافه کنید
میتوانید از برچسب کلیک برای افزودن معنای معنایی به رفتار کلیک یک کامپوزیشن استفاده کنید. برچسبهای کلیک توضیح میدهند که چه اتفاقی میافتد هنگام تعامل کاربر با ترکیبپذیر. سرویسهای دسترسپذیری از برچسبهای کلیک برای کمک به توصیف برنامه برای کاربران با نیازهای خاص استفاده میکنند.
برچسب کلیک را با ارسال یک پارامتر در اصلاح کننده clickable
تنظیم کنید:
@Composable private fun ArticleListItem(openArticle: () -> Unit) { Row( Modifier.clickable( // R.string.action_read_article = "read article" onClickLabel = stringResource(R.string.action_read_article), onClick = openArticle ) ) { // .. } }
همچنین، اگر به اصلاح کننده قابل کلیک دسترسی ندارید، برچسب کلیک را در اصلاح کننده معنایی تنظیم کنید:
@Composable private fun LowLevelClickLabel(openArticle: () -> Boolean) { // R.string.action_read_article = "read article" val readArticleLabel = stringResource(R.string.action_read_article) Canvas( Modifier.semantics { onClick(label = readArticleLabel, action = openArticle) } ) { // .. } }
عناصر بصری را توصیف کنید
وقتی یک Image
یا Icon
قابل ترکیب تعریف میکنید، هیچ راه خودکاری برای چارچوب Android برای درک آنچه برنامه نمایش میدهد وجود ندارد. شما باید یک توضیح متنی از عنصر بصری را ارسال کنید.
صفحه ای را تصور کنید که در آن کاربر می تواند صفحه فعلی را با دوستان خود به اشتراک بگذارد. این صفحه شامل یک نماد اشتراک گذاری قابل کلیک است:
بر اساس آیکون به تنهایی، چارچوب اندروید نمی تواند آن را برای یک کاربر کم بینا توصیف کند. فریم ورک اندروید نیاز به توضیح متنی اضافی از نماد دارد.
پارامتر 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
نیاز دارد یا خیر. از خود بپرسید که آیا این عنصر اطلاعاتی را که کاربر برای انجام وظیفه خود به آن نیاز دارد منتقل می کند یا خیر. اگر نه، بهتر است توضیحات را کنار بگذارید.
ادغام عناصر
سرویسهای دسترسپذیری مانند Talkback و Switch Access به کاربران اجازه میدهند تا فوکوس را روی عناصر روی صفحه تغییر دهند. مهم است که عناصر در دانه بندی مناسب متمرکز شوند. هنگامی که تک تک قطعات کامپوزیشن سطح پایین در صفحه نمایش شما به طور مستقل فوکوس می شود، کاربران باید برای حرکت در صفحه نمایش تعامل زیادی داشته باشند. اگر عناصر به شدت با هم ادغام شوند، کاربران ممکن است متوجه نشوند که کدام عناصر به یکدیگر تعلق دارند
هنگامی که یک اصلاح کننده clickable
را روی یک composable اعمال می کنید، Compose به طور خودکار همه عناصر موجود در composable را ادغام می کند. این همچنین برای ListItem
صادق است. عناصر موجود در یک آیتم لیست با هم ادغام می شوند و سرویس های دسترسی آنها را به عنوان یک عنصر می بینند.
ممکن است مجموعهای از ترکیبپذیرها را داشته باشید که یک گروه منطقی را تشکیل میدهند، اما آن گروه قابل کلیک یا بخشی از یک آیتم فهرست نیست. همچنان میخواهید که سرویسهای دسترسپذیری آنها را بهعنوان یک عنصر مشاهده کنند. به عنوان مثال، یک Composable را تصور کنید که آواتار کاربر، نام او و برخی اطلاعات اضافی را نشان می دهد:
می توانید Compose را برای ادغام این عناصر با استفاده از پارامتر mergeDescendants
در اصلاح کننده semantics
فعال کنید. به این ترتیب، سرویسهای دسترسی فقط عنصر ادغام شده را انتخاب میکنند و تمام ویژگیهای معنایی فرزندان ادغام میشوند.
@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") } } }
سرویسهای دسترسپذیری اکنون روی کل کانتینر بهطور همزمان تمرکز میکنند و محتویاتشان را ادغام میکنند:
افزودن اقدامات سفارشی
به آیتم لیست زیر نگاهی بیندازید:
وقتی از صفحهخوانی مانند Talkback برای شنیدن آنچه روی صفحه نمایش داده میشود استفاده میکنید، ابتدا کل مورد و سپس نماد نشانک را انتخاب میکند.
در یک لیست طولانی، این می تواند بسیار تکراری شود. یک رویکرد بهتر، تعریف یک اقدام سفارشی است که به کاربر اجازه می دهد آیتم را نشانک کند. به خاطر داشته باشید که باید رفتار خود نماد نشانک را نیز به صراحت حذف کنید تا مطمئن شوید که توسط سرویس دسترسپذیری انتخاب نشده است. این کار با اصلاح کننده clearAndSetSemantics
انجام می شود:
@Composable private fun PostCardSimple( /* ... */ isFavorite: Boolean, onToggleFavorite: () -> Boolean ) { val actionLabel = stringResource( if (isFavorite) R.string.unfavorite else R.string.favorite ) Row( modifier = Modifier .clickable(onClick = { /* ... */ }) .semantics { // Set any explicit semantic properties customActions = listOf( CustomAccessibilityAction(actionLabel, onToggleFavorite) ) } ) { /* ... */ BookmarkButton( isBookmarked = isFavorite, onClick = onToggleFavorite, // Clear any semantics properties set on this node modifier = Modifier.clearAndSetSemantics { } ) } }
وضعیت یک عنصر را توصیف کنید
یک composable میتواند یک stateDescription
برای معناشناسی تعریف کند که چارچوب Android از آن برای خواندن وضعیتی که composable در آن قرار دارد استفاده میکند. به عنوان مثال، یک composable قابل تغییر میتواند در حالت "checked" یا "unchecked" باشد. در برخی موارد، ممکن است بخواهید برچسبهای توصیف حالت پیشفرض را که Compose استفاده میکند لغو کنید. میتوانید این کار را با مشخص کردن صریح برچسبهای توصیف وضعیت قبل از تعریف یک composable به عنوان toggleable انجام دهید:
@Composable private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) { val stateSubscribed = stringResource(R.string.subscribed) val stateNotSubscribed = stringResource(R.string.not_subscribed) Row( modifier = Modifier .semantics { // Set any explicit semantic properties stateDescription = if (selected) stateSubscribed else stateNotSubscribed } .toggleable( value = selected, onValueChange = { onToggle() } ) ) { /* ... */ } }
سرفصل ها را تعریف کنید
گاهی اوقات برنامه ها محتوای زیادی را روی یک صفحه در یک ظرف قابل پیمایش نشان می دهند. به عنوان مثال، یک صفحه می تواند محتوای کامل مقاله ای را که کاربر در حال خواندن آن است نشان دهد:
کاربرانی که نیازهای دسترسی دارند در پیمایش چنین صفحهای مشکل دارند. برای کمک به ناوبری، مشخص کنید کدام عناصر سرفصل هستند. در مثال قبل، هر عنوان زیربخش را می توان به عنوان عنوانی برای دسترسی تعریف کرد. برخی از سرویسهای دسترسپذیری، مانند Talkback، به کاربران اجازه میدهند که مستقیماً از سرفصل به عنوان حرکت کنند.
در Compose، با تعریف خاصیت semantics
آن، نشان میدهید که composable یک عنوان است:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
با ترکیبات سفارشی مدیریت کنید
هر زمان که اجزای Material خاصی را در برنامه خود با نسخه های سفارشی جایگزین می کنید، باید ملاحظات دسترسی را در نظر داشته باشید.
فرض کنید که Checkbox
Material را با پیاده سازی خودتان جایگزین می کنید. ممکن است فراموش کنید که اصلاح کننده triStateToggleable
را اضافه کنید، که ویژگی های دسترسی برای این مؤلفه را کنترل می کند.
به عنوان یک قانون سرانگشتی، به اجرای مؤلفه در کتابخانه Material نگاه کنید و هر گونه رفتار دسترسی را که می توانید پیدا کنید، تقلید کنید. بهعلاوه، از اصلاحکنندههای بنیاد، برخلاف اصلاحکنندههای سطح UI، به شدت استفاده کنید، زیرا این موارد شامل ملاحظات دسترسی خارج از جعبه است.
اجرای مؤلفه سفارشی خود را با چندین سرویس دسترسی آزمایش کنید تا رفتار آن را تأیید کنید.
منابع اضافی
- دسترسپذیری : مفاهیم اساسی و تکنیکهای مشترک برای همه برنامهنویسی اندروید
- ساخت برنامههای قابل دسترس : مراحل کلیدی که میتوانید برای دسترسی بیشتر برنامه خود بردارید
- اصول بهبود دسترسی به برنامه : اصول کلیدی که باید هنگام کار برای دسترسی بیشتر برنامه خود به خاطر داشته باشید
- Testing for Accessibility : تست اصول و ابزار برای دسترسی اندروید