تغییر ترتیب پیمایش

ترتیب پیمایش ترتیبی است که خدمات دسترس‌پذیری ازطریق آن در عناصر میانای کاربر پیمایش می‌کنند. در برنامه Compose، عناصر به‌ترتیب خواندن موردانتظار چیده می‌شوند، که معمولاً از چپ به راست و سپس از بالا به پایین است. بااین‌حال، در برخی سناریوها، Compose ممکن است به راهنمایی‌های بیشتری برای تعیین ترتیب خواندن صحیح نیاز داشته باشد.

isTraversalGroup و traversalIndex ویژگی‌های معنایی هستند که به شما امکان می‌دهند در سناریوهایی که الگوریتم مرتب‌سازی پیش‌فرض Compose کافی نیست، بر ترتیب پیمایش برای سرویس‌های دسترس‌پذیری تأثیر بگذارید. isTraversalGroup گروه‌های مهم ازنظر معنایی را که به سفارشی‌سازی نیاز دارند شناسایی می‌کند، درحالی‌که traversalIndex ترتیب عناصر تکی را در آن گروه‌ها تنظیم می‌کند. می‌توانید از isTraversalGroup به‌تنهایی استفاده کنید تا نشان دهید که همه عناصر درون یک گروه باید باهم انتخاب شوند، یا از traversalIndex برای سفارشی‌سازی بیشتر استفاده کنید.

از isTraversalGroup و traversalIndex در برنامه‌تان برای کنترل ترتیب پیمایش صفحه‌خوان استفاده کنید.

گروه‌بندی عناصر برای پیمایش

‫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 روی، برای مثال، Column هیچ تأثیری نخواهد داشت، مگر اینکه ستون isTraversalGroup نیز روی آن تنظیم شده باشد.

مثال زیر نشان می‌دهد که چگونه می‌توانید از traversalIndex و isTraversalGroup با هم استفاده کنید.

صفحه ساعت سناریوی رایجی است که در آن ترتیب پیمایش استاندارد کار نمی‌کند. نمونه موجود در این بخش یک انتخابگر زمان است که کاربر می‌تواند در آن اعداد روی صفحه ساعت را پیمایش کند و رقم‌های مربوط به ساعت و دقیقه را انتخاب کند.

صفحه ساعت با انتخابگر زمان در بالای آن.
شکل ۲. تصویر صفحه ساعت.

در قطعه ساده‌شده زیر، یک CircularLayout وجود دارد که در آن ۱۲ عدد کشیده شده است، که از ۱۲ شروع می‌شود و در جهت عقربه‌های ساعت دور دایره حرکت می‌کند:

@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 هر مقدار ساعت بزرگ‌تر می‌شود—مقدار ساعت ۰ دارای traversalIndex ۰ است و مقدار ساعت ۱ دارای traversalIndex ۱ است. به‌این‌ترتیب، ترتیبی که TalkBack آن‌ها را می‌خواند تنظیم می‌شود. اکنون، اعداد داخل CircularLayout به ترتیب موردانتظار خوانده می‌شوند.

چون traversalIndexes تنظیم‌شده فقط نسبت به نمایه‌های دیگر در همان گروه‌بندی است، بقیه ترتیب صفحه‌نمایش حفظ شده است. به عبارت دیگر، تغییرات معنایی نشان‌داده‌شده در تکه‌کد قبلی فقط ترتیب را در صفحه ساعتی که isTraversalGroup = true برای آن تنظیم شده است تغییر می‌دهد.

توجه داشته باشید که بدون تنظیم معناشناسی CircularLayout's روی isTraversalGroup = true، تغییرات traversalIndex همچنان اعمال می‌شود. اما بدون CircularLayout برای پیوند دادن آن‌ها، دوازده رقم صفحه ساعت در آخر خوانده می‌شود، یعنی پس‌از اینکه همه عناصر دیگر روی صفحه بازدید شدند. این اتفاق می‌افتد زیرا همه عناصر دیگر دارای traversalIndex پیش‌فرض 0f هستند و عناصر نوشتاری ساعت پس‌از همه عناصر 0f دیگر خوانده می‌شوند.

ملاحظات میانای برنامه‌سازی کاربردی

هنگام استفاده از میاناهای برنامه‌سازی کاربردی پیمایش، موارد زیر را درنظر بگیرید:

  • ‫isTraversalGroup = true باید روی والد حاوی عناصر گروه‌بندی‌شده تنظیم شود.
  • traversalIndex باید روی مؤلفه فرعی‌ای تنظیم شود که حاوی معناشناسی است و توسط سرویس‌های دسترس‌پذیری انتخاب خواهد شد.
  • مطمئن شوید همه عناصری که بررسی می‌کنید در یک سطح zIndex باشند، زیرا این امر بر معناشناسی و ترتیب پیمایش نیز تأثیر می‌گذارد.
  • مطمئن شوید که هیچ معناشناسی‌ای به‌طور غیرضروری ادغام نشده باشد، زیرا این امر ممکن است بر اینکه شاخص‌های پیمایش به کدام مؤلفه‌ها اعمال می‌شوند تأثیر بگذارد.