بهطور پیشفرض، رفتار صفحهخوان دسترسپذیری در برنامه Compose به ترتیب خواندن مورد انتظار، که معمولاً از چپ به راست و سپس از بالا به پایین است، اجرا میشود. با این حال، انواعی از طرحبندی برنامهها وجود دارد که الگوریتم نمیتواند ترتیب خواندن واقعی را بدون نکات اضافی تعیین کند. در برنامههای مبتنی بر view، میتوانید چنین مشکلاتی را با استفاده از ویژگیهای traversalBefore
و traversalAfter
برطرف کنید. با شروع در Compose 1.5 ، Compose یک API به همان اندازه انعطاف پذیر، اما با یک مدل مفهومی جدید ارائه می دهد.
isTraversalGroup
و traversalIndex
ویژگی های معنایی هستند که به شما امکان می دهند دسترسی و ترتیب تمرکز TalkBack را در سناریوهایی که الگوریتم مرتب سازی پیش فرض مناسب نیست کنترل کنید. isTraversalGroup
گروه های مهم معنایی را شناسایی می کند، در حالی که traversalIndex
ترتیب عناصر فردی را در آن گروه ها تنظیم می کند. برای سفارشی سازی بیشتر می توانید isTraversalGroup
به تنهایی یا با traversalIndex
استفاده کنید.
از isTraversalGroup
و traversalIndex
در برنامه خود برای کنترل ترتیب پیمایش صفحه خوان استفاده کنید.
گروه بندی عناصر با isTraversalGroup
isTraversalGroup
یک ویژگی بولی است که تعیین می کند آیا یک گره معنایی یک گروه پیمایش است یا خیر. این نوع گره، گرهی است که عملکرد آن به عنوان یک مرز یا مرز در سازماندهی فرزندان گره است.
تنظیم isTraversalGroup = true
در یک گره به این معنی است که همه فرزندان آن گره قبل از انتقال به عناصر دیگر بازدید می شوند. میتوانید isTraversalGroup
را روی گرههای قابل تمرکز غیرصفحهخوان، مانند ستونها، ردیفها یا جعبهها تنظیم کنید.
مثال زیر از isTraversalGroup
استفاده می کند. چهار عنصر متنی را منتشر می کند. دو عنصر سمت چپ متعلق به یک عنصر CardBox
است، در حالی که دو عنصر سمت راست متعلق به یک عنصر CardBox
است:
// CardBox() function takes in top and bottom sample text. @Composable fun CardBox( topSampleText: String, bottomSampleText: String, modifier: Modifier = Modifier ) { Box(modifier) { Column { Text(topSampleText) Text(bottomSampleText) } } } @Composable fun TraversalGroupDemo() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is " val bottomSampleText2 = "on the right." Row { CardBox( topSampleText1, bottomSampleText1 ) CardBox( topSampleText2, bottomSampleText2 ) } }
کد خروجی مشابه زیر تولید می کند:
از آنجا که هیچ معنایی تنظیم نشده است، رفتار پیشفرض صفحهخوان این است که عناصر را از چپ به راست و از بالا به پایین طی کند. به دلیل این پیشفرض، TalkBack بخشهای جمله را به ترتیب اشتباه میخواند:
"این جمله در است" → "این جمله است" → "ستون سمت چپ." → "در سمت راست."
برای ترتیب صحیح قطعات، قطعه اصلی را تغییر دهید تا isTraversalGroup
را روی true
تنظیم کنید:
@Composable fun TraversalGroupDemo2() { val topSampleText1 = "This sentence is in " val bottomSampleText1 = "the left column." val topSampleText2 = "This sentence is" val bottomSampleText2 = "on the right." Row { CardBox( // 1, topSampleText1, bottomSampleText1, Modifier.semantics { isTraversalGroup = true } ) CardBox( // 2, topSampleText2, bottomSampleText2, Modifier.semantics { isTraversalGroup = true } ) } }
از آنجایی که isTraversalGroup
به طور خاص روی هر CardBox
تنظیم شده است، مرزهای CardBox
هنگام مرتبسازی عناصر اعمال میشوند. در این حالت ابتدا CardBox
سمت چپ و سپس CardBox
سمت راست خوانده می شود.
اکنون، TalkBack قطعات جمله را به ترتیب صحیح می خواند:
"این جمله در" → "ستون سمت چپ است." → "این جمله است" → "در سمت راست."
سفارشی کردن بیشتر سفارش پیمایش
traversalIndex
یک ویژگی شناور است که به شما امکان می دهد ترتیب پیمایش TalkBack را سفارشی کنید. اگر گروه بندی عناصر در کنار هم برای کارکرد صحیح TalkBack کافی نیست، از traversalIndex
همراه با isTraversalGroup
برای سفارشی کردن بیشتر سفارش صفحه خوان استفاده کنید.
ویژگی traversalIndex
دارای ویژگی های زیر است:
- ابتدا عناصر با مقادیر
traversalIndex
کمتر اولویت بندی می شوند. - می تواند مثبت یا منفی باشد.
- مقدار پیش فرض
0f
است. - فقط بر گرههای قابل تمرکز بر روی صفحهخوان تأثیر میگذارد، مانند عناصر روی صفحه مانند متن یا دکمهها. به عنوان مثال، تنظیم تنها
traversalIndex
روی یک ستون هیچ تاثیری نخواهد داشت، مگر اینکه ستونisTraversalGroup
نیز روی آن تنظیم شده باشد.
مثال زیر نشان می دهد که چگونه می توانید traversalIndex
و isTraversalGroup
با هم استفاده کنید.
مثال: صفحه ساعت تراورس
صفحه ساعت یک سناریوی رایج است که در آن ترتیب پیمایش استاندارد کار نمی کند. مثال در این بخش یک انتخابگر زمان است که در آن کاربر می تواند از اعداد روی صفحه ساعت عبور کند و ارقام را برای شکاف های ساعت و دقیقه انتخاب کند.
در قطعه ساده شده زیر، یک CircularLayout
وجود دارد که در آن 12 عدد ترسیم شده است که با 12 شروع می شود و در جهت عقربه های ساعت حول دایره حرکت می کند:
@Composable fun ClockFaceDemo() { CircularLayout { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier) { Text((if (value == 0) 12 else value).toString()) } }
از آنجایی که صفحه ساعت به صورت منطقی با ترتیب پیشفرض چپ به راست و بالا به پایین خوانده نمیشود، TalkBack اعداد را نامرتب میخواند. برای تصحیح این، از مقدار شمارنده افزایشی استفاده کنید، همانطور که در قطعه زیر نشان داده شده است:
@Composable fun ClockFaceDemo() { CircularLayout(Modifier.semantics { isTraversalGroup = true }) { repeat(12) { hour -> ClockText(hour) } } } @Composable private fun ClockText(value: Int) { Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) { Text((if (value == 0) 12 else value).toString()) } }
برای تنظیم صحیح ترتیب پیمایش، ابتدا CircularLayout
یک گروه پیمایش کنید و isTraversalGroup = true
را تنظیم کنید. سپس، همانطور که هر متن ساعت بر روی طرحبندی کشیده میشود، traversalIndex
مربوط به آن را روی مقدار شمارنده تنظیم کنید.
از آنجا که مقدار شمارنده به طور مداوم افزایش مییابد، هر مقدار ساعت، traversalIndex
بزرگتر میشود، زیرا اعداد به صفحه اضافه میشوند—مقدار ساعت 0 دارای traversalIndex
0 و مقدار ساعت 1 دارای traversalIndex
1 است. به این ترتیب، ترتیبی که TalkBack آنها را در تنظیم می کند. اکنون اعداد داخل CircularLayout
به ترتیب مورد انتظار خوانده می شوند.
از آنجایی که traversalIndexes
هایی که تنظیم شده اند فقط نسبت به سایر نمایه های داخل همان گروه بندی هستند، بقیه ترتیب صفحه حفظ شده است. به عبارت دیگر، تغییرات معنایی نشاندادهشده در قطعه کد قبلی، فقط ترتیب در صفحه ساعت را تغییر میدهد که دارای isTraversalGroup = true
است.
توجه داشته باشید که بدون تنظیم معنایی CircularLayout's
به isTraversalGroup = true
، تغییرات traversalIndex
همچنان اعمال می شود. با این حال، بدون CircularLayout
که آنها را متصل کند، دوازده رقم صفحه ساعت در آخر خوانده میشوند، پس از بازدید از سایر عناصر روی صفحه. این به این دلیل اتفاق میافتد که همه عناصر دیگر دارای traversalIndex
پیشفرض 0f
هستند و عناصر متن ساعت بعد از همه عناصر 0f
دیگر خوانده میشوند.
مثال: سفارشی کردن ترتیب پیمایش برای دکمه عمل شناور
در این مثال، traversalIndex
و isTraversalGroup
ترتیب پیمایش یک دکمه عمل شناور طراحی مواد (FAB) را کنترل می کنند. اساس این مثال طرح زیر است:
بهطور پیشفرض، طرحبندی در این مثال به ترتیب TalkBack زیر است:
نوار برنامه بالا ← متون نمونه 0 تا 6 ← دکمه اقدام شناور (FAB) ← نوار برنامه پایین
ممکن است بخواهید صفحهخوان ابتدا روی FAB تمرکز کند. برای تنظیم traversalIndex
روی یک عنصر Material مانند FAB، موارد زیر را انجام دهید:
@Composable fun FloatingBox() { Box(modifier = Modifier.semantics { isTraversalGroup = true; traversalIndex = -1f }) { FloatingActionButton(onClick = {}) { Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon") } } }
در این قطعه، ایجاد کادری با مقدار isTraversalGroup
روی true
و تنظیم traversalIndex
در همان کادر ( -1f
کمتر از مقدار پیشفرض 0f
است) به این معنی است که کادر شناور قبل از سایر عناصر روی صفحه قرار میگیرد.
در مرحله بعد، میتوانید جعبه شناور و سایر عناصر را در یک داربست قرار دهید، که طرحبندی Material Design را اجرا میکند:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ColumnWithFABFirstDemo() { Scaffold( topBar = { TopAppBar(title = { Text("Top App Bar") }) }, floatingActionButtonPosition = FabPosition.End, floatingActionButton = { FloatingBox() }, content = { padding -> ContentColumn(padding = padding) }, bottomBar = { BottomAppBar { Text("Bottom App Bar") } } ) }
TalkBack به ترتیب زیر با عناصر تعامل دارد:
FAB ← نوار برنامه بالا ← متون نمونه 0 تا 6 ← نوار برنامه پایین
منابع اضافی
- دسترسپذیری : مفاهیم اساسی و تکنیکهای مشترک برای همه برنامهنویسی اندروید
- ساخت برنامههای قابل دسترس : مراحل کلیدی که میتوانید برای دسترسی بیشتر برنامه خود بردارید
- اصول برای بهبود دسترسی به برنامه : اصول کلیدی که باید هنگام کار برای دسترسی بیشتر به برنامه خود در نظر داشته باشید
- Testing for Accessibility : تست اصول و ابزار برای دسترسی اندروید