علاوهبر اطلاعات اصلی که یک عنصر ترکیبی حمل میکند، مانند رشته نوشتاری
یک عنصر ترکیبی Text، داشتن اطلاعات تکمیلی بیشتر درباره عناصر میانای کاربر میتواند مفید باشد.
اطلاعات مربوط به معنا و نقش یک عنصر در Compose را معناشناسی مینامند که روشی برای ارائه بافتار اضافی درباره عناصر ترکیبی به سرویسهایی مثل دسترسپذیری، تکمیل خودکار، و آزمایش است. برای مثال، نماد دوربین ممکن است ازنظر بصری فقط یک تصویر باشد، اما معنای معنایی آن میتواند «عکس بگیر» باشد.
با ترکیب معناشناسی مناسب با «میاناهای برنامهسازی کاربردی Compose» مناسب، تا حد امکان اطلاعاتی درباره عنصرتان دراختیار خدمات دسترسپذیری قرار میدهید، که سپس تصمیم میگیرند چگونه آن را به کاربر نشان دهند.
میاناهای برنامهسازی کاربردی «پایه» و «میانای کاربر آهنگسازی» و «مواد» با معناشناسی داخلی ارائه میشوند که از نقش و عملکرد خاص خود پیروی میکنند، اما میتوانید این معناشناسی را برای میاناهای برنامهسازی کاربردی موجود تغییر دهید یا معناشناسی جدیدی برای عناصر سفارشی، براساس الزامات خاص خودتان، تنظیم کنید.
خصوصیات معنایی
خواص معنایی مفهوم عنصر ترکیبی مربوطه را منتقل میکنند. برای مثال، عنصر ترکیبی Text حاوی دارایی معنایی text است، زیرا این معنا آن عنصر ترکیبی است. Icon حاوی
contentDescription دارایی (اگر توسط توسعهدهنده تنظیم شده باشد) است که معنای نماد را بهصورت نوشتاری منتقل میکند.
درنظر بگیرید که چگونه خواص معنایی مفهوم یک عنصر ترکیبی را منتقل میکنند. Switch را درنظر بگیرید. کاربر آن را اینگونه میبیند:
Switch در حالت «روشن» و «خاموش».برای توصیف معنی این عنصر، میتوانید بگویید: «این یک «کلید» است که عنصری قابلتغییر در وضعیت «روشن» است. میتوانید روی آن کلیک کنید تا با آن تعامل داشته باشید."
دقیقاً برای همین منظور از داراییهای معنایی استفاده میشود. گره معنایی این عنصر «کلید» حاوی داراییهای زیر است، همانگونه که با بازرس چیدمان تجسم شده است:
Switch قابل ترکیب را نشان میدهد.Role نوع عنصر را نشان میدهد. StateDescription نحوه ارجاع به حالت «روشن» را شرح میدهد. بهطور پیشفرض، این نسخه محلیسازیشده کلمه «روشن» است، اما براساس بافت میتوان آن را دقیقتر کرد (برای مثال، «فعال»). ToggleableState وضعیت فعلی «کلید» است. خصوصیت
OnClick به روش استفادهشده برای تعامل با این عنصر ارجاع میدهد.
پیگیری کردن ویژگیهای معنایی هر عنصر ترکیبی در برنامه شما امکانات قدرتمند زیادی را فراهم میکند:
- خدمات دسترسپذیری از این ویژگیها برای نمایش میانای کاربر در صفحه و اجازه دادن به کاربران برای تعامل با آن استفاده میکنند. برای عنصر ترکیبی «کلید»، Talkback ممکن است اعلام کند: «روشن؛ کلید؛ برای روشن/خاموش کردن دو تکضرب بزنید». کاربر میتواند با دو تکضرب زدن روی صفحهنمایش، «کلید» را روشن/خاموش کند.
-
چارچوب «آزمایش» از این داراییها برای یافتن گرهها، تعامل با آنها، و انجام ادعاها استفاده میکند:
val mySwitch = SemanticsMatcher.expectValue( SemanticsProperties.Role, Role.Switch ) composeTestRule.onNode(mySwitch) .performClick() .assertIsOff()
ترکیبشوندهها و اصلاحکنندههایی که روی Compose کتابخانه پایه ساخته شدهاند، ازقبل ویژگیهای مربوطه را بهطور پیشفرض برای شما تنظیم میکنند. بهصورت اختیاری، میتوانید این ویژگیها را بهصورت دستی تغییر دهید تا پشتیبانی از دسترسپذیری را برای موارد استفاده خاص بهبود دهید، یا استراتژی ادغام یا پاکسازی عناصر ترکیبی خود را تغییر دهید.
برای نشان دادن نوع محتوای خاص عنصر به سرویسهای دسترسپذیری، میتوانید از انواع مختلف معناشناسی استفاده کنید. این افزودهها از اطلاعات معنایی اصلی در مکان پشتیبانی میکنند و به خدمات دسترسپذیری کمک میکنند نحوه نمایش، اعلام، یا تعامل با عنصر شما را دقیق تنظیم کنند.
برای فهرست کامل داراییهای معنایی، به
SemanticsProperties شیء مراجعه کنید. برای فهرست کامل «کنشهای» دسترسپذیری ممکن،
شیء SemanticsActions را ببینید.
سرصفحهها
برنامهها اغلب حاوی صفحههایی با محتوای نوشتاری غنی، مثل مقالههای طولانی یا صفحات خبری هستند که معمولاً با سرصفحههای مختلف به زیربخشهای مختلف تقسیم میشوند:
کاربران دارای نیازهای دسترسپذیری ممکن است در پیمایش آسان چنین صفحهای
دچار مشکل شوند. برای بهبود تجربه پیمایش، برخیاز سرویسهای دسترسپذیری امکان پیمایش آسانتر را مستقیماً بین بخشها یا عنوانها فراهم میکنند. برای فعال کردن این ویژگی، با تعریف کردن دارایی معنایی آن، نشان دهید که عنصرتان heading است:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
هشدارها و بالاپرها
اگر عنصر شما هشدار یا بالاپری است، مثلاً Snackbar، شاید بخواهید به خدمات دسترسپذیری علامت دهید که ساختار جدید یا بهروزرسانیهای محتوا میتواند به کاربران منتقل شود.
عناصر شبیه هشدار را میتوان با ویژگی معنایی liveRegion علامتگذاری کرد. این تنظیم به سرویسهای دسترسپذیری اجازه میدهد کاربر را بهطور خودکار از
تغییرات این عنصر یا عناصر فرزند آن مطلع کند:
PopupAlert( message = "You have a new message", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite } )
در اکثر مواردی که توجه کاربران باید فقط بهطور خلاصه به هشدارها یا محتوای مهم درحال تغییر روی صفحه جلب شود، باید از liveRegionMode.Polite استفاده کنید.
برای جلوگیری از بازخورد مختلکننده، باید از liveRegion.Assertive بهصورت محدود استفاده کنید.
این ویژگی باید برای موقعیتهایی استفاده شود که آگاه کردن کاربران از محتوای حساس به زمان حیاتی است:
PopupAlert( message = "Emergency alert incoming", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Assertive } )
از مناطق زنده نباید در محتوایی که بهطور مکرر بهروز میشود، مانند تایمرهای شمارش معکوس، استفاده شود تا از سردرگم کردن کاربران با بازخورد مداوم جلوگیری شود.
عناصر پنجرهمانند
عناصر سفارشی پنجرهمانند، شبیه به ModalBottomSheet، برای متمایز شدن از محتوای اطراف به نشانهای
اضافی نیاز دارند. برای این کار، میتوانید از
paneTitle معناشناسی استفاده کنید تا هرگونه تغییر پنجره یا قاب مرتبط بتواند
بهدرستی توسط سرویسهای دسترسپذیری نشان داده شود، همراه با اطلاعات
معناشناسی اصلی آن:
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
برای مرجع، ببینید Material 3 چگونه از paneTitle برای عناصرش استفاده میکند.
عناصر خطا
برای انواع دیگر محتوا، مثل عناصر شبیه خطا، ممکن است بخواهید
اطلاعات معنایی اصلی را برای کاربران دارای نیازهای دسترسپذیری گسترش دهید.
هنگام تعریف وضعیتهای خطا، میتوانید خدمات دسترسپذیری را از معناشناسی
error آن مطلع کنید و پیامهای خطای گسترده ارائه دهید.
در این مثال، TalkBack اطلاعات نوشتاری خطای اصلی را میخواند و پساز آن پیامرسانی اضافی و ازهم بازشده را میخواند:
Error( errorText = "Fields cannot be empty", modifier = Modifier .semantics { error("Please add both email and password") } )
عناصر پیگیری پیشرفت
برای عناصر سفارشی که پیشرفت را پیگیری میکنند، ممکن است بخواهید کاربران را از تغییرات پیشرفتشان، ازجمله مقدار پیشرفت فعلی، محدوده آن، و اندازه گام مطلع کنید. میتوانید این کار را با معناشناسی progressBarRangeInfo انجام دهید―این کار تضمین میکند که سرویسهای دسترسپذیری از تغییرات پیشرفت مطلع میشوند و میتوانند کاربران را براساس آن بهروز کنند. فناوریهای کمکی مختلف ممکن است روشهای منحصربهفردی برای اشاره به افزایش و کاهش پیشرفت داشته باشند.
ProgressInfoBar( modifier = Modifier .semantics { progressBarRangeInfo = ProgressBarRangeInfo( current = progress, range = 0F..1F ) } )
اطلاعات فهرست و مورد
در فهرستها و شبکههای سفارشی با تعداد زیادی مورد، ممکن است برای خدمات دسترسپذیری مفید باشد که اطلاعات دقیقتری مثل تعداد کل موارد و شاخصها را نیز دریافت کند.
بااستفاده از معناشناسی collectionInfo و 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) } ) } }
شرح وضعیت
عنصر ترکیبی میتواند stateDescription را برای معناشناسی تعریف کند که
چارچوب Android از آن برای خواندن وضعیت عنصر ترکیبی استفاده میکند. برای
مثال، یک عنصر ترکیبی قابلتغییر میتواند در حالت «علامتدار» یا «بدون علامت» باشد. در برخی موارد، ممکن است بخواهید برچسبهای
توضیحات وضعیت پیشفرضی را که Compose استفاده میکند ملغی کنید. میتوانید این کار را با مشخص کردن صریح برچسبهای شرح وضعیت قبلاز تعریف یک عنصر ترکیبی بهعنوان قابلتغییر انجام دهید:
@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() } ) ) { /* ... */ } }
کنشهای سفارشی
از کنشهای سفارشی میتوان برای اشارههای پیچیدهتر صفحه لمسی، مانند کشیدن برای بستن یا کشیدن و رها کردن، استفاده کرد، زیرا تعامل با این اشارهها برای کاربران دارای اختلالات حرکتی یا ناتوانیهای دیگر میتواند چالشبرانگیز باشد.
برای اینکه اشاره تند کشیدن برای بستن دردسترستر باشد، میتوانید آن را به کنش سفارشی پیوند دهید و کنش و برچسب بستن را به آن منتقل کنید:
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 عنصر را برجسته میکند و اشاره میکند که کنشهای بیشتری در منو آن دردسترس است، که نشاندهنده کنش تند کشیدن برای بستن در آنجا است:
مورد استفاده دیگر برای کنشهای سفارشی، فهرستهای طولانی با مواردی است که کنشهای دردسترس بیشتری دارند، زیرا ممکن است برای کاربران خستهکننده باشد که هر کنش را برای هر مورد بهصورت جداگانه تکرار کنند:
برای بهبود تجربه پیمایش، که بهویژه برای فناوریهای کمکی تعاملی مثل «دسترسی با کلید» یا «دسترسی گفتاری» مفید است، میتوانید از کنشهای سفارشی در محتوی استفاده کنید تا کنشها را از پیمایش تکی به منو کنش جداگانهای منتقل کنید:
ArticleListItemRow( modifier = Modifier .semantics { customActions = listOf( CustomAccessibilityAction( label = "Open article", action = { openArticle() true } ), CustomAccessibilityAction( label = "Add to bookmarks", action = { addToBookmarks() true } ), ) } ) { Article( modifier = Modifier.clearAndSetSemantics { }, onClick = openArticle, ) BookmarkButton( modifier = Modifier.clearAndSetSemantics { }, onClick = addToBookmarks, ) }
در این موارد، حتماً معناشناسی اصلی کودکان را بهصورت دستی با
اصلاحکننده clearAndSetSemantics پاک کنید، زیرا آنها را به
کنشهای سفارشی منتقل میکنید.
بااستفاده از «دسترسی با کلید» بهعنوان مثال، منو آن با انتخاب ظرف باز میشود و کنشهای تودرتوی دردسترس را در آنجا فهرست میکند:
درخت معناشناسی
ترکیب واسط کاربر برنامه شما را توصیف میکند و با اجرای ترکیبپذیرها تولید میشود. ترکیب یک ساختار درختی است که از ترکیبپذیرهایی تشکیل شده است که رابط کاربری شما را توصیف میکنند.
در کنار «ترکیب»، درخت موازیای وجود دارد که درخت معنایی نامیده میشود. این درخت رابط کاربری شما را به روشی جایگزین که برای سرویسهای دسترسپذیری و چارچوب آزمایش قابلفهم است توصیف میکند. خدمات دسترسپذیری از این درخت برای توصیف برنامه به کاربرانی که نیازهای خاص دارند استفاده میکنند. چارچوب آزمایش از درخت برای تعامل با برنامه شما و اظهارات درباره آن استفاده میکند. درخت «معناشناسی» حاوی اطلاعاتی درباره نحوه کشیدن عناصر ترکیبی نیست، اما حاوی اطلاعاتی درباره معنای معنایی عناصر ترکیبی است.
اگر برنامه شما از عناصر ترکیبی و اصلاحکنندههای کتابخانه پایه Compose و Material تشکیل شده باشد، درخت «معانی» بهطور خودکار برای شما تکمیل و تولید میشود. بااینحال، وقتی که عناصر ترکیبی سطح پایین سفارشی اضافه میکنید، باید معناشناسی آن را بهصورت دستی ارائه دهید. همچنین ممکن است شرایطی وجود داشته باشد که درخت شما معنای عناصر روی صفحه را بهدرستی یا بهطور کامل نشان ندهد، در این صورت میتوانید درخت را تطبیق دهید.
برای مثال، این عنصر ترکیبی تقویم سفارشی را درنظر بگیرید:
در این مثال، کل تقویم بهعنوان یک عنصر ترکیبی سطح پایین واحد پیادهسازی شده است و از عنصر ترکیبی Layout استفاده میکند و مستقیماً در Canvas طراحی میکند.
اگر کار دیگری انجام ندهید، خدمات دسترسپذیری اطلاعات کافی درباره محتوای
ترکیبی و انتخاب کاربر در تقویم دریافت نخواهد کرد. برای مثال، اگر کاربری روی روزی که حاوی ۱۷ است کلیک کند، چارچوب
دسترسپذیری فقط اطلاعات شرح کنترل کل تقویم را دریافت میکند. در این حالت، سرویس دسترسپذیری TalkBack
اعلام میکند «تقویم» یا، کمی بهتر، «تقویم آوریل» و کاربر
باید حدس بزند چه روزی انتخاب شده است. برای اینکه این عنصر ترکیبی
دسترسپذیرتر شود، باید اطلاعات معنایی را بهصورت دستی اضافه کنید.
درخت ادغامشده و ادغامنشده
همانطور که قبلاً ذکر شد، هر عنصر ترکیبی در درخت واسط کاربر ممکن است صفر یا چند ویژگی معنایی تنظیمشده داشته باشد. وقتی یک عنصر ترکیبی هیچ ویژگی معناییای نداشته باشد، بهعنوان بخشی از درخت «معناشناسی» اضافه نمیشود. به این ترتیب، درخت «معانی» فقط شامل گرههایی است که واقعاً معنای معنایی دارند. بااینحال، گاهی اوقات برای انتقال معنای صحیح آنچه در صفحه نشان داده میشود، ادغام برخیاز زیردرختهای گرهها و برخورد با آنها بهعنوان یک گره نیز مفید است. به این ترتیب میتوانید درباره مجموعهای از گرهها بهصورت کلی استدلال کنید، بهجای اینکه با هر گره فرزند بهصورت جداگانه سروکار داشته باشید. بهطور کلی، هر گره در این درخت هنگام استفاده از «خدمات دسترسپذیری» نشاندهنده یک عنصر قابلتمرکز است.
نمونهای از چنین ترکیبی Button است. میتوانید درباره دکمه بهعنوان یک عنصر واحد استدلال کنید، حتی اگر ممکن است شامل چندین گره فرزند باشد:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
در درخت «معناشناسی»، داراییهای فرزندان دکمه ادغام میشود، و دکمه بهعنوان یک گره برگ واحد در درخت ارائه میشود:
ترکیبشوندهها و اصلاحکنندهها میتوانند با فراخوانی Modifier.semantics
(mergeDescendants = true) {} نشان دهند که میخواهند ویژگیهای معنایی فرزندانشان را ادغام کنند. تنظیم این دارایی روی true نشان میدهد که
داراییهای معنایی باید ادغام شوند. در مثال Button، عنصر ترکیبی Button بهصورت داخلی از اصلاحکننده clickable استفاده میکند که شامل اصلاحکننده semantics است. بنابراین، گرههای فرزند دکمه ادغام میشوند.
برای کسب اطلاعات بیشتر درباره اینکه چه زمانی باید رفتار ادغام را در عنصر ترکیبیتان تغییر دهید، مستندات دسترسپذیری را بخوانید.
چندین اصلاحگر و عنصر ترکیبی در کتابخانههای «پایه» و «ترکیب Material» این ویژگی را تنظیم کردهاند. برای مثال، اصلاحکنندههای clickable و toggleable
بهطور خودکار فرزندانشان را ادغام میکنند. همچنین، عنصر ترکیبی ListItem
فرزندان خود را ادغام خواهد کرد.
بازرسی درخت
درخت معنایی درواقع دو درخت متفاوت است. درخت معنایی ادغامشدهای وجود دارد که وقتی mergeDescendants روی true تنظیم میشود، گرههای فرزند را ادغام میکند.
همچنین درخت معنایی ادغامنشدهای وجود دارد که ادغام را اعمال نمیکند، اما هر گره را دستنخورده نگه میدارد. خدمات دسترسپذیری از درخت ادغامنشده استفاده میکنند و
الگوریتمهای ادغام خودشان را با درنظر گرفتن mergeDescendants
دارایی اعمال میکنند. چارچوب آزمایش بهطور پیشفرض از درخت ادغامشده استفاده میکند.
با روش printToLog() میتوانید هر دو درخت را بررسی کنید. بهطور پیشفرض، و همانطور که در
مثالهای قبلی دیدید، درخت ادغامشده ثبت میشود. برای چاپ کردن درخت ادغامنشده
بهجای آن، پارامتر useUnmergedTree مطابقتدهنده onRoot() را روی
true تنظیم کنید:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")
«بازرس چیدمان» به شما امکان میدهد با انتخاب کردن مورد دلخواه در فیلتر نما، درخت «معانی» ادغامشده و ادغامنشده را نمایش دهید:
برای هر گره در درخت، «بازرس چیدمان» هم «معناشناسی ادغامشده» و هم «معناشناسی» تنظیمشده در آن گره را در پانل ویژگیها نشان میدهد:
بهطور پیشفرض، تطبیقدهندهها در «چارچوب آزمون» از درخت معناشناسی ادغامشده استفاده میکنند.
به همین دلیل میتوانید با مطابقت دادن نوشتار نشاندادهشده در Button با آن تعامل داشته باشید:
composeTestRule.onNodeWithText("Like").performClick()
با تنظیم پارامتر useUnmergedTree در
مطابقتدهندهها روی true، مانند مطابقتدهنده onRoot، این رفتار را ملغی کنید.
تطبیق دادن درخت
همانطور که قبلاً ذکر شد، میتوانید برخیاز ویژگیهای معنایی را ملغی کنید یا پاک کنید یا رفتار ادغام درخت را تغییر دهید. این موضوع بهویژه زمانی که شما درحال ایجاد کردن عناصر سفارشی خودتان هستید اهمیت دارد. بدون تنظیم ویژگیهای صحیح و رفتار ادغام، ممکن است برنامه شما دردسترس نباشد و آزمایشها ممکن است متفاوت از آنچه انتظار دارید رفتار کنند. اگر میخواهید درباره آزمایش بیشتر بدانید، راهنمای آزمایش را ببینید.
توصیهشده برای شما
- توجه: نوشتار پیوند وقتی جاوا اسکریپت خاموش است نمایش داده میشود
- دسترسپذیری در Compose
- Material Design 2 در Compose
- آزمایش کردن چیدمان «نوشتن»