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

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

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

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

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

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

किसी नोड पर 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 वाक्य के हिस्सों को गलत क्रम में पढ़ता है:

"यह वाक्य" → "यह वाक्य" → "बाएं कॉलम में है." → "दाईं ओर."

फ़्रैगमेंट को सही क्रम में लगाने के लिए, ओरिजनल स्निपेट में बदलाव करके 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, वाक्य के फ़्रैगमेंट को सही क्रम में पढ़कर सुनाएगा:

"यह वाक्य" → "बाएं कॉलम में है." → "यह वाक्य" → "दाईं ओर है."

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

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

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

  • traversalIndex की कम वैल्यू वाले एलिमेंट को प्राथमिकता दी जाती है.
  • यह संख्या, सकारात्मक या नकारात्मक हो सकती है.
  • डिफ़ॉल्ट वैल्यू 0f है.
  • ट्रैवर्स इंडेक्स को ट्रैवर्स करने के व्यवहार पर असर डालने के लिए, इसे ऐसे कॉम्पोनेंट पर सेट करना होगा जिसे सुलभता सेवाओं से चुना और फ़ोकस किया जा सके. जैसे, टेक्स्ट या बटन जैसे स्क्रीन पर मौजूद एलिमेंट.
    • उदाहरण के लिए, किसी Column कॉलम में सिर्फ़ traversalIndex को चालू करने का कोई असर नहीं होगा. ऐसा तब तक होगा, जब तक कॉलम में 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 के बिना, घड़ी की डायल के बारह अंकों को आखिर में पढ़ा जाता है. ऐसा तब होता है, जब स्क्रीन पर मौजूद सभी अन्य एलिमेंट को पढ़ लिया जाता है. ऐसा इसलिए होता है, क्योंकि अन्य सभी एलिमेंट का डिफ़ॉल्ट traversalIndex 0f होता है. साथ ही, घड़ी के टेक्स्ट एलिमेंट, अन्य सभी 0f एलिमेंट के बाद पढ़े जाते हैं.

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

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

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