معناشناسی در نوشتن

یک ترکیب ، رابط کاربری برنامه شما را توصیف می کند و با اجرای composable ها تولید می شود. ترکیب یک ساختار درختی است که از ترکیب‌هایی تشکیل شده است که رابط کاربری شما را توصیف می‌کنند.

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

یک سلسله مراتب رابط کاربری معمولی و درخت معنایی آن
شکل 1. یک سلسله مراتب رابط کاربری معمولی و درخت معنایی آن.

اگر برنامه شما از ترکیب‌کننده‌ها و اصلاح‌کننده‌های Compose Foundation و کتابخانه مواد تشکیل شده باشد، درخت Semantics به‌طور خودکار برای شما پر و تولید می‌شود. با این حال، هنگامی که ترکیب‌پذیرهای سطح پایین سفارشی را اضافه می‌کنید، باید معنای آن را به صورت دستی ارائه کنید . همچنین ممکن است شرایطی وجود داشته باشد که درخت شما به درستی یا به طور کامل معنای عناصر روی صفحه را نشان ندهد، در این صورت می توانید درخت را تطبیق دهید.

به عنوان مثال این تقویم سفارشی را در نظر بگیرید:

یک تقویم سفارشی قابل تنظیم با عناصر روز قابل انتخاب
شکل 2. یک تقویم سفارشی قابل تنظیم با عناصر روز قابل انتخاب.

در این مثال، کل تقویم به‌عنوان یک قابل ترکیب سطح پایین، با استفاده از 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 را در نظر بگیرید. این شکلی است که برای کاربر به نظر می رسد:

شکل 3. یک سوئیچ در حالت "روشن" و "خاموش" خود..

برای توصیف معنای این عنصر، می‌توانید موارد زیر را بگویید: "این یک سوئیچ است که یک عنصر قابل تغییر در حالت "روشن" است. می‌توانید روی آن کلیک کنید تا با آن تعامل داشته باشید.

این دقیقاً همان چیزی است که از ویژگی های معنایی استفاده می شود. گره معنایی این عنصر سوئیچ دارای ویژگی های زیر است که با Layout Inspector به تصویر کشیده شده است:

Layout Inspector که ویژگی‌های Semantics یک Switch را نشان می‌دهد
شکل 4. Layout Inspector که خصوصیات Semantics یک سوئیچ قابل ترکیب را نشان می دهد.

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، ویژگی‌های نوادگان دکمه ادغام می‌شوند و دکمه به صورت یک گره برگ در درخت ارائه می‌شود:

نمایش معنایی تک برگ ادغام شده
شکل 5. نمایش معنایی تک برگ ادغام شده.

ترکیب‌کننده‌ها و اصلاح‌کننده‌ها می‌توانند با فراخوانی 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 ادغام‌شده و غیرادغام‌شده را فراهم می‌کند.
شکل 6. گزینه های نمای Layout Inspector که امکان نمایش درخت Semantics ادغام شده و ادغام نشده را فراهم می کند.

برای هر گره در درخت شما، Layout Inspector هر دو Semantics ادغام شده و Semantics را روی آن گره در پانل خواص نشان می دهد:

ویژگی های معنایی ادغام و تنظیم شدند
شکل 7. خصوصیات معنایی ادغام و تنظیم شدند.

به طور پیش‌فرض، تطبیق‌کنندگان در چارچوب تست از درخت Semantics ادغام شده استفاده می‌کنند. به همین دلیل است که می توانید با یک Button با تطبیق متن نشان داده شده در داخل آن تعامل داشته باشید:

composeTestRule.onNodeWithText("Like").performClick()

با تنظیم پارامتر useUnmergedTree تطبیق‌دهنده‌ها روی true ، مانند تطبیق onRoot ، این رفتار را نادیده بگیرید.

رفتار ادغام

وقتی یک کامپوزیشن نشان می دهد که فرزندانش باید ادغام شوند، این ادغام دقیقا چگونه اتفاق می افتد؟

هر ویژگی معنایی یک استراتژی ادغام تعریف شده دارد. به عنوان مثال، ویژگی ContentDescription تمام مقادیر ContentDescription را به یک لیست اضافه می کند. استراتژی ادغام یک ویژگی semantics را با بررسی اجرای mergePolicy آن در SemanticsProperties.kt بررسی کنید. ویژگی‌ها می‌توانند مقدار والد یا فرزند را بگیرند، مقادیر را در یک لیست یا رشته ادغام کنند، اصلاً اجازه ادغام را ندهند و به جای آن یک استثنا ایجاد کنند، یا هر استراتژی ادغام سفارشی دیگری.

نکته مهم این است که فرزندانی که خودشان mergeDescendants = true تنظیم کرده اند در ادغام گنجانده نمی شوند. به یک مثال نگاه کنید:

مورد فهرست با تصویر، مقداری متن و نماد نشانک
شکل 8. فهرست مورد با تصویر، مقداری متن و نماد نشانک.

در اینجا یک مورد لیست قابل کلیک وجود دارد. هنگامی که کاربر ردیف را فشار می دهد، برنامه به صفحه جزئیات مقاله می رود، جایی که کاربر می تواند مقاله را بخواند. در داخل آیتم فهرست، دکمه ای برای نشانک گذاری مقاله وجود دارد که یک عنصر قابل کلیک تودرتو را تشکیل می دهد، بنابراین دکمه به طور جداگانه در درخت ادغام شده نشان داده می شود. بقیه مطالب در ردیف ادغام می شوند:

درخت ادغام شده حاوی چندین متن در یک لیست در داخل گره Row است. درخت ادغام نشده شامل گره های جداگانه برای هر متن قابل ترکیب است.
شکل 9. درخت ادغام شده حاوی چندین متن در یک لیست در داخل گره Row است. درخت ادغام نشده شامل گره های جداگانه برای هر متن قابل ترکیب است.

درخت معناشناسی را تطبیق دهید

همانطور که قبلا ذکر شد، می توانید برخی از ویژگی های معنایی را لغو یا پاک کنید یا رفتار ادغام درخت را تغییر دهید. این امر به ویژه زمانی مرتبط است که شما در حال ایجاد اجزای سفارشی خود هستید. بدون تنظیم ویژگی‌ها و رفتار ادغام درست، ممکن است برنامه شما در دسترس نباشد و آزمایش‌ها متفاوت از آنچه انتظار دارید رفتار کنند. برای مطالعه بیشتر در مورد برخی موارد استفاده متداول که باید درخت Semantics را تطبیق دهید، اسناد دسترسی را بخوانید. اگر می‌خواهید درباره آزمایش بیشتر بدانید، راهنمای تست را بررسی کنید.

منابع اضافی

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}