ट्रैवर्सल ऑर्डर में बदलाव करना

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

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

स्क्रीन रीडर के ट्रैवर्सल ऑर्डर को कंट्रोल करने के लिए, अपने ऐप्लिकेशन में isTraversalGroup और traversalIndex का इस्तेमाल करें.

ट्रैवर्सल के लिए एलिमेंट को ग्रुप करना

isTraversalGroup एक बूलियन प्रॉपर्टी है. इससे यह तय होता है कि सिमैंटिक नोड, ट्रैवर्सल ग्रुप है या नहीं. इस तरह के नोड का काम, चाइल्ड नोड को व्यवस्थित करने के लिए बाउंड्री या बॉर्डर के तौर पर काम करना है.

किसी नोड पर isTraversalGroup = true सेट करने का मतलब है कि अन्य एलिमेंट पर जाने से पहले, उस नोड के सभी चाइल्ड एलिमेंट पर विज़िट किया जाता है. isTraversalGroup को उन नोड पर सेट किया जा सकता है जिन पर स्क्रीन रीडर फ़ोकस नहीं कर सकता. जैसे, कॉलम, लाइन या बॉक्स.

यहां दिए गए उदाहरण में, isTraversalGroup का इस्तेमाल किया गया है. यह चार टेक्स्ट एलिमेंट दिखाता है. बाईं ओर मौजूद दो एलिमेंट, एक CardBox एलिमेंट से जुड़े हैं. वहीं, दाईं ओर मौजूद दो एलिमेंट, दूसरे CardBox एलिमेंट से जुड़े हैं:

// CardBox() function takes in top and bottom sample text.
@Composable
fun CardBox(
    topSampleText: String,
    bottomSampleText: String,
    modifier: Modifier = Modifier
) {
    Box(modifier) {
        Column {
            Text(topSampleText)
            Text(bottomSampleText)
        }
    }
}

@Composable
fun TraversalGroupDemo() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is "
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
            topSampleText1,
            bottomSampleText1
        )
        CardBox(
            topSampleText2,
            bottomSampleText2
        )
    }
}

कोड से, इस तरह का आउटपुट मिलता है:

टेक्स्ट के दो कॉलम वाला लेआउट. इसमें बाईं ओर मौजूद कॉलम में 'यह वाक्य बाईं ओर मौजूद कॉलम में है' और दाईं ओर मौजूद कॉलम में 'यह वाक्य दाईं ओर मौजूद कॉलम में है' लिखा है.
पहली इमेज. दो वाक्यों वाला लेआउट (एक वाक्य बाएं कॉलम में और एक वाक्य दाएं कॉलम में).

कोई सिमैंटिक सेट न होने की वजह से, स्क्रीन रीडर का डिफ़ॉल्ट व्यवहार, एलिमेंट को बाईं से दाईं ओर और ऊपर से नीचे की ओर ट्रैवर्स करना होता है. इस डिफ़ॉल्ट सेटिंग की वजह से, TalkBack वाक्य के हिस्सों को गलत क्रम में पढ़ता है:

"This sentence is in" → "This sentence is" → "the left column." "दाईं ओर" पर क्लिक करें.

फ़्रैगमेंट को सही क्रम में लगाने के लिए, ओरिजनल स्निपेट में बदलाव करके isTraversalGroup को true पर सेट करें:

@Composable
fun TraversalGroupDemo2() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is"
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
//      1,
            topSampleText1,
            bottomSampleText1,
            Modifier.semantics { isTraversalGroup = true }
        )
        CardBox(
//      2,
            topSampleText2,
            bottomSampleText2,
            Modifier.semantics { isTraversalGroup = true }
        )
    }
}

isTraversalGroup को हर CardBox पर सेट किया जाता है. इसलिए, एलिमेंट को क्रम से लगाते समय CardBox की सीमाएं लागू होती हैं. इस मामले में, बाईं ओर मौजूद CardBox को पहले पढ़ा जाता है. इसके बाद, दाईं ओर मौजूद CardBox को पढ़ा जाता है.

अब TalkBack, वाक्य के हिस्सों को सही क्रम में पढ़ता है:

"This sentence is in" → "the left column." → "यह वाक्य" → "सही है."

ट्रैवर्सल ऑर्डर को पसंद के मुताबिक बनाना

traversalIndex एक फ़्लोट प्रॉपर्टी है. इसकी मदद से, TalkBack के ट्रैवर्सल ऑर्डर को पसंद के मुताबिक बनाया जा सकता है. अगर एलिमेंट को एक साथ ग्रुप करने से TalkBack सही तरीके से काम नहीं करता है, तो स्क्रीन रीडर के क्रम को और पसंद के मुताबिक बनाने के लिए, isTraversalGroup के साथ traversalIndex का इस्तेमाल करें.

traversalIndex प्रॉपर्टी की ये विशेषताएं हैं:

  • कम traversalIndex वैल्यू वाले एलिमेंट को पहले प्राथमिकता दी जाती है.
  • यह पॉज़िटिव या नेगेटिव हो सकता है.
  • डिफ़ॉल्ट वैल्यू 0f है.
  • ट्रैवर्सल इंडेक्स, ट्रैवर्सल के व्यवहार पर असर डाल सके, इसके लिए इसे ऐसे कॉम्पोनेंट पर सेट करना होगा जिसे सुलभता सेवाएं चुन सकें और जिस पर फ़ोकस कर सकें. जैसे, स्क्रीन पर मौजूद एलिमेंट, जैसे कि टेक्स्ट या बटन.
    • उदाहरण के लिए, सिर्फ़ traversalIndex को Column पर सेट करने से कोई असर नहीं पड़ेगा. ऐसा तब तक होगा, जब तक कॉलम में isTraversalGroup भी सेट न हो.

यहां दिए गए उदाहरण में, traversalIndex और isTraversalGroup को एक साथ इस्तेमाल करने का तरीका बताया गया है.

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

घड़ी का फ़ेस, जिसके ऊपर समय चुनने वाला टूल है.
दूसरी इमेज. वॉच फ़ेस की इमेज.

नीचे दिए गए आसान स्निपेट में, एक CircularLayout है जिसमें 12 नंबर बनाए गए हैं. ये नंबर 12 से शुरू होते हैं और सर्कल के चारों ओर घड़ी की सुई की दिशा में घूमते हैं:

@Composable
fun ClockFaceDemo() {
    CircularLayout {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier) {
        Text((if (value == 0) 12 else value).toString())
    }
}

वॉच फ़ेस को बाएं से दाएं और ऊपर से नीचे के डिफ़ॉल्ट क्रम में नहीं पढ़ा जाता. इसलिए, TalkBack नंबरों को क्रम से नहीं पढ़ता. इसे ठीक करने के लिए, काउंटर की वैल्यू को बढ़ाने वाले तरीके का इस्तेमाल करें. इसके बारे में इस स्निपेट में बताया गया है:

@Composable
fun ClockFaceDemo() {
    CircularLayout(Modifier.semantics { isTraversalGroup = true }) {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) {
        Text((if (value == 0) 12 else value).toString())
    }
}

ट्रैवर्सल ऑर्डर को सही तरीके से सेट करने के लिए, पहले CircularLayout को ट्रैवर्सल ग्रुप बनाएं और isTraversalGroup = true को सेट करें. इसके बाद, जैसे ही हर घड़ी का टेक्स्ट लेआउट पर ड्रॉ होता है, उसके हिसाब से traversalIndex को काउंटर वैल्यू पर सेट करें.

काउंटर की वैल्यू लगातार बढ़ती रहती है. इसलिए, स्क्रीन पर नंबर जुड़ने के साथ-साथ, हर क्लॉक वैल्यू का traversalIndex बढ़ता जाता है. क्लॉक वैल्यू 0 का traversalIndex 0 होता है और क्लॉक वैल्यू 1 का traversalIndex 1 होता है. इस तरह, TalkBack के लिए टेक्स्ट पढ़ने का क्रम सेट हो जाता है. अब CircularLayout में मौजूद नंबर, सही क्रम में पढ़े जाते हैं.

सेट किए गए traversalIndexes, एक ही ग्रुप में मौजूद अन्य इंडेक्स से जुड़े होते हैं. इसलिए, स्क्रीन के बाकी क्रम को सुरक्षित रखा गया है. दूसरे शब्दों में, ऊपर दिए गए कोड स्निपेट में दिखाए गए सिमैंटिक बदलाव, सिर्फ़ उस वॉच फ़ेस के क्रम में बदलाव करते हैं जिसमें isTraversalGroup = true सेट है.

ध्यान दें कि CircularLayout's सिमैंटिक को isTraversalGroup = true पर सेट किए बिना भी, traversalIndex में किए गए बदलाव लागू होते हैं. हालांकि, CircularLayout के बिना, वॉच फ़ेस पर मौजूद 12 अंकों को सबसे आखिर में पढ़ा जाता है. ऐसा तब होता है, जब स्क्रीन पर मौजूद अन्य सभी एलिमेंट को पढ़ लिया जाता है. ऐसा इसलिए होता है, क्योंकि अन्य सभी एलिमेंट का डिफ़ॉल्ट traversalIndex, 0f होता है. साथ ही, घड़ी के टेक्स्ट एलिमेंट को अन्य सभी 0f एलिमेंट के बाद पढ़ा जाता है.

एपीआई से जुड़ी ज़रूरी बातें

ट्रैवर्सल एपीआई का इस्तेमाल करते समय, इन बातों का ध्यान रखें:

  • isTraversalGroup = true को उस पैरंट एलिमेंट पर सेट किया जाना चाहिए जिसमें ग्रुप किए गए एलिमेंट शामिल हैं.
  • traversalIndex को ऐसे चाइल्ड कॉम्पोनेंट पर सेट किया जाना चाहिए जिसमें सिमैंटिक शामिल हों और जिसे सुलभता सेवाएं चुनेंगी.
  • पक्का करें कि जिन एलिमेंट की जांच की जा रही है वे सभी एक ही zIndex लेवल पर हों. ऐसा इसलिए, क्योंकि इससे सिमैंटिक और ट्रैवर्सल ऑर्डर पर भी असर पड़ता है.
  • पक्का करें कि कोई भी सिमैंटिक, बिना वजह मर्ज न किया गया हो. ऐसा इसलिए, क्योंकि इससे यह तय हो सकता है कि कॉम्पोनेंट ट्रैवर्सल इंडेक्स किन कॉम्पोनेंट पर लागू किए जाएं.