मर्ज करना और खाता मिटाना

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

सिमेंटिक्स मर्ज करना

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

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

उदाहरण के लिए, ऐसे कॉम्पोज़ेबल के बारे में सोचें जो उपयोगकर्ता का अवतार, उसका नाम, और कुछ और जानकारी दिखाता है:

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

इन एलिमेंट को मर्ज करने के लिए, 'लिखें' सुविधा को चालू किया जा सकता है. इसके लिए, सेमेटिक्स मॉडिफ़ायर में mergeDescendants पैरामीटर का इस्तेमाल करें. इस तरह, सुलभता सेवाएं कॉम्पोनेंट को एक इकाई के तौर पर इस्तेमाल करती हैं. साथ ही, वंश के सभी सेमेटिक प्रॉपर्टी को मर्ज कर देती हैं:

@Composable
private fun PostMetadata(metadata: Metadata) {
    // Merge elements below for accessibility purposes
    Row(modifier = Modifier.semantics(mergeDescendants = true) {}) {
        Image(
            imageVector = Icons.Filled.AccountCircle,
            contentDescription = null // decorative
        )
        Column {
            Text(metadata.author.name)
            Text("${metadata.date}${metadata.readTimeMinutes} min read")
        }
    }
}

सुलभता सेवाएं अब पूरे कंटेनर पर एक साथ फ़ोकस करती हैं और उसके कॉन्टेंट को मर्ज करती हैं:

यूज़र इंटरफ़ेस (यूआई) एलिमेंट का ग्रुप, जिसमें उपयोगकर्ता का नाम शामिल होता है. सभी एलिमेंट एक साथ चुने जाते हैं.
दूसरी इमेज. यूज़र इंटरफ़ेस (यूआई) एलिमेंट का ग्रुप, जिसमें उपयोगकर्ता का नाम शामिल होता है. सभी एलिमेंट एक साथ चुने जाते हैं.

हर सिमेंटिक प्रॉपर्टी के लिए, मर्ज करने की एक खास रणनीति तय होती है. उदाहरण के लिए, ContentDescription प्रॉपर्टी, सूची में सभी वंशज ContentDescription वैल्यू जोड़ती है. किसी सेमेनटिक प्रॉपर्टी को मर्ज करने की रणनीति देखने के लिए, SemanticsProperties.kt में mergePolicy को लागू करने की जांच करें. प्रॉपर्टी, पैरंट या चाइल्ड वैल्यू को ले सकती हैं, वैल्यू को सूची या स्ट्रिंग में मर्ज कर सकती हैं, मर्ज करने की अनुमति नहीं दे सकती हैं और इसके बजाय कोई अपवाद या मर्ज करने की कोई अन्य कस्टम रणनीति दिखा सकती हैं.

ऐसी अन्य स्थितियां भी हैं जहां आपको लगता है कि चाइल्ड सेमेंटेक्स को पैरंट सेमेंटेक्स में मर्ज किया जाना चाहिए, लेकिन ऐसा नहीं होता. नीचे दिए गए उदाहरण में, हमारे पास clickable सूची आइटम पैरंट है, जिसमें चाइल्ड एलिमेंट हैं. हम उम्मीद कर सकते हैं कि पैरंट, उन सभी को मर्ज कर देगा:

इमेज, कुछ टेक्स्ट, और बुकमार्क आइकॉन वाला सूची आइटम
तीसरी इमेज. इमेज, कुछ टेक्स्ट, और बुकमार्क आइकॉन वाला आइटम.

@Composable
private fun ArticleListItem(
    openArticle: () -> Unit,
    addToBookmarks: () -> Unit,
) {

    Row(modifier = Modifier.clickable { openArticle() }) {
        // Merges with parent clickable:
        Icon(
            painter = painterResource(R.drawable.ic_logo),
            contentDescription = "Article thumbnail"
        )
        ArticleDetails()

        // Defies the merge due to its own clickable:
        BookmarkButton(onClick = addToBookmarks)
    }
}

जब उपयोगकर्ता clickable आइटम Row को दबाता है, तो लेख खुल जाता है. लेख को बुकमार्क करने के लिए, नेस्ट किए गए टेक्स्ट में BookmarkButton मौजूद है. नेस्ट किया गया यह बटन, मर्ज नहीं किया गया के तौर पर दिखता है. वहीं, लाइन में मौजूद बच्चों के लिए बने बाकी कॉन्टेंट को मर्ज किया गया है:

मर्ज किए गए ट्री में, पंक्ति नोड के अंदर एक सूची में कई टेक्स्ट होते हैं. मर्ज नहीं किए गए ट्री में, हर टेक्स्ट कॉम्पोज़ेबल के लिए अलग-अलग नोड होते हैं.
चौथी इमेज. मर्ज किए गए ट्री में, Row नोड के अंदर एक सूची में कई टेक्स्ट होते हैं. मर्ज नहीं किए गए ट्री में, हर Text कॉम्पोज़ेबल
के लिए अलग-अलग नोड होते हैं.

डिज़ाइन के हिसाब से, कुछ कॉम्पोज़ेबल अपने-आप पैरंट के तहत मर्ज नहीं होते. जब चाइल्ड एलिमेंट भी मर्ज हो रहे हों, तो पैरंट एलिमेंट अपने चाइल्ड एलिमेंट को मर्ज नहीं कर सकता. ऐसा, mergeDescendants = true सेटिंग को साफ़ तौर पर सेट करके या बटन या क्लिक किए जा सकने वाले एलिमेंट जैसे ऐसे कॉम्पोनेंट के ज़रिए किया जा सकता है जो अपने-आप मर्ज हो जाते हैं. यह जानने से कि कुछ एपीआई मर्ज कैसे करते हैं या मर्ज करने से कैसे बचते हैं, आपको अनचाहे व्यवहारों को डीबग करने में मदद मिल सकती है.

मर्ज करने की सुविधा का इस्तेमाल तब करें, जब चाइल्ड एलिमेंट अपने पैरंट के तहत एक लॉजिकल और समझदार ग्रुप बनाएं. हालांकि, अगर नेस्ट किए गए चाइल्ड एलिमेंट को मैन्युअल तरीके से अडजस्ट करने या उनके सेमेटिक को हटाने की ज़रूरत है, तो हो सकता है कि आपकी ज़रूरतों के हिसाब से अन्य एपीआई बेहतर हों. उदाहरण के लिए, clearAndSetSemantics.

सेमेटिक्स को हटाना और सेट करना

अगर सेमेटिक जानकारी को पूरी तरह से मिटाना है या उस पर फिर से लिखना है, तो clearAndSetSemantics का इस्तेमाल करें. यह एक बेहतरीन एपीआई है.

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

ध्यान दें कि खाली लैम्ब्डा का इस्तेमाल करके सेमेटिक्स मिटाने पर, मिटाए गए सेमेटिक्स को किसी भी ऐसे उपभोक्ता को नहीं भेजा जाता जो इस जानकारी का इस्तेमाल करता है. जैसे, सुलभता, ऑटोमैटिक भरना या जांच. clearAndSetSemantics{/*semantic information*/} से कॉन्टेंट को ओवरराइट करने पर, नए सिमेंटिक्स, एलिमेंट और उसके वंशजों के सभी पुराने सिमेंटिक्स की जगह ले लेते हैं.

यहां कस्टम टॉगल कॉम्पोनेंट का उदाहरण दिया गया है. इसे आइकॉन और टेक्स्ट के साथ, इंटरैक्ट की जा सकने वाली लाइन के तौर पर दिखाया गया है:

// Developer might intend this to be a toggleable.
// Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied,
// a custom description is set, and a Role is applied.

@Composable
fun FavoriteToggle() {
    val checked = remember { mutableStateOf(true) }
    Row(
        modifier = Modifier
            .toggleable(
                value = checked.value,
                onValueChange = { checked.value = it }
            )
            .clearAndSetSemantics {
                stateDescription = if (checked.value) "Favorited" else "Not favorited"
                toggleableState = ToggleableState(checked.value)
                role = Role.Switch
            },
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = null // not needed here

        )
        Text("Favorite?")
    }
}

आइकॉन और टेक्स्ट में कुछ सेमेटिक जानकारी होती है, लेकिन इनसे यह पता नहीं चलता कि इस कॉम्पोनेंट को टॉगल किया जा सकता है. मर्ज करना काफ़ी नहीं है, क्योंकि आपको कॉम्पोनेंट के बारे में ज़्यादा जानकारी देनी होगी.

ऊपर दिया गया स्निपेट, कस्टम टॉगल कॉम्पोनेंट बनाता है. इसलिए, आपको टॉगल करने की सुविधा के साथ-साथ stateDescription, toggleableState, और role सेमेटिक्स जोड़ने होंगे. इस तरह, कॉम्पोनेंट का स्टेटस और उससे जुड़ी कार्रवाई उपलब्ध होती है. उदाहरण के लिए, TalkBack "चालू करने के लिए दो बार टैप करें" के बजाय, "टॉगल करने के लिए दो बार टैप करें" के बारे में बताता है.

ओरिजनल सेमेटिक्स को हटाकर और नए और ज़्यादा जानकारी वाले सेट करने पर, अब ऐक्सेसबिलिटी सेवाएं यह देख सकती हैं कि यह टॉगल किया जा सकने वाला कॉम्पोनेंट है, जिसकी स्थिति बदली जा सकती है.

clearAndSetSemantics का इस्तेमाल करते समय, इन बातों का ध्यान रखें:

  • इस एपीआई के सेट होने पर, सेवाओं को कोई जानकारी नहीं मिलती. इसलिए, इसका इस्तेमाल कम से कम करें.
    • एआई एजेंट और मिलती-जुलती सेवाएं, स्क्रीन को समझने के लिए सेमेटिक्स की जानकारी का इस्तेमाल कर सकती हैं. इसलिए, इस जानकारी को सिर्फ़ ज़रूरत पड़ने पर मिटाया जाना चाहिए.
  • कस्टम सेमेटिक्स, एपीआई लैम्ब्डा में सेट किए जा सकते हैं.
  • मॉडिफ़ायर का क्रम मायने रखता है―यह एपीआई, मर्ज करने की अन्य रणनीतियों के बावजूद, लागू होने के बाद के सभी सेमेटिक को हटा देता है.

सेमेटिक्स छिपाना

कुछ मामलों में, एलिमेंट को सुलभता सेवाओं पर भेजने की ज़रूरत नहीं होती. ऐसा तब होता है, जब उनकी अतिरिक्त जानकारी सुलभता के लिए ज़रूरी न हो या वह सिर्फ़ विज़ुअल के तौर पर सजावटी हो और इंटरैक्टिव न हो. ऐसे मामलों में, hideFromAccessibility एपीआई की मदद से एलिमेंट छिपाए जा सकते हैं.

यहां दिए गए उदाहरणों में ऐसे कॉम्पोनेंट हैं जिन्हें छिपाने की ज़रूरत पड़ सकती है: एक कॉम्पोनेंट पर मौजूद ऐसा वॉटरमार्क जो ज़रूरी नहीं है और जानकारी को अलग-अलग दिखाने के लिए इस्तेमाल किया गया वर्ण.

@Composable
fun WatermarkExample(
    watermarkText: String,
    content: @Composable () -> Unit,
) {
    Box {
        WatermarkedContent()
        // Mark the watermark as hidden to accessibility services.
        WatermarkText(
            text = watermarkText,
            color = Color.Gray.copy(alpha = 0.5f),
            modifier = Modifier
                .align(Alignment.BottomEnd)
                .semantics { hideFromAccessibility() }
        )
    }
}

@Composable
fun DecorativeExample() {
    Text(
        modifier =
        Modifier.semantics {
            hideFromAccessibility()
        },
        text = "A dot character that is used to decoratively separate information, like •"
    )
}

यहां hideFromAccessibility का इस्तेमाल करने से यह पक्का होता है कि वॉटरमार्क और डेकोरेशन, सुलभता सेवाओं से छिपे रहें. हालांकि, टेस्टिंग जैसे अन्य इस्तेमाल के उदाहरणों के लिए, उनके सेमेंटेक्स को बनाए रखा जाता है.

इस्तेमाल के उदाहरणों का ब्रेकडाउन

यहां इस्तेमाल के उदाहरणों की खास जानकारी दी गई है. इससे, आपको यह समझने में मदद मिलेगी कि पिछले एपीआई के बीच साफ़ तौर पर अंतर कैसे किया जा सकता है:

  • जब कॉन्टेंट का इस्तेमाल, सुलभता सेवाओं के लिए नहीं किया जाना है, तो:
    • hideFromAccessibility का इस्तेमाल तब करें, जब कॉन्टेंट शायद सजावटी या गै़र-ज़रूरी हो, लेकिन फिर भी उसकी जांच की जानी चाहिए.
    • जब सभी सेवाओं के लिए पैरंट और चाइल्ड सेमेंटेक्स को हटाना हो, तो खाली लैम्ब्डा के साथ clearAndSetSemantics{} का इस्तेमाल करें.
    • जब किसी कॉम्पोनेंट के सेमेटिक्स को मैन्युअल तरीके से सेट करना हो, तो लैम्ब्डा के अंदर कॉन्टेंट के साथ clearAndSetSemantics{/*content*/} का इस्तेमाल करें.
  • जब कॉन्टेंट को एक इकाई के तौर पर माना जाना चाहिए और उसके सभी बच्चों की जानकारी पूरी होनी चाहिए, तब:
    • मर्ज किए गए सिमेंटिक वंशजों का इस्तेमाल करें.
एपीआई के इस्तेमाल के अलग-अलग उदाहरणों वाली टेबल.
पांचवीं इमेज. एपीआई के इस्तेमाल के अलग-अलग उदाहरणों वाली टेबल.