علاوهبر اطلاعات اصلی که یک ترکیبپذیر حمل میکند، مانند رشته نوشتاری
یک ترکیبپذیر Text، داشتن اطلاعات تکمیلی بیشتر درباره عناصر میانای کاربر میتواند مفید باشد.
اطلاعات مربوط به معنی و نقش مؤلفه در Compose معناشناسی نامیده میشود که روشی برای ارائه بافتار اضافی درباره مؤلفههای تشکیلدهنده به سرویسهایی مانند دسترسپذیری، تکمیل خودکار، و آزمایش است. برای مثال، نماد دوربین ممکن است ازنظر بصری فقط یک تصویر باشد، اما معنی معنایی آن میتواند «عکس گرفتن» باشد.
با ترکیب کردن معناشناسی مناسب با Compose API مناسب، تا جایی که ممکن است اطلاعات بیشتری درباره مؤلفهتان به سرویسهای دسترسپذیری ارائه میدهید و سپس این سرویسها تصمیم میگیرند که چگونه آن را به کاربر نشان دهند.
میاناهای برنامهسازی کاربردی Material و Compose UI و Foundation با معناشناسیهای داخلی ارائه میشوند که از نقش و عملکرد خاص خود پیروی میکنند، اما میتوانید این معناشناسیها را برای میاناهای برنامهسازی کاربردی موجود نیز اصلاح کنید یا معناشناسیهای جدیدی برای مؤلفههای سفارشی، براساس الزامات خاص خود، تنظیم کنید.
خصوصیات معنایی
ویژگیهای معنایی مفهوم ترکیبپذیر مربوطه را منتقل میکنند. برای مثال، ترکیبپذیر Text حاوی ویژگی معنایی text است، زیرا این معنای آن ترکیبپذیر است. Icon حاوی ویژگی contentDescription است (اگر توسط توسعهدهنده تنظیم شده باشد) که معنی نماد را بهصورت نوشتاری منتقل میکند.
درنظر بگیرید که چگونه ویژگیهای معنایی مفهوم یک ترکیبپذیر را منتقل میکنند. Switch را درنظر بگیرید. این همان چیزی است که کاربر میبیند:
Switch در حالت «روشن» و «خاموش».برای توصیف معنی این عنصر، میتوانید اینگونه بگویید: «این یک کلید است که عنصری قابلتغییر در وضعیت «روشن» است. میتوانید روی آن کلیک کنید تا با آن تعامل داشته باشید.»
این دقیقاً همان چیزی است که از ویژگیهای معنایی برای آن استفاده میشود. گره معنایی این عنصر «کلید» حاوی ویژگیهای زیر است، همانطور که با «بازرس چیدمان» تجسم شده است:
Switch composable را نشان میدهد.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) } ) } }
شرح وضعیت
یک composable میتواند یک stateDescription برای معناشناسی تعریف کند که چارچوب Android از آن برای خواندن وضعیتی که composable در آن قرار دارد استفاده میکند. برای مثال، یک composable قابلتغییر میتواند در حالت «علامتزده» یا «علامتنزده» باشد. در برخی موارد، ممکن است بخواهید برچسبهای شرح وضعیت پیشفرض را که 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() } ) ) { /* ... */ } }
کنشهای سفارشی
از کنشهای سفارشی میتوان برای اشارههای پیچیدهتر در صفحه لمسی استفاده کرد، مثل تند کشیدن برای رد کردن یا کشیدن و رها کردن، زیرا تعامل با این اشارهها میتواند برای کاربران دارای اختلالات حرکتی یا سایر ناتوانیها چالشبرانگیز باشد.
برای اینکه اشاره تند کشیدن برای بستن دسترسپذیرتر شود، میتوانید آن را به کنش سفارشی پیوند دهید و کنش بستن و برچسب را در آنجا ارسال کنید:
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 foundation و material تشکیل شده باشد، درخت «معناشناسی» بهطور خودکار برای شما پر و تولید میشود. بااینحال وقتی ترکیبشدنیهای سطح پایین سفارشی اضافه میکنید، باید معناشناسی آن را بهصورت دستی ارائه دهید. همچنین ممکن است شرایطی وجود داشته باشد که درخت شما بهطور صحیح یا کامل معنی عناصر روی صفحه را نشان ندهد، در این صورت میتوانید درخت را اصلاح کنید.
برای مثال، این تقویم سفارشی قابلترکیب را درنظر بگیرید:
در این مثال، کل تقویم بهعنوان یک ترکیبپذیر سطح پایین تکی پیادهسازی شده است که از ترکیبپذیر Layout استفاده میکند و مستقیماً در Canvas ترسیم میشود.
اگر کار دیگری انجام ندهید، سرویسهای دسترسپذیری اطلاعات کافی درباره محتوای composable و انتخاب کاربر در تقویم دریافت نخواهند کرد. برای مثال، اگر کاربر روی روزی که عدد ۱۷ را نشان میدهد کلیک کند،
چارچوب دسترسپذیری فقط اطلاعات توصیفی کل
کنترل تقویم را دریافت میکند. در این حالت، سرویس دسترسپذیری TalkBack «تقویم» یا، کمی بهتر، «تقویم آوریل» را اعلام میکند و کاربر نمیداند چه روزی انتخاب شده است. برای اینکه این composable دسترسپذیرتر شود، باید اطلاعات معنایی را بهصورت دستی اضافه کنید.
درخت ادغامشده و ادغامنشده
همانطور که قبلاً ذکر شد، هر composable در درخت واسط کاربر ممکن است صفر یا چند ویژگی معنایی تنظیمشده داشته باشد. وقتی یک composable هیچ ویژگی معنایی تنظیمشدهای ندارد، بهعنوان بخشی از درخت «معناشناسی» گنجانده نمیشود. به این ترتیب، درخت «معناشناسی» فقط حاوی گرههایی است که واقعاً معنای معنایی دارند. اما گاهی اوقات برای انتقال معنی صحیح آنچه در صفحه نشان داده میشود، ادغام کردن برخیاز زیرشاخههای گرهها و درنظر گرفتن آنها بهعنوان یک گره نیز مفید است. بهاینترتیب میتوانید درباره مجموعهای از گرهها بهعنوان یک کل استدلال کنید، بهجای اینکه با هر گره فرزند بهصورت جداگانه سروکار داشته باشید. بهعنوان یک قاعده کلی، هر گره در این درخت نشاندهنده یک عنصر قابلتمرکز هنگام استفاده از سرویسهای «دسترسپذیری» است.
نمونهای از چنین ترکیبپذیری Button است. میتوانید دکمه را بهعنوان یک عنصر واحد درنظر بگیرید،
هرچند ممکن است حاوی چندین گره فرزند باشد:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
در درخت «معناشناسی»، ویژگیهای فرزندان دکمه ادغام میشوند، و دکمه بهعنوان یک گره برگ واحد در درخت ارائه میشود:
Composables و اصلاحکنندهها میتوانند با فراخوانی Modifier.semantics
(mergeDescendants = true) {} نشان دهند که میخواهند ویژگیهای معنایی فرزندان خود را ادغام کنند. تنظیم این ویژگی روی true نشان میدهد که
ویژگیهای معنایی باید ادغام شوند. در مثال Button،
ترکیبپذیر Button بهطور داخلی از اصلاحکننده clickable استفاده میکند که شامل این
اصلاحکننده semantics است. بنابراین، گرههای فرزند دکمه ادغام میشوند.
برای کسب اطلاعات بیشتر درباره اینکه چه زمانی باید رفتار ادغام را در ترکیبشدنی خود تغییر دهید، مستندات دسترسپذیری را بخوانید.
چندین اصلاحکننده و ترکیبشدنی در کتابخانههای Foundation و Material Compose
این ویژگی را تنظیم کردهاند. برای مثال، اصلاحکنندههای 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
- آزمایش کردن چیدمان Compose