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

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

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

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

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

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

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

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

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

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

@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 के अन्य एपीआई की मदद से बदला जा सकता है.

सहभागी तत्‍व

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")
}

ऐक्सेसibililty सेवाओं के बारे में ज़्यादा जानकारी देने और कार्रवाई के बारे में बेहतर तरीके से बताने के लिए, पैरंट पर क्लिक किए जा सकने वाले किसी खास 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
                }
            )
        }
    )
}

इस मामले में, आपको क्लिक ऐक्शन को दो बार पास करने की ज़रूरत नहीं है, क्योंकि clickable या Button जैसे मौजूदा Compose एपीआई, इसे आपके लिए मैनेज करते हैं. ऐसा इसलिए होता है, क्योंकि मर्ज करने का लॉजिक यह पक्का करता है कि मौजूद जानकारी के लिए, सबसे बाहरी मॉडिफ़ायर लेबल और कार्रवाई की जाए.

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

आपको ऐसे मामले मिल सकते हैं जहां आपको लगता है कि चाइल्ड सेमेंटेक्स को किसी पैरंट सेमेंटेक्स में मर्ज किया जाना चाहिए, लेकिन ऐसा नहीं होता. ज़्यादा जानकारी के लिए, मर्ज करना और मिटाना देखें.

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

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

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

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

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