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

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

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

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

टच टारगेट (स्क्रीन के वे हिस्से जहां छूने पर कोई कार्रवाई होती है) का कम से कम साइज़

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

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

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

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

जब 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)
        )
    }
}

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

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

@Composable
private fun MinimumInteractiveBox() {
    var clicked by remember { mutableStateOf(false) }
    Row(verticalAlignment = Alignment.CenterVertically) {
        Box(
            Modifier
                .clickable { clicked = !clicked }
                .minimumInteractiveComponentSize()
                .size(24.dp)
                .background(if (clicked) Color.DarkGray else Color.Black)
        )
        Text("Option")
    }
}

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

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 मॉडिफ़ायर का डायरेक्ट ऐक्सेस न हो. उदाहरण के लिए, जब इसे किसी लोअर नेस्टेड लेयर में सेट किया गया हो. हालांकि, इसके बाद भी आपको डिफ़ॉल्ट तौर पर सेट किए गए सूचना लेबल को बदलना हो. इसके लिए, clickable को सेट करने और सूचना में बदलाव करने की प्रोसेस को अलग-अलग करें. इसके लिए, semantics मॉडिफ़ायर का इस्तेमाल करें और वहां क्लिक लेबल सेट करें, ताकि कार्रवाई को दिखाने के तरीके में बदलाव किया जा सके:

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

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

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

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

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