कभी-कभी एलिमेंट के डिफ़ॉल्ट फ़ोकस व्यवहार को बदलना ज़रूरी हो जाता है किस तरह का है. उदाहरण के लिए, हो सकता है कि आप कॉम्पोनेबल ग्रुप, को रोकना फ़ोकस पर एक खास कंपोज़ेबल पर, साफ़ तौर पर फ़ोकस करने का अनुरोध करें एक पर, कैप्चर या रिलीज़ फ़ोकस या फ़ोकस रीडायरेक्ट का इस्तेमाल, पेज पर आने या बाहर जाने के लिए किया जा सकता है. यह सेक्शन में बताया गया है कि जब डिफ़ॉल्ट सेटिंग आपकी पसंद के मुताबिक न हों, तो फ़ोकस के व्यवहार को कैसे बदलें ज़रूरत.
फ़ोकस ग्रुप की मदद से, एक ही जगह पर आसानी से नेविगेट करें
कभी-कभी, Jetpack Compose, उसके लिए सही अगले आइटम का तुरंत अनुमान नहीं लगा पाता
टैब वाला नेविगेशन, खास तौर पर तब, जब कॉम्प्लेक्स पैरंट Composables
, जैसे कि टैब और
सूचियां काम करती हैं.
आम तौर पर, फ़ोकस सर्च Composables
के एलान के क्रम के हिसाब से होता है.
कुछ मामलों में ऐसा करना नामुमकिन है, जैसे कि जब Composables
में से कोई
क्रम के मुताबिक पेज को हॉरिज़ॉन्टल तरीके से स्क्रोल किया जा सकता है, जो पूरी तरह से नहीं दिखता. यह इसमें दिखाया गया है
नीचे दिया गया उदाहरण देखें.
ऐसा हो सकता है कि Jetpack Compose, यात्रा की शुरुआत में अगले आइटम पर फ़ोकस करे देखें, जैसा कि नीचे दिखाया गया है. एक-तरफ़ा नेविगेशन:
![एक ऐप्लिकेशन का ऐनिमेशन, जिसमें ऊपर का हॉरिज़ॉन्टल नेविगेशन और नीचे दिए गए आइटम की सूची दिख रही है.](https://developer.android.google.cn/static/develop/ui/compose/images/touchinput/one_directional_navigation_1.gif?authuser=19&hl=hi)
इस उदाहरण में, यह साफ़ तौर पर बताया गया है कि डेवलपर का मकसद चॉकलेट टैब से नीचे दी गई पहली इमेज पर जाएं और फिर वापस पेस्ट्री टैब. इसके बजाय, वे चाहते थे कि टैब पर तब तक फ़ोकस जारी रहे जब तक आखिरी टैब में जाकर, अंदरूनी कॉन्टेंट पर फ़ोकस करें:
![एक ऐप्लिकेशन का ऐनिमेशन, जिसमें ऊपर का हॉरिज़ॉन्टल नेविगेशन और नीचे दिए गए आइटम की सूची दिख रही है.](https://developer.android.google.cn/static/develop/ui/compose/images/touchinput/one_directional_navigation_2.gif?authuser=19&hl=hi)
उन स्थितियों में ज़रूरी है कि कंपोज़ेबल के ग्रुप पर फ़ोकस किया जाए
और पिछले उदाहरण की तरह टैब पंक्ति में, आपको सभी पंक्तियों को एक साथ
माता-पिता में से Composable
, जिसमें focusGroup()
मॉडिफ़ायर है:
LazyVerticalGrid(columns = GridCells.Fixed(4)) { item(span = { GridItemSpan(maxLineSpan) }) { Row(modifier = Modifier.focusGroup()) { FilterChipA() FilterChipB() FilterChipC() } } items(chocolates) { SweetsCard(sweets = it) } }
दो-तरफ़ा नेविगेशन, दिए गए फ़िल्टर के लिए सबसे नज़दीकी कंपोज़ेबल दिखता है
दिशा— अगर किसी अन्य समूह का कोई तत्व किसी ऐसे तत्व के करीब है जो पूरी तरह से दिखाई नहीं देता है
मौजूदा समूह में आइटम, नेविगेशन सबसे नज़दीक वाला आइटम चुनता है. इससे बचने के लिए
कार्रवाई के लिए, focusGroup()
मॉडिफ़ायर लागू किया जा सकता है.
फ़ोकस के हिसाब से, FocusGroup
पूरे ग्रुप को एक इकाई की तरह दिखाता है,
लेकिन ग्रुप पर फ़ोकस नहीं होगा. इसकी जगह, सबसे नज़दीकी बच्चा
ध्यान लगाने के बजाय उन पर फ़ोकस किया जा सकता है. इस तरह नेविगेशन, पूरी तरह से दिखने वाले (पूरी तरह से दिखाई नहीं देने वाले पेज) पर जाना चाहता है
समूह छोड़ने से पहले आइटम.
इस मामले में, FilterChip
के तीन इंस्टेंस पर
SweetsCard
आइटम, भले ही SweetsCards
उपयोगकर्ता और कुछ FilterChip
छिपे हुए हो सकते हैं. ऐसा इसलिए होता है, क्योंकि
focusGroup
मॉडिफ़ायर, फ़ोकस मैनेजर को आइटम का क्रम बदलने के लिए कहता है
फ़ोकस किए गए हों, ताकि नेविगेट करना आसान हो और यूज़र इंटरफ़ेस (यूआई) के साथ बेहतर तरीके से काम कर सके.
focusGroup
मॉडिफ़ायर के बिना, अगर FilterChipC
नहीं दिखता, तो फ़ोकस करें
नेविगेशन को सबसे आखिर में समझेगा. हालांकि, ऐसा मॉडिफ़ायर जोड़ने से यह नहीं होता कि
सिर्फ़ खोजे जाने लायक है, लेकिन FilterChipB
के ठीक बाद वह फ़ोकस भी हासिल कर लेगा, जैसे कि
उपयोगकर्ता क्या उम्मीद करते हैं.
कंपोज़ेबल को फ़ोकस करने लायक बनाना
कुछ कंपोज़ेबल, डिज़ाइन के आधार पर फ़ोकस किए जा सकते हैं. जैसे, बटन या कंपोज़ेबल
clickable
मॉडिफ़ायर लगा है. अगर आपको ख़ास तौर पर,
किसी कंपोज़ेबल में फ़ोकस करने लायक व्यवहार के लिए, focusable
मॉडिफ़ायर का इस्तेमाल किया जाता है:
var color by remember { mutableStateOf(Green) } Box( Modifier .background(color) .onFocusChanged { color = if (it.isFocused) Blue else Green } .focusable() ) { Text("Focusable 1") }
कंपोज़ेबल को फ़ोकस न करने लायक बनाना
ऐसी स्थितियां हो सकती हैं जिनमें आपके कुछ एलिमेंट को शामिल नहीं करना चाहिए
फ़ोकस में हैं. इन खास अवसरों पर, canFocus property
का फ़ायदा लिया जा सकता है
ताकि Composable
पर फ़ोकस न किया जा सके.
var checked by remember { mutableStateOf(false) } Switch( checked = checked, onCheckedChange = { checked = it }, // Prevent component from being focused modifier = Modifier .focusProperties { canFocus = false } )
FocusRequester
की मदद से, कीबोर्ड फ़ोकस का अनुरोध करें
कुछ मामलों में, हो सकता है कि आप साफ़ तौर पर उपयोगकर्ता इंटरैक्शन. उदाहरण के लिए, किसी उपयोगकर्ता से यह पूछा जा सकता है कि उसे रीस्टार्ट करना है या नहीं फ़ॉर्म भरने और अगर वे "हां" दबाएं, तो आप पहले फ़ील्ड पर फिर से फ़ोकस करना चाहते हों फ़ॉर्म भरें.
सबसे पहले, किसी FocusRequester
ऑब्जेक्ट को
जिसमें आपको कीबोर्ड के फ़ोकस को ले जाना हो. इस कोड में
तो FocusRequester
ऑब्जेक्ट, TextField
Modifier.focusRequester
नाम का मॉडिफ़ायर:
val focusRequester = remember { FocusRequester() } var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.focusRequester(focusRequester) )
असल फ़ोकस के अनुरोध भेजने के लिए, FocusRequester के requestFocus
तरीके को कॉल किया जा सकता है. आपको इस तरीके को, Composable
कॉन्टेक्स्ट के बाहर इस्तेमाल करना चाहिए
(अन्यथा, हर बार बदलाव पर इसे पुनः लागू किया जाता है). नीचे दिया गया स्निपेट
यह दिखाता है कि कीबोर्ड के फ़ोकस को इधर-उधर ले जाने के लिए, सिस्टम से अनुरोध कैसे किया जाता है कि बटन
क्लिक किया गया:
val focusRequester = remember { FocusRequester() } var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.focusRequester(focusRequester) ) Button(onClick = { focusRequester.requestFocus() }) { Text("Request focus on TextField") }
फ़ोकस कैप्चर करें और छोड़ें
फ़ोकस का फ़ायदा लेकर, उपयोगकर्ताओं को अपने ऐप्लिकेशन का सही डेटा उपलब्ध कराने के लिए बढ़ावा दिया जा सकता है को अपना काम करना होगा— उदाहरण के लिए, कोई मान्य ईमेल पता या फ़ोन नंबर पाना जोड़ें. हालांकि गड़बड़ी की स्थितियां आपके उपयोगकर्ताओं को समस्या के बारे में सूचित करती हैं, लेकिन आपको तब तक फ़ोकस करने के लिए, गलत जानकारी वाली फ़ील्ड की ज़रूरत पड़ सकती है, जब तक कि तय किया है.
फ़ोकस कैप्चर करने के लिए, captureFocus()
तरीका शुरू किया जा सकता है और
इसके बजाय, इसे बाद में freeFocus()
तरीके से रिलीज़ कर दें, जैसा कि नीचे बताया गया है
उदाहरण:
val textField = FocusRequester() TextField( value = text, onValueChange = { text = it if (it.length > 3) { textField.captureFocus() } else { textField.freeFocus() } }, modifier = Modifier.focusRequester(textField) )
फ़ोकस मॉडिफ़ायर की प्राथमिकता
Modifiers
को उन एलिमेंट के तौर पर देखा जा सकता है जिनमें सिर्फ़ एक ही चाइल्ड है. इसलिए, सूची में
बाईं ओर (या सबसे ऊपर) हर Modifier
में, इसके बाद आने वाला Modifier
शामिल होगा
दाईं ओर (या नीचे). इसका मतलब है कि दूसरा Modifier
इसके अंदर मौजूद है
ताकि दो focusProperties
का एलान करते समय, सिर्फ़ सबसे ऊपर
इनमें से एक काम करता है, क्योंकि नीचे दी गई चीज़ें सबसे ऊपर दी गई हैं.
कॉन्सेप्ट को बेहतर तरीके से समझाने के लिए, यह कोड देखें:
Modifier .focusProperties { right = item1 } .focusProperties { right = item2 } .focusable()
इस मामले में, item2
को सही फ़ोकस के तौर पर दिखाने वाला focusProperties
उसका इस्तेमाल नहीं किया जाना चाहिए, जैसा कि पहले में बताया गया है; इस तरह, item1
एक का इस्तेमाल किया गया.
इस तरीके का इस्तेमाल करके, माता-पिता भी सेटिंग को डिफ़ॉल्ट रूप से
FocusRequester.Default
का इस्तेमाल करके:
Modifier .focusProperties { right = Default } .focusProperties { right = item1 } .focusProperties { right = item2 } .focusable()
एक ही मॉडिफ़ायर चेन का हिस्सा होना ज़रूरी नहीं है. माता-पिता
कंपोज़ेबल, चाइल्ड कंपोज़ेबल की फ़ोकस प्रॉपर्टी को ओवरराइट कर सकता है. उदाहरण के लिए,
इस FancyButton
को देखें, जो बटन को फ़ोकस करने लायक नहीं बनाता:
@Composable fun FancyButton(modifier: Modifier = Modifier) { Row(modifier.focusProperties { canFocus = false }) { Text("Click me") Button(onClick = { }) { Text("OK") } } }
इस बटन को फिर से फ़ोकस करने लायक बनाने के लिए, उपयोगकर्ता canFocus
को true
पर सेट कर सकता है:
FancyButton(Modifier.focusProperties { canFocus = true })
हर Modifier
की तरह, फ़ोकस से जुड़े फ़ंक्शन, क्रम के हिसाब से अलग-अलग तरह से काम करते हैं
करने के लिए कहा जाएगा. उदाहरण के लिए, इस तरह के कोड से Box
फ़ोकस करने लायक है, लेकिन FocusRequester
इस फ़ोकस करने लायक डिवाइस से नहीं जुड़ा है, क्योंकि यह
फ़ोकस करने लायक होने के बाद एलान किया जाता है.
Box( Modifier .focusable() .focusRequester(Default) .onFocusChanged {} )
याद रखें कि focusRequester
पहले
क्रम में इसके नीचे फ़ोकस किया जा सकता है, ताकि यह focusRequester
ध्यान लगाने लायक पहला बच्चा. कोई जानकारी उपलब्ध न होने पर, उसका इस्तेमाल किसी चीज़ पर नहीं किया जाएगा.
हालांकि, Box
पर फ़ोकस किया जा सकता है (focusable()
मॉडिफ़ायर की मदद से),
तो दो-तरफ़ा नेविगेशन का इस्तेमाल करके इस पर जाएं.
एक अन्य उदाहरण के तौर पर, onFocusChanged()
के तौर पर इनमें से कोई एक काम करेगा
मॉडिफ़ायर फ़ोकस करने लायक उस पहले एलिमेंट को कहते हैं जो फ़ोकस करने लायक पहले एलिमेंट के बाद दिखता है
focusable()
या focusTarget()
मॉडिफ़ायर.
Box( Modifier .onFocusChanged {} .focusRequester(Default) .focusable() ) |
Box( Modifier .focusRequester(Default) .onFocusChanged {} .focusable() ) |
एंट्री या एग्ज़िट पर फ़ोकस को रीडायरेक्ट करना
कभी-कभी, आपको एक बहुत ही खास तरह का नेविगेशन देना पड़ता है, जैसे कि नीचे ऐनिमेशन में दिखाया गया है:
![एक स्क्रीन का ऐनिमेशन, जिसमें दो कॉलम अगल-बगल रखे हुए हैं और फ़ोकस को एक से दूसरे कॉलम पर ऐनिमेट किया गया है.](https://developer.android.google.cn/static/develop/ui/compose/images/touchinput/two_dimensional_navigation_1.gif?authuser=19&hl=hi)
इसे बनाने के तरीके के बारे में विस्तार से बात करने से पहले, यह जानना ज़रूरी है कि डिफ़ॉल्ट
फ़ोकस सर्च का व्यवहार. खोज पर एक बार फ़ोकस करके, बिना किसी बदलाव के
डी-पैड पर DOWN
दबाकर, Clickable 3
आइटम तक पहुंचता है या इसके बराबर
ऐरो बटन) का इस्तेमाल करके, फ़ोकस को Column
के नीचे दिखाई गई किसी भी चीज़ पर ले जाया जाएगा,
ग्रुप से बाहर निकलें और दाईं ओर वाले हिस्से को अनदेखा करें. अगर कोई
फ़ोकस करने लायक आइटम उपलब्ध हैं, फ़ोकस कहीं भी नहीं जाता, लेकिन फ़ोकस में रहता है
Clickable 3
.
इस व्यवहार में बदलाव करने और सही नेविगेशन देने के लिए,
focusProperties
मॉडिफ़ायर, जिससे आपको यह मैनेज करने में मदद मिलती है कि फ़ोकस होने पर क्या होता है
खोज Composable
में प्रवेश करता है या बाहर निकालता है:
val otherComposable = remember { FocusRequester() } Modifier.focusProperties { exit = { focusDirection -> when (focusDirection) { Right -> Cancel Down -> otherComposable else -> Default } } }
इसके अंदर, किसी खास Composable
पर फ़ोकस किया जा सकता है
या पदानुक्रम के किसी खास हिस्से से बाहर निकल जाता है— उदाहरण के लिए, जब आपके यूज़र इंटरफ़ेस (यूआई) में दो
कॉलम में है और आप यह सुनिश्चित करना चाहते हैं कि जब भी पहला वाला संसाधित हो,
फ़ोकस दूसरे पर स्विच होता है:
![एक स्क्रीन का ऐनिमेशन, जिसमें दो कॉलम अगल-बगल रखे हुए हैं और फ़ोकस को एक से दूसरे कॉलम पर ऐनिमेट किया गया है.](https://developer.android.google.cn/static/develop/ui/compose/images/touchinput/two_dimensional_navigation_2.gif?authuser=19&hl=hi)
इस GIF में, जब फ़ोकस Column
1 में Clickable 3 Composable
पर पहुंच जाता है,
अगले आइटम पर फ़ोकस किया जा रहा है, जो दूसरे Column
में Clickable 4
है. यह व्यवहार
focusDirection
को enter
और exit
के साथ जोड़कर हासिल किया जा सकता है
वैल्यू को focusProperties
मॉडिफ़ायर में बदला जा सकता है. उन दोनों को एक लैम्डा की ज़रूरत होती है, जो
एक पैरामीटर के रूप में उस दिशा से जहां से फ़ोकस आ रहा है और
FocusRequester
. यह लैम्डा तीन तरह से काम कर सकता है: लौटने वाले
FocusRequester.Cancel
फ़ोकस को जारी रखने से रोकता है, जबकि
FocusRequester.Default
अपने व्यवहार में बदलाव नहीं करता है. इसके बजाय,
FocusRequester
को किसी दूसरे Composable
से अटैच करने पर, फ़ोकस सीधे उस पर जाता है
खास Composable
.
फ़ोकस को बेहतर बनाने की दिशा बदलें
फ़ोकस को अगले आइटम पर या किसी सटीक दिशा पर ले जाने के लिए,
onPreviewKey
मॉडिफ़ायर का इस्तेमाल करें और LocalFocusManager
को
moveFocus
मॉडिफ़ायर की मदद से फ़ोकस को बेहतर बनाएं.
इस उदाहरण में, फ़ोकस करने के डिफ़ॉल्ट तरीके के बारे में बताया गया है: जब कोई
tab
बटन दबाने का पता चला है. फ़ोकस अगले एलिमेंट पर ले जाता है
सूची. आम तौर पर, आपको इसे कॉन्फ़िगर करने की ज़रूरत नहीं होती है. हालांकि, यह ज़रूरी है
डिफ़ॉल्ट को बदलने के लिए सिस्टम के आंतरिक कामों को जानने के लिए
व्यवहार.
val focusManager = LocalFocusManager.current var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.onPreviewKeyEvent { when { KeyEventType.KeyUp == it.type && Key.Tab == it.key -> { focusManager.moveFocus(FocusDirection.Next) true } else -> false } } )
इस सैंपल में, focusManager.moveFocus()
फ़ंक्शन फ़ोकस को आगे बढ़ाकर
आइटम में बताया गया है या फ़ंक्शन पैरामीटर में बताई गई दिशा तक.
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- फ़ोकस करने के लिए प्रतिक्रिया दें
- Compose पर फ़ोकस करें
- फ़ोकस ट्रैवर्सल का क्रम बदलना