एपीआई के डिफ़ॉल्ट तौर पर लागू होने वाले विकल्प

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

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

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

टच टारगेट का कम से कम साइज़

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

मटेरियल कॉम्पोनेंट, जैसे कि Checkbox, RadioButton, Switch, Slider, और Surface, इस कम से कम साइज़ को अंदरूनी तौर पर सेट करते हैं. हालांकि, ऐसा सिर्फ़ तब होता है, जब कॉम्पोनेंट उपयोगकर्ता की कार्रवाइयां पा सकता है. उदाहरण के लिए, जब किसी Checkbox का onCheckedChange पैरामीटर, ऐसी वैल्यू पर सेट होता है जिसमें कोई वैल्यू मौजूद है, तो चेकबॉक्स में पैडिंग शामिल होती है, ताकि उसकी चौड़ाई और ऊंचाई कम से कम 48 डीपी हो.

@Composable
private fun CheckableCheckbox() {
    Checkbox(checked = true, onCheckedChange = {})
}

डिफ़ॉल्ट पैडिंग वाला चेकबॉक्स, जिसकी चौड़ाई और ऊंचाई 48 डीपी है.
पहली इमेज. डिफ़ॉल्ट पैडिंग वाला चेकबॉक्स.

onCheckedChange पैरामीटर को null पर सेट करने पर, पैडिंग शामिल नहीं की जाती, क्योंकि कॉम्पोनेंट के साथ सीधे तौर पर इंटरैक्ट नहीं किया जा सकता.

@Composable
private fun NonClickableCheckbox() {
    Checkbox(checked = true, onCheckedChange = null)
}

ऐसा चेकबॉक्स जिसमें कोई पैडिंग नहीं है.
दूसरी इमेज. पैडिंग के बिना चेकबॉक्स.

Switch, RadioButton या Checkbox जैसे सिलेक्शन कंट्रोल लागू करते समय, आम तौर पर क्लिक किए जा सकने वाले व्यवहार को पैरंट कंटेनर में ले जाया जाता है. इसके लिए, कंपोज़ेबल पर क्लिक कॉलबैक को null पर सेट किया जाता है. साथ ही, पैरंट कंपोज़ेबल में toggleable या selectable मॉडिफ़ायर जोड़ा जाता है.

@Composable
private fun CheckableRow() {
    MaterialTheme {
        var checked by remember { mutableStateOf(false) }
        Row(
            Modifier
                .toggleable(
                    value = checked,
                    role = Role.Checkbox,
                    onValueChange = { checked = !checked }
                )
                .padding(16.dp)
                .fillMaxWidth()
        ) {
            Text("Option", Modifier.weight(1f))
            Checkbox(checked = checked, onCheckedChange = null)
        }
    }
}

'विकल्प' टेक्स्ट के बगल में मौजूद चेकबॉक्स को चुना और नहीं चुना जा रहा है.
तीसरी इमेज. क्लिक किए जा सकने वाले चेकबॉक्स के साथ.

जब क्लिक किए जा सकने वाले कंपोज़ेबल का साइज़, टच टारगेट के कम से कम साइज़ से छोटा होता है, तब भी Compose, टच टारगेट का साइज़ बढ़ा देता है. यह कंपोज़ेबल की सीमाओं के बाहर, टच टारगेट के साइज़ को बड़ा करके ऐसा करता है.

यहां दिए गए उदाहरण में, क्लिक किए जा सकने वाले बहुत छोटे Box को दिखाया गया है. टच टारगेट एरिया, Box की सीमाओं से बाहर अपने-आप बढ़ जाता है. इसलिए, Box के बगल में टैप करने पर भी क्लिक इवेंट ट्रिगर होता है.

@Composable
private fun SmallBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .size(1.dp)
        )
    }
}

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

अलग-अलग कंपोज़ेबल के टच एरिया के बीच ओवरलैप होने से रोकने के लिए, कंपोज़ेबल के लिए हमेशा इतना बड़ा साइज़ इस्तेमाल करें जो कम से कम हो. उदाहरण में, इसका मतलब है कि अंदरूनी बॉक्स के लिए कम से कम साइज़ सेट करने के लिए, sizeIn मॉडिफ़ायर का इस्तेमाल करना:

@Composable
private fun LargeBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .sizeIn(minWidth = 48.dp, minHeight = 48.dp)
        )
    }
}

पिछले उदाहरण में दिए गए बहुत छोटे बॉक्स का साइज़ बढ़ाकर, बड़े टच टारगेट को बनाया गया है.
पांचवीं इमेज. बड़ा बॉक्स टच टारगेट.

ग्राफ़िक एलिमेंट

Image या Icon कंपोज़ेबल को तय करने पर, Android फ़्रेमवर्क के पास यह समझने का कोई ऑटोमैटिक तरीका नहीं होता कि ऐप्लिकेशन क्या दिखा रहा है. आपको ग्राफ़िक एलिमेंट की जानकारी टेक्स्ट के तौर पर देनी होगी.

मान लें कि यह एक ऐसी स्क्रीन है जहां उपयोगकर्ता, मौजूदा पेज को दोस्तों के साथ शेयर कर सकता है. इस स्क्रीन में, क्लिक किया जा सकने वाला शेयर आइकॉन मौजूद है:

क्लिक किए जा सकने वाले चार आइकॉन की एक स्ट्रिप. इसमें 'शेयर करें' आइकॉन को हाइलाइट किया गया है.
छठी इमेज. क्लिक किए जा सकने वाले आइकॉन की एक लाइन में, 'शेयर करें' आइकॉन चुना गया है.

सिर्फ़ आइकॉन के आधार पर, Android फ़्रेमवर्क दृष्टिबाधित व्यक्ति को इसके बारे में नहीं बता सकता. Android फ़्रेमवर्क को आइकॉन के बारे में टेक्स्ट के तौर पर अतिरिक्त जानकारी की ज़रूरत होती है.

contentDescription पैरामीटर, ग्राफ़िक एलिमेंट के बारे में बताता है. स्थानीय भाषा में स्ट्रिंग का इस्तेमाल करें, क्योंकि यह उपयोगकर्ता को दिखती है.

@Composable
private fun ShareButton(onClick: () -> Unit) {
    IconButton(onClick = onClick) {
        Icon(
            imageVector = Icons.Filled.Share,
            contentDescription = stringResource(R.string.label_share)
        )
    }
}

कुछ ग्राफ़िक एलिमेंट सिर्फ़ सजावट के लिए होते हैं. ऐसा हो सकता है कि आपको उन्हें उपयोगकर्ता को न दिखाना हो. contentDescription पैरामीटर को null पर सेट करने का मतलब है कि Android फ़्रेमवर्क को यह जानकारी दी गई है कि इस एलिमेंट से कोई कार्रवाई या स्थिति जुड़ी नहीं है.

@Composable
private fun PostImage(post: Post, modifier: Modifier = Modifier) {
    val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1)

    Image(
        painter = image,
        // Specify that this image has no semantic meaning
        contentDescription = null,
        modifier = modifier
            .size(40.dp, 40.dp)
            .clip(MaterialTheme.shapes.small)
    )
}

contentDescription का इस्तेमाल मुख्य रूप से ग्राफ़िक एलिमेंट के लिए किया जाता है. जैसे, इमेज. मटेरियल कॉम्पोनेंट, जैसे कि Button या Text, और ऐक्शन किए जा सकने वाले व्यवहार, जैसे कि clickable या toggleable, पहले से तय किए गए अन्य सिमैंटिक के साथ आते हैं. ये सिमैंटिक, उनके मूल व्यवहार के बारे में बताते हैं. इन्हें अन्य Compose API के ज़रिए बदला जा सकता है.

सहभागी तत्‍व

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

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

ऐसे बटन जिनमें बच्चों के सिमैंटिक को मर्ज नहीं किया गया है और मर्ज किया गया है.
सातवीं इमेज. ऐसे बटन जिनमें चाइल्ड एलिमेंट के सिमैंटिक को मर्ज नहीं किया गया है और ऐसे बटन जिनमें चाइल्ड एलिमेंट के सिमैंटिक को मर्ज किया गया है.

इसी तरह, clickable मॉडिफ़ायर का इस्तेमाल करने से, कंपोज़ेबल अपने डिसेंडेंट के सिमैंटिक को एक ही इकाई में मर्ज कर देता है. इस इकाई को सुलभता सेवाओं को भेजा जाता है. साथ ही, इससे जुड़ी कार्रवाई की जानकारी भी भेजी जाती है:

Row(
    // Uses `mergeDescendants = true` under the hood
    modifier = Modifier.clickable { openArticle() }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open",
    )
    Text("Accessibility in Compose")
}

क्लिक किए जा सकने वाले पैरंट एलिमेंट पर कोई खास onClickLabel भी सेट किया जा सकता है, ताकि सुलभता सेवाओं को अतिरिक्त जानकारी दी जा सके. साथ ही, कार्रवाई को बेहतर तरीके से दिखाया जा सके:

Row(
    modifier = Modifier
        .clickable(onClickLabel = "Open this article") {
            openArticle()
        }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open"
    )
    Text("Accessibility in Compose")
}

TalkBack का उदाहरण लेते हुए, यह clickable मॉडिफ़ायर और इसका क्लिक लेबल, TalkBack को "इस लेख को खोलने के लिए दो बार टैप करें" के बारे में जानकारी देने की सुविधा देगा. इसके बजाय, "चालू करने के लिए दो बार टैप करें" के बारे में सामान्य डिफ़ॉल्ट फ़ीडबैक देगा.

कार्रवाई के टाइप के हिसाब से, यह सुझाव बदलता रहता है. लंबे समय तक क्लिक करने पर, TalkBack "डबल टैप करके रखें" के बारे में एक सुराग देगा. इसके बाद, एक लेबल दिखेगा:

Row(
    modifier = Modifier
        .combinedClickable(
            onLongClickLabel = "Bookmark this article",
            onLongClick = { addToBookmarks() },
            onClickLabel = "Open this article",
            onClick = { openArticle() },
        )
) {}

कुछ मामलों में, हो सकता है कि आपके पास clickable मॉडिफ़ायर का सीधा ऐक्सेस न हो. उदाहरण के लिए, जब इसे किसी लोअर नेस्टेड लेयर में सेट किया गया हो. हालांकि, आपको अब भी डिफ़ॉल्ट रूप से सेट किए गए सूचना लेबल को बदलना हो. इसके लिए, semantics मॉडिफ़ायर का इस्तेमाल करके, सूचना में बदलाव करने से clickable को अलग करें. साथ ही, कार्रवाई के बारे में जानकारी में बदलाव करने के लिए, वहां क्लिक लेबल सेट करें:

@Composable
private fun ArticleList(openArticle: () -> Unit) {
    NestedArticleListItem(
        // Clickable is set separately, in a nested layer:
        onClickAction = openArticle,
        // Semantics are set here:
        modifier = Modifier.semantics {
            onClick(
                label = "Open this article",
                action = {
                    // Not needed here: openArticle()
                    true
                }
            )
        }
    )
}

आपको क्लिक ऐक्शन को दो बार पास करने की ज़रूरत नहीं है. Compose के मौजूदा एपीआई, जैसे कि clickable या Button, आपके लिए यह काम करते हैं. मर्ज करने का लॉजिक यह पुष्टि करता है कि सबसे बाहरी मॉडिफ़ायर लेबल और कार्रवाई, मौजूद जानकारी के लिए की गई है. पिछले उदाहरण में, NestedArticleListItem, openArticle() क्लिक ऐक्शन को अपने clickable सिमैंटिक में अपने-आप पास कर देता है. दूसरे सिमैंटिक्स मॉडिफ़ायर ऐक्शन में, क्लिक ऐक्शन को शून्य पर सेट किया जा सकता है. हालांकि, क्लिक लेबल को दूसरे सिमैंटिक मॉडिफ़ायर onClick(label = "Open this document") से लिया गया है, क्योंकि यह पहले सिमैंटिक मॉडिफ़ायर में मौजूद नहीं था.

ऐसा हो सकता है कि आपको ऐसे मामले दिखें जिनमें आपको बच्चों के लिए बने कॉन्टेंट के सिमैंटिक को पैरंट कॉन्टेंट के सिमैंटिक के साथ मर्ज करने की उम्मीद हो, लेकिन ऐसा न हो. ज़्यादा जानकारी के लिए, मर्ज करना और मिटाना लेख पढ़ें.

कस्टम कॉम्पोनेंट

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

आपको सिमेंटिक को साफ़ तौर पर बताने और सेट करने वाले सेक्शन में, कस्टम टॉगल कॉम्पोनेंट का उदाहरण भी मिल सकता है. साथ ही, एपीआई के दिशा-निर्देशों में, कस्टम कॉम्पोनेंट में ऐक्सेसिबिलिटी की सुविधा को सपोर्ट करने के तरीके के बारे में ज़्यादा जानकारी मिल सकती है.