یک ترکیب ، رابط کاربری برنامه شما را توصیف می کند و با اجرای composable ها تولید می شود. ترکیب یک ساختار درختی است که از ترکیبهایی تشکیل شده است که رابط کاربری شما را توصیف میکنند.
در کنار ترکیب، یک درخت موازی وجود دارد که درخت معناشناسی نامیده می شود. این درخت رابط کاربری شما را به روشی جایگزین توصیف میکند که برای سرویسهای دسترسپذیری و چارچوب تست قابل درک است. سرویسهای دسترسپذیری از درخت برای توصیف برنامه برای کاربران با نیاز خاص استفاده میکنند. چارچوب تست از درخت برای تعامل با برنامه شما و اظهار نظر در مورد آن استفاده می کند. درخت Semantics حاوی اطلاعاتی در مورد نحوه ترسیم کامپوزیشنهای شما نیست، اما حاوی اطلاعاتی در مورد معنای معنایی اجزای سازنده شما است.
اگر برنامه شما از ترکیبکنندهها و اصلاحکنندههای Compose Foundation و کتابخانه مواد تشکیل شده باشد، درخت Semantics بهطور خودکار برای شما پر و تولید میشود. با این حال، هنگامی که ترکیبپذیرهای سطح پایین سفارشی را اضافه میکنید، باید معنای آن را به صورت دستی ارائه کنید . همچنین ممکن است شرایطی وجود داشته باشد که درخت شما به درستی یا به طور کامل معنای عناصر روی صفحه را نشان ندهد، در این صورت می توانید درخت را تطبیق دهید.
به عنوان مثال این تقویم سفارشی را در نظر بگیرید:
در این مثال، کل تقویم بهعنوان یک قابل ترکیب سطح پایین، با استفاده از Layout
composable و رسم مستقیم روی Canvas
پیادهسازی میشود. اگر کار دیگری انجام ندهید، سرویسهای دسترسپذیری اطلاعات کافی در مورد محتوای قابل تنظیم و انتخاب کاربر در تقویم دریافت نمیکنند. به عنوان مثال، اگر کاربر روی روز حاوی 17 کلیک کند، چارچوب دسترسی فقط اطلاعات توضیحات را برای کل کنترل تقویم دریافت می کند. در این صورت، سرویس دسترسپذیری TalkBack «تقویم» یا کمی بهتر، «تقویم آوریل» را اعلام میکند و کاربر میخواهد بداند چه روزی انتخاب شده است. برای دسترسی بیشتر به این ترکیب، باید اطلاعات معنایی را به صورت دستی اضافه کنید.
ویژگی های معنایی
همه گره های درخت UI با مقداری معنای معنایی دارای یک گره موازی در درخت Semantics هستند. گره در درخت Semantics حاوی ویژگی هایی است که معنای ترکیب پذیر مربوطه را می رساند. به عنوان مثال، Text
composable حاوی یک text
ویژگی معنایی است، زیرا این معنای آن composable است. یک Icon
حاوی ویژگی contentDescription
است (اگر توسط توسعه دهنده تنظیم شده باشد) که معنای Icon
را به صورت متنی نشان می دهد. Composable ها و Modifier هایی که در بالای کتابخانه Compose foundation ساخته شده اند، قبلاً ویژگی های مربوطه را برای شما تنظیم کرده اند. به صورت اختیاری، خودتان ویژگی ها را با semantics
و اصلاح کننده های clearAndSetSemantics
تنظیم یا لغو کنید. به عنوان مثال، اقدامات دسترسی سفارشی را به یک گره اضافه کنید، یک توضیح حالت جایگزین برای یک عنصر قابل تغییر ارائه دهید، یا نشان دهید که یک متن خاص قابل ترکیب باید به عنوان عنوان در نظر گرفته شود.
برای تجسم درخت Semantics، از Layout Inspector Tool یا از متد printToLog()
در تست ها استفاده کنید. این درخت Semantics فعلی را در Logcat چاپ می کند.
class MyComposeTest { @get:Rule val composeTestRule = createComposeRule() @Test fun MyTest() { // Start the app composeTestRule.setContent { MyTheme { Text("Hello world!") } } // Log the full semantics tree composeTestRule.onRoot().printToLog("MY TAG") } }
خروجی این تست خواهد بود:
Printing with useUnmergedTree = 'false'
Node #1 at (l=0.0, t=63.0, r=221.0, b=120.0)px
|-Node #2 at (l=0.0, t=63.0, r=221.0, b=120.0)px
Text = '[Hello world!]'
Actions = [GetTextLayoutResult]
در نظر بگیرید که چگونه ویژگی های معنایی معنای یک ترکیب پذیر را منتقل می کنند. یک Switch
را در نظر بگیرید. این شکلی است که برای کاربر به نظر می رسد:
برای توصیف معنای این عنصر، میتوانید موارد زیر را بگویید: "این یک سوئیچ است که یک عنصر قابل تغییر در حالت "روشن" است. میتوانید روی آن کلیک کنید تا با آن تعامل داشته باشید.
این دقیقاً همان چیزی است که از ویژگی های معنایی استفاده می شود. گره معنایی این عنصر سوئیچ دارای ویژگی های زیر است که با Layout Inspector به تصویر کشیده شده است:
Role
نوع عنصر را نشان می دهد. StateDescription
نحوه ارجاع به حالت "روشن" را توضیح می دهد. بهطور پیشفرض، این یک نسخه محلیشده از کلمه «روشن» است، اما میتوان آن را بر اساس زمینه خاصتر کرد (به عنوان مثال، «فعال»). ToggleableState
وضعیت فعلی سوئیچ است. ویژگی OnClick
به روش استفاده شده برای تعامل با این عنصر اشاره می کند. برای یک لیست کامل از ویژگی های معنایی، شی SemanticsProperties
بررسی کنید. برای لیست کاملی از اقدامات امکان دسترسی، شی SemanticsActions
بررسی کنید.
ردیابی ویژگیهای معنایی هر یک از قابلیتهای ترکیبی در برنامه شما، بسیاری از احتمالات قدرتمند را باز میکند. چند نمونه:
- Talkback از ویژگیها برای خواندن با صدای بلند آنچه روی صفحه نمایش داده میشود استفاده میکند و به کاربر اجازه میدهد به راحتی با آن تعامل داشته باشد. برای Switch composable، Talkback ممکن است بگوید: «روشن؛ سوئیچ؛ برای جابجایی دو ضربه سریع بزنید». کاربر می تواند روی صفحه نمایش خود دو بار ضربه بزند تا خاموش شود.
- چارچوب تست از ویژگی ها برای یافتن گره ها، تعامل با آنها و اظهار نظر استفاده می کند. یک آزمایش نمونه برای سوئیچ می تواند این باشد:
val mySwitch = SemanticsMatcher.expectValue( SemanticsProperties.Role, Role.Switch ) composeTestRule.onNode(mySwitch) .performClick() .assertIsOff()
درخت معناشناسی ادغام شده و ادغام نشده
همانطور که قبلا ذکر شد، هر یک از ترکیبپذیرها در درخت UI ممکن است دارای صفات معنایی صفر یا بیشتر باشد. وقتی یک composable هیچ مجموعه ای از ویژگی های معنایی ندارد، به عنوان بخشی از درخت Semantics گنجانده نمی شود. به این ترتیب، درخت Semantics فقط شامل گره هایی است که در واقع حاوی معنای معنایی هستند. با این حال، گاهی اوقات برای انتقال معنای صحیح آنچه روی صفحه نمایش داده می شود، ادغام برخی از زیردرخت های گره ها و در نظر گرفتن آنها به عنوان یکی نیز مفید است. به این ترتیب میتوانید بهجای اینکه با هر نود بهصورت جداگانه سروکار داشته باشید، درباره مجموعهای از گرهها بهعنوان یک کل استدلال کنید. به عنوان یک قاعده کلی، هر گره در این درخت نشان دهنده یک عنصر قابل تمرکز هنگام استفاده از خدمات دسترسی است.
نمونه ای از چنین ترکیب پذیری Button
است. شما می توانید در مورد یک دکمه به عنوان یک عنصر استدلال کنید، حتی اگر ممکن است چندین گره فرزند داشته باشد:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
در درخت Semantics، ویژگیهای نوادگان دکمه ادغام میشوند و دکمه به صورت یک گره برگ در درخت ارائه میشود:
ترکیبکنندهها و اصلاحکنندهها میتوانند با فراخوانی Modifier.semantics (mergeDescendants = true) {}
نشان دهند که میخواهند ویژگیهای معنایی فرزندان خود را ادغام کنند. تنظیم این ویژگی روی true
نشان می دهد که ویژگی های semantics باید ادغام شوند. در مثال Button
، Button
composable از اصلاح کننده clickable
به صورت داخلی استفاده می کند که شامل این اصلاح کننده semantics
است. بنابراین، نودهای نود دکمه ادغام می شوند. اسناد دسترسپذیری را بخوانید تا درباره اینکه چه زمانی باید رفتار ادغام را در ترکیببندی خود تغییر دهید، بیشتر بدانید.
چندین اصلاح کننده و ترکیب پذیر در کتابخانه های Foundation و Material Compose دارای این ویژگی هستند. به عنوان مثال، اصلاح کننده های clickable
و toggleable
به طور خودکار فرزندان خود را ادغام می کنند. همچنین، ListItem
composable نوادگان خود را ادغام می کند.
درختان را بررسی کنید
درخت معناشناسی در واقع دو درخت متفاوت است. یک درخت Semantics ادغام شده وجود دارد که وقتی mergeDescendants
روی true
تنظیم می شود، گره های نسل را ادغام می کند. همچنین یک درخت Semantics ادغام نشده وجود دارد که ادغام را اعمال نمی کند، اما هر گره را دست نخورده نگه می دارد. سرویسهای دسترسی از درخت ادغام نشده استفاده میکنند و الگوریتمهای ادغام خود را با در نظر گرفتن ویژگی mergeDescendants
اعمال میکنند. چارچوب تست به طور پیش فرض از درخت ادغام شده استفاده می کند.
می توانید هر دو درخت را با متد printToLog()
بررسی کنید. به طور پیش فرض، و مانند مثال های قبلی، درخت ادغام شده ثبت می شود. برای چاپ درخت ادغام نشده، پارامتر useUnmergedTree
تطبیق دهنده onRoot()
را روی true
تنظیم کنید:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")
Layout Inspector به شما امکان می دهد هر دو درخت Semantics ادغام شده و ادغام نشده را با انتخاب مورد ترجیحی در فیلتر view نمایش دهید:
برای هر گره در درخت شما، Layout Inspector هر دو Semantics ادغام شده و Semantics را روی آن گره در پانل خواص نشان می دهد:
به طور پیشفرض، تطبیقکنندگان در چارچوب تست از درخت Semantics ادغام شده استفاده میکنند. به همین دلیل است که می توانید با یک Button
با تطبیق متن نشان داده شده در داخل آن تعامل داشته باشید:
composeTestRule.onNodeWithText("Like").performClick()
با تنظیم پارامتر useUnmergedTree
تطبیقدهندهها روی true
، مانند تطبیق onRoot
، این رفتار را نادیده بگیرید.
رفتار ادغام
وقتی یک کامپوزیشن نشان می دهد که فرزندانش باید ادغام شوند، این ادغام دقیقا چگونه اتفاق می افتد؟
هر ویژگی معنایی یک استراتژی ادغام تعریف شده دارد. به عنوان مثال، ویژگی ContentDescription
تمام مقادیر ContentDescription را به یک لیست اضافه می کند. استراتژی ادغام یک ویژگی semantics را با بررسی اجرای mergePolicy
آن در SemanticsProperties.kt
بررسی کنید. ویژگیها میتوانند مقدار والد یا فرزند را بگیرند، مقادیر را در یک لیست یا رشته ادغام کنند، اصلاً اجازه ادغام را ندهند و به جای آن یک استثنا ایجاد کنند، یا هر استراتژی ادغام سفارشی دیگری.
نکته مهم این است که فرزندانی که خودشان mergeDescendants = true
تنظیم کرده اند در ادغام گنجانده نمی شوند. به یک مثال نگاه کنید:
در اینجا یک مورد لیست قابل کلیک وجود دارد. هنگامی که کاربر ردیف را فشار می دهد، برنامه به صفحه جزئیات مقاله می رود، جایی که کاربر می تواند مقاله را بخواند. در داخل آیتم فهرست، دکمه ای برای نشانک گذاری مقاله وجود دارد که یک عنصر قابل کلیک تودرتو را تشکیل می دهد، بنابراین دکمه به طور جداگانه در درخت ادغام شده نشان داده می شود. بقیه مطالب در ردیف ادغام می شوند:
درخت معناشناسی را تطبیق دهید
همانطور که قبلا ذکر شد، می توانید برخی از ویژگی های معنایی را لغو یا پاک کنید یا رفتار ادغام درخت را تغییر دهید. این امر به ویژه زمانی مرتبط است که شما در حال ایجاد اجزای سفارشی خود هستید. بدون تنظیم ویژگیها و رفتار ادغام درست، ممکن است برنامه شما در دسترس نباشد و آزمایشها متفاوت از آنچه انتظار دارید رفتار کنند. برای مطالعه بیشتر در مورد برخی موارد استفاده متداول که باید درخت Semantics را تطبیق دهید، اسناد دسترسی را بخوانید. اگر میخواهید درباره آزمایش بیشتر بدانید، راهنمای تست را بررسی کنید.
منابع اضافی
- دسترسپذیری : مفاهیم و تکنیکهای اساسی مشترک در همه برنامههای اندروید
- ساخت برنامههای قابل دسترس : مراحل کلیدی که میتوانید برای دسترسی بیشتر برنامه خود بردارید
- اصول برای بهبود دسترسی به برنامه : اصول کلیدی که باید هنگام کار برای دسترسی بیشتر به برنامه خود در نظر داشته باشید
- Testing for Accessibility : تست اصول و ابزار برای دسترسی اندروید
برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- قابلیت دسترسی در نوشتن
- Material Design 2 در Compose
- آزمایش طرحبندی Compose شما