जब मैंने Jetpack Compose के बारे में अपना पिछला लेख लिखा, तो मैंने कहा था कि Jetpack Compose में कुछ (मेरी राय में) बुनियादी घटक गायब हैं, और उनमें से एक टूलटिप है।
उस समय, टूलटिप्स प्रदर्शित करने के लिए कोई बिल्ट-इन कम्पोजेबल नहीं था और ऑनलाइन कई वैकल्पिक समाधान चल रहे थे। उन समाधानों की समस्या यह थी कि एक बार Jetpack Compose के नए संस्करण जारी होने पर, वे समाधान टूट सकते हैं। इसलिए यह आदर्श नहीं था और समुदाय इस उम्मीद में छोड़ दिया गया था कि भविष्य में किसी समय टूलटिप्स के लिए समर्थन जोड़ा जाएगा।
मुझे यह कहते हुए खुशी हो रही है कि Compose Material 3 के संस्करण 1.1.0 से, हमारे पास अब बिल्ट-इन टूलटिप समर्थन है। 👏
जबकि यह अपने आप में बहुत अच्छा है, उस संस्करण के जारी होने के बाद से एक साल से अधिक बीत चुका है। और बाद के संस्करणों के साथ, टूलटिप्स से संबंधित API भी काफी बदल गया है।
यदि आप चेंजलॉग देखते हैं, तो आप देखेंगे कि सार्वजनिक और आंतरिक API कैसे बदल गए हैं। इसलिए ध्यान रखें, कि जब आप इस लेख को पढ़ते हैं, तो चीजें बदलती रह सकती हैं क्योंकि टूलटिप्स से संबंधित सब कुछ अभी भी ExperimentalMaterial3Api::class एनोटेशन द्वारा चिह्नित है।
❗️ इस लेख के लिए उपयोग किया गया Material 3 का संस्करण 1.2.1 है, जो 6 मार्च, 2024 को जारी किया गया था
अब हमारे पास दो अलग-अलग प्रकार के टूलटिप्स के लिए समर्थन है:
प्लेन टूलटिप
रिच मीडिया टूलटिप
प्लेन टूलटिप
आप पहले प्रकार का उपयोग एक आइकन बटन के बारे में जानकारी प्रदान करने के लिए कर सकते हैं जो अन्यथा स्पष्ट नहीं होगा। उदाहरण के लिए, आप एक प्लेन टूलटिप का उपयोग यह इंगित करने के लिए कर सकते हैं कि आइकन बटन क्या दर्शाता है।

अपने एप्लिकेशन में टूलटिप जोड़ने के लिए, आप TooltipBox कम्पोजेबल का उपयोग करते हैं। यह कम्पोजेबल कई तर्क लेता है:
fun TooltipBox( positionProvider: PopupPositionProvider, tooltip: @Composable TooltipScope.() -> Unit, state: TooltipState, modifier: Modifier = Modifier, focusable: Boolean = true, enableUserInput: Boolean = true, content: @Composable () -> Unit, )
यदि आपने पहले कम्पोजेबल्स का उपयोग किया है तो इनमें से कुछ आपके लिए परिचित होने चाहिए। मैं उन पर प्रकाश डालूंगा जिनका यहां एक विशिष्ट उपयोग मामला है:
positionProvider - PopupPositionProvider प्रकार का, और टूलटिप की स्थिति की गणना करने के लिए उपयोग किया जाता है।
tooltip - यह वह जगह है जहां आप डिज़ाइन कर सकते हैं कि टूलटिप कैसा दिखेगा।
state - यह एक विशिष्ट टूलटिप इंस्टेंस से जुड़ी स्थिति को रखता है। यह टूलटिप को दिखाने/खारिज करने जैसे तरीकों को उजागर करता है और जब एक इंस्टेंस को इंस्टेंटिएट करते हैं, तो आप घोषित कर सकते हैं कि टूलटिप लगातार होना चाहिए या नहीं (मतलब अगर यह स्क्रीन पर तब तक प्रदर्शित रहना चाहिए जब तक उपयोगकर्ता टूलटिप के बाहर क्लिक एक्शन नहीं करता)।
content - यह वह UI है जिसके ऊपर/नीचे टूलटिप प्रदर्शित होगा।
यहां सभी प्रासंगिक तर्कों के साथ BasicTooltipBox को इंस्टेंटिएट करने का एक उदाहरण है:
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class) @Composable fun BasicTooltip() { val tooltipPosition = TooltipDefaults.rememberPlainTooltipPositionProvider() val tooltipState = rememberBasicTooltipState(isPersistent = false) BasicTooltipBox(positionProvider = tooltipPosition, tooltip = { Text("Hello World") } , state = tooltipState) { IconButton(onClick = { }) { Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Your icon's description") } } }

Jetpack Compose में TooltipDefaults नामक एक बिल्ट-इन क्लास है। आप इस क्लास का उपयोग उन तर्कों को इंस्टेंटिएट करने में मदद के लिए कर सकते हैं जो TooltipBox बनाते हैं। उदाहरण के लिए, आप टूलटिप को एंकर एलिमेंट के संबंध में सही ढंग से स्थिति देने के लिए TooltipDefaults.rememberPlainTooltipPositionProvider का उपयोग कर सकते हैं।
रिच टूलटिप
एक रिच मीडिया टूलटिप एक प्लेन टूलटिप से अधिक जगह लेता है और आइकन बटन की कार्यक्षमता के बारे में अधिक संदर्भ प्रदान करने के लिए उपयोग किया जा सकता है। जब टूलटिप दिखाया जाता है, तो आप आगे की व्याख्या या परिभाषा प्रदान करने के लिए इसमें बटन और लिंक जोड़ सकते हैं।
इसे प्लेन टूलटिप के समान तरीके से इंस्टेंटिएट किया जाता है, TooltipBox के अंदर, लेकिन आप RichTooltip कम्पोजेबल का उपयोग करते हैं।
TooltipBox(positionProvider = tooltipPosition, tooltip = { RichTooltip( title = { Text("RichTooltip") }, caretSize = caretSize, action = { TextButton(onClick = { scope.launch { tooltipState.dismiss() tooltipState.onDispose() } }) { Text("Dismiss") } } ) { Text("This is where a description would go.") } }, state = tooltipState) { IconButton(onClick = { /* Icon button's click event */ }) { Icon(imageVector = tooltipIcon, contentDescription = "Your icon's description", tint = iconColor) } }
रिच टूलटिप के बारे में कुछ बातें नोटिस करें:
एक रिच टूलटिप में कैरेट के लिए समर्थन है।
आप टूलटिप में एक एक्शन (यानी एक बटन) जोड़ सकते हैं ताकि उपयोगकर्ताओं को अधिक जानकारी खोजने का विकल्प दिया जा सके।
आप टूलटिप को खारिज करने का लॉजिक जोड़ सकते हैं।


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

टूलटिप की स्थिति को "रीसेट" करने के लिए, हमें onDispose विधि को कॉल करना होगा जो टूलटिप स्टेट के माध्यम से उजागर होती है। एक बार जब हम ऐसा करते हैं, तो टूलटिप स्टेट रीसेट हो जाती है और जब उपयोगकर्ता UI आइटम पर लॉन्ग प्रेस करता है तो टूलटिप फिर से दिखाया जाएगा।
@OptIn(ExperimentalMaterial3Api::class) @Composable fun RichTooltip() { val tooltipPosition = TooltipDefaults.rememberRichTooltipPositionProvider() val tooltipState = rememberTooltipState(isPersistent = true) val scope = rememberCoroutineScope() TooltipBox(positionProvider = tooltipPosition, tooltip = { RichTooltip( title = { Text("RichTooltip") }, caretSize = TooltipDefaults.caretSize, action = { TextButton(onClick = { scope.launch { tooltipState.dismiss() tooltipState.onDispose() /// <---- HERE } }) { Text("Dismiss") } } ) { } }, state = tooltipState) { IconButton(onClick = { }) { Icon(imageVector = Icons.Filled.Call, contentDescription = "Your icon's description") } } }

एक और परिदृश्य जहां टूलटिप स्टेट रीसेट नहीं होती है, यदि उपयोगकर्ता टूलटिप के बाहर क्लिक करता है, जिससे इसे खारिज कर दिया जाता है, बजाय इसके कि हम स्वयं डिसमिस मेथड को उपयोगकर्ता की कार्रवाई के अनुसार कॉल करें। यह पर्दे के पीछे डिसमिस मेथड को कॉल करता है और टूलटिप स्टेट को खारिज पर सेट किया जाता है। हमारे टूलटिप को फिर से देखने के लिए UI एलिमेंट पर लॉन्ग प्रेस करने का परिणाम कुछ भी नहीं होगा।

हमारा लॉजिक जो टूलटिप के onDispose मेथड को कॉल करता है, ट्रिगर नहीं होता है, तो हम टूलटिप की स्थिति को कैसे रीसेट कर सकते हैं?
वर्तमान में, मैं इसका पता नहीं लगा पाया हूं। यह टूलटिप के MutatorMutex से संबंधित हो सकता है। शायद आगामी रिलीज में इसके लिए एक API होगा। मैंने देखा कि यदि स्क्रीन पर अन्य टूलटिप्स मौजूद हैं और उन्हें दबाया जाता है, तो यह पहले क्लिक किए गए टूलटिप को रीसेट कर देता है।

यदि आप यहां दिखाए गए कोड को देखना चाहते हैं, तो आप इस GitHub रिपॉजिटरी पर जा सकते हैं
यदि आप किसी एप्लिकेशन में टूलटिप्स देखना चाहते हैं, तो आप इसे यहां देख सकते हैं।
संदर्भ
Material3 टूलटिप अवलोकन
टूलटिप डिफॉल्ट्स
टूलटिप सोर्स कोड
मुफ्त में कोड करना सीखें। freeCodeCamp का ओपन सोर्स पाठ्यक्रम 40,000 से अधिक लोगों को डेवलपर्स के रूप में नौकरी पाने में मदद कर चुका है। शुरू करें