सिमैंटिक

किसी कॉम्पोज़ेबल में मौजूद मुख्य जानकारी के अलावा, यूज़र इंटरफ़ेस (यूआई) एलिमेंट के बारे में ज़्यादा जानकारी भी मददगार हो सकती है. जैसे, Text कॉम्पोज़ेबल की टेक्स्ट स्ट्रिंग.

Compose में किसी कॉम्पोनेंट के मतलब और भूमिका के बारे में जानकारी को सिमेंटिक्स कहा जाता है. यह सुलभता, ऑटोमैटिक भरने की सुविधा, और टेस्टिंग जैसी सेवाओं को कंपोज़ेबल के बारे में ज़्यादा जानकारी देने का एक तरीका है. उदाहरण के लिए, कैमरे का आइकॉन सिर्फ़ एक इमेज हो सकता है, लेकिन इसका मतलब "फ़ोटो लें" हो सकता है.

सही सेमेटिक्स को सही Compose एपीआई के साथ जोड़कर, ऐक्सेसibililty सेवाओं को अपने कॉम्पोनेंट के बारे में ज़्यादा से ज़्यादा जानकारी दी जाती है. इसके बाद, यह सेवाएं यह तय करती हैं कि उपयोगकर्ता को कॉम्पोनेंट को कैसे दिखाया जाए.

Material और Compose यूज़र इंटरफ़ेस (यूआई) और फ़ाउंडेशन एपीआई में, पहले से मौजूद ऐसे सेमेटिक्स होते हैं जो उनकी खास भूमिका और फ़ंक्शन के मुताबिक होते हैं. हालांकि, अपनी ज़रूरतों के मुताबिक, मौजूदा एपीआई के लिए इन सेमेटिक्स में बदलाव किया जा सकता है या कस्टम कॉम्पोनेंट के लिए नए सेमेटिक्स सेट किए जा सकते हैं.

सिमेंटिक प्रॉपर्टी

सेमैटिक प्रॉपर्टी, उससे जुड़े कॉम्पोज़ेबल का मतलब बताती हैं. उदाहरण के लिए, Text कॉम्पोज़ेबल में एक सीमेंटिक प्रॉपर्टी text होती है, क्योंकि वह कॉम्पोज़ेबल का मतलब होती है. Icon में एक contentDescription प्रॉपर्टी होती है (अगर डेवलपर ने सेट की हो), जो टेक्स्ट में बताती है कि आइकॉन का क्या मतलब है.

देखें कि सेमेटिक्स प्रॉपर्टी, किसी कॉम्पोज़ेबल का मतलब कैसे बताती हैं. Switch का इस्तेमाल करें. उपयोगकर्ता को यह ऐसा दिखता है:

पहली इमेज. Switch की "चालू" और "बंद" स्थिति.

इस एलिमेंट के मतलब के बारे में बताने के लिए, यह कहा जा सकता है: "यह एक स्विच है, जो 'चालू' स्थिति में टॉगल किया जा सकता है. इस पर क्लिक करके, उससे इंटरैक्ट किया जा सकता है."

सेमेटिक्स प्रॉपर्टी का इस्तेमाल इसी काम के लिए किया जाता है. इस 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 जैसी सुलभता सेवा उस कॉम्पोनेंट को हाइलाइट करती है और बताती है कि उसके मेन्यू में और भी कार्रवाइयां उपलब्ध हैं. साथ ही, वहां स्वाइप करके हटाने की कार्रवाई को दिखाती है:

TalkBack ऐक्शन मेन्यू की इमेज
चौथी इमेज. TalkBack के ऐक्शन मेन्यू को विज़ुअलाइज़ किया गया है.

कस्टम ऐक्शन के लिए इस्तेमाल का एक और उदाहरण, उन आइटम की लंबी सूचियां हैं जिनमें ज़्यादा ऐक्शन उपलब्ध हैं. ऐसा इसलिए, क्योंकि उपयोगकर्ताओं के लिए हर आइटम के लिए हर ऐक्शन को अलग-अलग दोहराना मुश्किल हो सकता है:

=स्क्रीन पर Switch Access के नेविगेशन को विज़ुअलाइज़ करना
पांचवीं इमेज. स्क्रीन पर, स्विच ऐक्सेस के नेविगेशन को विज़ुअलाइज़ किया गया है.

नेविगेशन अनुभव को बेहतर बनाने के लिए, कंटेनर पर कस्टम ऐक्शन का इस्तेमाल किया जा सकता है. इससे, ऐक्शन को अलग-अलग ट्रैवर्सल से हटाकर, अलग ऐक्शन मेन्यू में ले जाया जा सकता है. यह सुविधा, इंटरैक्शन पर आधारित सहायक टेक्नोलॉजी के लिए खास तौर पर मददगार होती है. जैसे, स्विच ऐक्सेस या वॉइस ऐक्सेस:

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 मॉडिफ़ायर की मदद से, चाइल्ड एलिमेंट के मूल सेमेटिक्स को मैन्युअल तरीके से हटाना न भूलें. ऐसा इसलिए, क्योंकि उन्हें कस्टम ऐक्शन में ले जाया जा रहा है.

उदाहरण के लिए, स्विच ऐक्सेस की सुविधा का इस्तेमाल करने पर, कंटेनर चुनने पर उसका मेन्यू खुलता है. इसमें नेस्ट की गई उपलब्ध कार्रवाइयों की सूची दिखती है:

लेख की सूची के आइटम को हाइलाइट करने के लिए, बटन से ऐक्सेस करने की सुविधा का इस्तेमाल करना
छठी इमेज. Switch Access की मदद से, लेख की सूची में मौजूद आइटम को हाइलाइट करें.
ऐक्सेस का तरीका बदलने की सुविधा से जुड़े ऐक्शन मेन्यू का विज़ुअलाइज़ेशन.
सातवीं इमेज. स्विच ऐक्सेस के ऐक्शन मेन्यू को विज़ुअलाइज़ किया गया है.

सिमैंटिक ट्री

कॉम्पोज़िशन से आपके ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) के बारे में पता चलता है. इसे चलाने के लिए, कॉम्पोज़ेबल का इस्तेमाल किया जाता है. कॉम्पोज़िशन एक ट्री-स्ट्रक्चर होता है. इसमें ऐसे कॉम्पोज़ेबल होते हैं जिनसे आपके यूज़र इंटरफ़ेस (यूआई) के बारे में जानकारी मिलती है.

कॉम्पोज़िशन के बगल में, एक पैरलल ट्री होता है, जिसे सिमेंटिक्स ट्री कहा जाता है. यह ट्री आपके यूज़र इंटरफ़ेस (यूआई) के बारे में एक अलग तरीके से बताता है. इसे सुलभता सेवाओं और टेस्टिंग फ़्रेमवर्क के लिए समझा जा सकता है. सुलभता सेवाएं, किसी खास ज़रूरत वाले उपयोगकर्ताओं को ऐप्लिकेशन के बारे में बताने के लिए, ट्री का इस्तेमाल करती हैं. टेस्टिंग फ़्रेमवर्क, आपके ऐप्लिकेशन के साथ इंटरैक्ट करने और उसके बारे में दावे करने के लिए, ट्री का इस्तेमाल करता है. सेमेटिक्स ट्री में, आपके कॉम्पोनेंट को ड्रॉ करने के तरीके की जानकारी नहीं होती. हालांकि, इसमें आपके कॉम्पोनेंट के सेमेटिक मतलब के बारे में जानकारी होती है.

यूज़र इंटरफ़ेस (यूआई) की सामान्य हैरारकी और उसका सिमेंटिक्स ट्री
आठवीं इमेज. यूज़र इंटरफ़ेस (यूआई) की सामान्य हैरारकी और उसका सिमेंटिक्स ट्री.

अगर आपके ऐप्लिकेशन में Compose फ़ाउंडेशन और मटीरियल लाइब्रेरी के कॉम्पोज़ेबल और मॉडिफ़ायर शामिल हैं, तो सेमेटिक्स ट्री आपके लिए अपने-आप भर जाता है और जनरेट हो जाता है. हालांकि, लो-लेवल के कस्टम कंपोज़ेबल जोड़ते समय, आपको मैन्युअल तरीके से उनके सेमेटिक्स देने होंगे. ऐसा भी हो सकता है कि आपका ट्री, स्क्रीन पर मौजूद एलिमेंट का मतलब सही तरीके से या पूरी तरह से न दिखाए. ऐसे में, ट्री में बदलाव किया जा सकता है.

उदाहरण के लिए, इस कस्टम कैलेंडर कॉम्पोज़ेबल को देखें:

दिन के चुनिंदा एलिमेंट के साथ कस्टम कैलेंडर कॉम्पोज़ करना
नौवीं इमेज. दिन के चुने जा सकने वाले एलिमेंट के साथ कस्टम कैलेंडर कॉम्पोज़ किया जा सकता है.

इस उदाहरण में, पूरे कैलेंडर को एक लो-लेवल के कमपोज़ेबल के तौर पर लागू किया गया है. इसके लिए, Layout कमपोज़ेबल का इस्तेमाल किया गया है और सीधे Canvas में ड्रॉ किया गया है. अगर आपने कुछ और नहीं किया, तो सुलभता सेवाओं को कॉम्पोज़ेबल के कॉन्टेंट और कैलेंडर में उपयोगकर्ता के चुने गए आइटम के बारे में ज़रूरत के मुताबिक जानकारी नहीं मिलेगी. उदाहरण के लिए, अगर कोई उपयोगकर्ता 17 वाले दिन पर क्लिक करता है, तो ऐक्सेसibiliटी फ़्रेमवर्क को सिर्फ़ पूरे कैलेंडर कंट्रोल के लिए जानकारी मिलती है. इस मामले में, TalkBack की सुलभता सेवा "Calendar" या थोड़ा बेहतर तरीके से "अप्रैल Calendar" के बारे में बताएगी. इससे उपयोगकर्ता को यह पता नहीं चल पाएगा कि किस दिन को चुना गया है. इस कॉम्पोज़ेबल को ज़्यादा ऐक्सेस करने लायक बनाने के लिए, आपको मैन्युअल तरीके से सेमैटिक जानकारी जोड़नी होगी.

मर्ज किया गया और अनमर्ज किया गया ट्री

जैसा कि पहले बताया गया है, यूज़र इंटरफ़ेस (यूआई) ट्री में मौजूद हर कॉम्पोज़ेबल में, सेमेटिक्स प्रॉपर्टी सेट नहीं की जा सकतीं या एक से ज़्यादा सेट की जा सकती हैं. जब किसी कॉम्पोज़ेबल में कोई सिमेंटिक प्रॉपर्टी सेट नहीं होती है, तो उसे सिमेंटिक्स ट्री के हिस्से के तौर पर शामिल नहीं किया जाता. इस तरह, सेमेटिक्स ट्री में सिर्फ़ वे नोड शामिल होते हैं जिनमें सेमेटिक का मतलब होता है. हालांकि, कभी-कभी स्क्रीन पर दिखाए गए कॉन्टेंट का सही मतलब बताने के लिए, नोड के कुछ सब-ट्री को मर्ज करना और उन्हें एक के तौर पर इस्तेमाल करना भी मददगार होता है. इस तरह, हर वंश वाले नोड को अलग से मैनेज करने के बजाय, नोड के पूरे सेट को एक साथ मैनेज किया जा सकता है. आम तौर पर, सुलभता सेवाओं का इस्तेमाल करते समय, इस ट्री में मौजूद हर नोड, फ़ोकस किए जा सकने वाले एलिमेंट को दिखाता है.

Button, ऐसे कॉम्पोज़ेबल का एक उदाहरण है. बटन को एक एलिमेंट के तौर पर देखा जा सकता है, भले ही उसमें कई चाइल्ड नोड हों:

Button(onClick = { /*TODO*/ }) {
    Icon(
        imageVector = Icons.Filled.Favorite,
        contentDescription = null
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
}

सेमेंटेटिक्स ट्री में, बटन के वंशजों की प्रॉपर्टी को मर्ज कर दिया जाता है. साथ ही, बटन को ट्री में एक लीफ़ नोड के तौर पर दिखाया जाता है:

मर्ज किए गए सिंगल लीफ़ सिमेंटिक्स का रेप्रज़ेंटेशन
10वीं इमेज. मर्ज किए गए सिंगल लीफ़ सिमेंटिक्स का रेप्रज़ेंटेशन.

कंपोज़ेबल और मॉडिफ़ायर, Modifier.semantics (mergeDescendants = true) {} को कॉल करके यह बता सकते हैं कि उन्हें अपने वंशजों की सेमेटिक्स प्रॉपर्टी मर्ज करनी हैं. इस प्रॉपर्टी को true पर सेट करने का मतलब है कि सिमेंटिक प्रॉपर्टी को मर्ज किया जाना चाहिए. Button उदाहरण में, Button composable, इंटरनल तौर पर clickable मॉडिफ़ायर का इस्तेमाल करता है. इसमें यह semantics मॉडिफ़ायर शामिल होता है. इसलिए, बटन के डिसेंटेंट नोड मर्ज कर दिए जाते हैं. अपने कॉम्पोनेंट में मर्ज करने के व्यवहार को कब बदलना चाहिए, इस बारे में ज़्यादा जानने के लिए सुलभता से जुड़ा दस्तावेज़ पढ़ें.

Foundation और Material Compose लाइब्रेरी में मौजूद कई मॉडिफ़ायर और कंपोज़ेबल में यह प्रॉपर्टी सेट होती है. उदाहरण के लिए, clickable और toggleable मोडिफ़ायर, अपने वंशजों को अपने-आप मर्ज कर देंगे. साथ ही, ListItem composable अपने डिसेंडेंट को मर्ज कर देगा.

ट्री व्यू की जांच करना

असल में, सेमेटिक्स ट्री दो अलग-अलग ट्री होते हैं. मर्ज किया गया सेमेटिक्स ट्री होता है. यह mergeDescendants को true पर सेट करने पर, वंश के नोड को मर्ज करता है. मर्ज नहीं किया गया सेमेटिक्स ट्री भी होता है. इसमें मर्ज करने की प्रोसेस लागू नहीं होती, लेकिन हर नोड को बरकरार रखा जाता है. सुलभता सेवाएं, मर्ज नहीं किए गए ट्री का इस्तेमाल करती हैं और mergeDescendants प्रॉपर्टी को ध्यान में रखते हुए, अपने मर्ज करने के एल्गोरिदम लागू करती हैं. टेस्टिंग फ़्रेमवर्क, डिफ़ॉल्ट रूप से मर्ज किए गए ट्री का इस्तेमाल करता है.

printToLog() तरीके से, दोनों ट्री की जांच की जा सकती है. डिफ़ॉल्ट रूप से और पहले दिए गए उदाहरणों की तरह, मर्ज किया गया ट्री लॉग किया जाता है. इसके बजाय, मर्ज नहीं किए गए ट्री को प्रिंट करने के लिए, onRoot() मैचर के useUnmergedTree पैरामीटर को true पर सेट करें:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")

लेआउट इंस्पेक्टर की मदद से, मर्ज किए गए और मर्ज नहीं किए गए सेमेटिक्स ट्री, दोनों को एक साथ देखा जा सकता है. इसके लिए, व्यू फ़िल्टर में अपनी पसंद का विकल्प चुनें:

लेआउट इंस्पेक्टर व्यू के विकल्प, जो मर्ज किए गए और अनमर्ज किए गए सिमैंटिक्स ट्री, दोनों को दिखाने की अनुमति देते हैं
11वां डायग्राम. लेआउट इंस्पेक्टर व्यू के विकल्प, जिनकी मदद से मर्ज किए गए और मर्ज नहीं किए गए सिमेंटिक्स ट्री, दोनों को दिखाया जा सकता है.

आपके ट्री के हर नोड के लिए, लेआउट इंस्पेक्टर, प्रॉपर्टी पैनल में मर्ज किए गए सेमेटिक्स और उस नोड पर सेट किए गए सेमेटिक्स, दोनों दिखाता है:

सेमेटिक प्रॉपर्टी मर्ज और सेट की गई
12वीं इमेज. सेमेटिक प्रॉपर्टी मर्ज और सेट की गई हैं.

डिफ़ॉल्ट रूप से, टेस्टिंग फ़्रेमवर्क में मौजूद मैचर, मर्ज किए गए सेमेटिक्स ट्री का इस्तेमाल करते हैं. इसलिए, Button के साथ इंटरैक्ट करने के लिए, उसमें दिखाए गए टेक्स्ट से मैच करें:

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

इस व्यवहार को बदलने के लिए, मैच करने वाले टूल के useUnmergedTree पैरामीटर को true पर सेट करें. ठीक वैसे ही जैसे onRoot मैच करने वाले टूल के लिए किया जाता है.

ट्री को अडजस्ट करना

जैसा कि पहले बताया गया है, कुछ सेमेटिक प्रॉपर्टी को बदला या मिटाया जा सकता है. इसके अलावा, ट्री के मर्ज करने के तरीके को भी बदला जा सकता है. यह खास तौर पर तब ज़रूरी होता है, जब आप अपने कस्टम कॉम्पोनेंट बना रहे हों. सही प्रॉपर्टी और मर्ज करने के तरीके को सेट किए बिना, हो सकता है कि आपका ऐप्लिकेशन ऐक्सेस न किया जा सके. साथ ही, हो सकता है कि टेस्ट आपकी उम्मीद के मुताबिक काम न करें. अगर आपको टेस्टिंग के बारे में ज़्यादा जानना है, तो टेस्टिंग के लिए बनी गाइड देखें.