2026 में Android पर edge-to-edge और predictive back: अब क्या अनिवार्य हो गया है, और अपने UI को टूटने से कैसे बचाएं
Edge-to-edge अब API 35+ पर अनिवार्य है और predictive back डिफ़ॉल्ट जेस्चर बन गया है। Compose insets, WindowInsets, और PredictiveBackHandler के लिए एक व्यावहारिक गाइड।
इस साइकल में दो Android UI बदलाव अब वैकल्पिक नहीं रहे। API 35+ को टारगेट करने वाले ऐप्स पर edge-to-edge जबरन लागू हो गया है — अब आप इसे छोड़कर सिस्टम को अपनी ओर से opaque बार बनाने नहीं दे सकते। और predictive back — वह back-swipe जेस्चर जो आपके पूरा करने से पहले यह दिखाता है कि आप कहां जा रहे हैं — अब एक experimental फ्लैग नहीं बल्कि gesture-nav डिवाइस पर डिफ़ॉल्ट इंटरैक्शन है। दोनों में से कोई भी एक redesign नहीं है। दोनों ही उस UI को स्पष्ट रूप से तोड़ देंगे जो इनके लिए नहीं बनाया गया था, और फेल होने का तरीका दोनों में एक जैसा है: यह उस emulator पर ठीक चलता है जिसे आपने टेस्ट किया, और नॉच वाले या three-button navigation बंद किए हुए असली फोन पर टूटा हुआ दिखता है।
यहां बताया गया है कि वास्तव में क्या बदला, और वह Compose कोड जो पांच ऐप्स की स्क्रीनों को दोनों बदलावों के तहत सही बनाए रखता है।
Edge-to-edge अब कोई विकल्प नहीं है
API 35 से पहले, enableEdgeToEdge() कुछ ऐसा था जिसे आप किसी खास स्क्रीन के लिए opt-in करते थे — उन ऐप्स के लिए एक अच्छा फीचर जो चाहते थे कि content एक translucent status bar के नीचे बहे। API 35 को टारगेट करना यह विकल्प हटा देता है: Window.setDecorFitsSystemWindows(false) का व्यवहार जबरन लागू हो जाता है, सिस्टम बार पारदर्शी हो जाते हैं, और आपका root content उनके पीछे बनता है, चाहे आपने कुछ भी कॉल किया हो या नहीं।
व्यावहारिक असर यह है: कोई भी लेआउट जो यह मानता था कि status bar और navigation bar अपनी खुद की जगह रिज़र्व करते हैं, अब content को physical pixel zero से शुरू होते हुए देखता है। एक top app bar का title क्लॉक के नीचे बैठता है। एक bottom nav bar के icons gesture pill के नीचे बैठते हैं। यह कोई visual polish issue नहीं है — असली डिवाइस पर इसका मतलब है कि users आपके UI की सबसे नीचे वाली row को tap नहीं कर सकते।
समाधान “हर जगह padding जोड़ना” नहीं है। यह है WindowInsets को सही सीमा पर, एक बार लागू करना, ताकि सिस्टम बार ठीक वहीं जगह रिज़र्व करें जहां content को उसकी जरूरत है, और कहीं और नहीं।
setContent {
AppTheme {
Scaffold(
contentWindowInsets = WindowInsets.safeDrawing,
topBar = { TopAppBar(title = { Text("Stocky") }) },
) { padding ->
LazyColumn(contentPadding = padding) {
items(pantryItems) { PantryRow(it) }
}
}
}
}
Scaffold को दिए गए top bar और bottom bar का हिसाब वह पहले से ही रखता है, इसलिए ज़्यादातर स्क्रीनों को बस इस एक parameter को वायर करने की जरूरत होती है। जाल यह है कि इसे दो बार कर दिया जाए: Scaffold अपने padding value पर safe-drawing insets लागू करता है, और अगर कोई child उसके ऊपर भी .systemBarsPadding() कॉल करे, तो आपको status bar के नीचे दोगुना gap मिल जाता है — एक खाली पट्टी जो design की गलती जैसी दिखती है, पर असल में insets कोड की गलती है।
जहां insets को हाथ से हैंडल करना पड़ता है
हर स्क्रीन Scaffold से नहीं गुजरती। Granyn, Stocky, और Mintly में मुझे हाथ से ठीक करनी पड़ी तीन जगहें:
- Bottom sheets और dialogs। एक
ModalBottomSheetअपनी खुद की surface parentScaffoldके padding से बाहर बनाता है, इसलिए उसके content को सबसे भीतरी column पर अपना खुद का.navigationBarsPadding()चाहिए, वरना आखिरी row gesture bar के नीचे बैठ जाती है। - Keyboard।
WindowInsets.ime,navigationBarsसे अलग एक inset है, और यह keyboard के खुलने-बंद होने के साथ animate होता है। किसी स्क्रीन के नीचे टिके हुए text field को.navigationBarsPadding()नहीं बल्कि.imePadding()चाहिए — जब keyboard बंद हो तो दोनों overlap करते हैं, और जिस पल यह खुलता है वे अलग हो जाते हैं। - Full-bleed images या headers। जब आप जानबूझकर चाहते हैं कि content status bar के नीचे बने — एक screenshot gallery, एक hero image — तो पूरे container पर padding लगाने के बजाय उसके ऊपर रखे interactive controls (back button, share icon) पर
.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top))लगाएं, वरना आप वह effect खो देंगे जो आप चाहते थे।
वह एक आदत जो user के मिलने से पहले इसमें से ज़्यादातर पकड़ लेती है: emulator में gesture navigation और status bar के लिए “Demo mode” customization चालू रखें, और हर स्क्रीन को notch simulation चालू करके चेक करें। Three-button navigation और एक सादा status bar लगभग हर उस insets bug को छिपा देते हैं जो आप शिप करने वाले हैं।
Predictive back: एक sharp कट से एक preview तक
दूसरा बदलाव व्यवहार से जुड़ा है, लेआउट से नहीं। Predictive back सिस्टम को यह दिखाने देता है कि back gesture कहां पहुंचेगा — नीचे वाली स्क्रीन का सिकुड़ता हुआ preview — इससे पहले कि user अपनी उंगली उठाए, ताकि वे मंज़िल देखकर बीच में ही gesture रद्द कर सकें। जो ऐप्स अभी opt in नहीं हुए हैं उन्हें अब भी एक flat, instant screen swap मिलता है; gesture काम करता है, पर यह डिवाइस पर मौजूद हर दूसरे predictive-back-aware ऐप के बगल में एक jump cut जैसा दिखता है।
Opt in करने के लिए एक manifest flag और एक Compose callback चाहिए:
<!-- AndroidManifest.xml -->
<application android:enableOnBackInvokedCallback="true">
PredictiveBackHandler(enabled = showDetail) { progress ->
try {
progress.collect { backEvent ->
// backEvent.progress: 0f (शुरुआत) → 1f (कमिटेड)
scale = 1f - (backEvent.progress * 0.1f)
}
showDetail = false // gesture commit हुआ
} catch (e: CancellationException) {
scale = 1f // gesture रद्द हुआ — वापस snap करें
}
}
PredictiveBackHandler (androidx.activity.compose से) आपको एक single callback के बजाय progress events का एक Flow देता है, यही वह हिस्सा है जहां BackHandler से आने वाले लोग अटक जाते हैं। आप इसे gesture की पूरी अवधि के लिए collect करते हैं, backEvent.progress के आधार पर एक animation चलाते हैं, और aborted swipe पर आने वाला CancellationException कोई error नहीं बल्कि normal exit path है — यही वह तरीका है जिससे सिस्टम आपको बताता है कि user ने commit करने से पहले छोड़ दिया। मैंने यही Mintly की session-detail स्क्रीन के लिए इस्तेमाल किया: timer view अब back swipe करने पर थोड़ा scale down होता है और उसके पीछे की list दिखाता है, और अगर आप जल्दी छोड़ दें तो flow के बस गायब हो जाने के बजाय साफ-सुथरे तरीके से पूरे साइज़ पर वापस snap हो जाता है।
शिप करने से पहले वास्तव में क्या चेक करें
- हर स्क्रीन gesture nav चालू और three-button nav बंद होने पर सही render होती है — यही वह mode है जिसमें ज़्यादातर नए डिवाइस आते हैं।
- status bar के नीचे कोई double-padded gap नहीं है (ऊपर बताया गया
Scaffold+ manual.systemBarsPadding()वाला जाल)। - Bottom sheets और snackbars बिना hardware nav buttons वाले डिवाइस पर gesture bar को क्लियर करते हैं।
- स्क्रीन के नीचे के पास वाले text fields
.imePadding()इस्तेमाल करते हैं और keyboard खुलने पर जंप नहीं करते। - कम से कम एक स्क्रीन पर जिसमें असली navigation हो (सिर्फ पहली स्क्रीन नहीं जिसे आप टेस्ट करते हैं) predictive back वायर की गई है, ताकि gesture स्क्रीनों के बीच असंगत महसूस न हो।
एक बार इसका सामना करने के बाद इनमें से कुछ भी मुश्किल नहीं है। यह बस three-button navigation वाले एक stock emulator में अदृश्य है — जो ठीक वही setup है जिसे हम में से ज़्यादातर लोग डिफ़ॉल्ट रूप से चलता छोड़ देते हैं — और यही वजह है कि यह जितना टूटा हुआ शिप होना चाहिए उससे कहीं ज़्यादा बार टूटा हुआ शिप होता है।
// संबंधित पठन
जर्नल से और भी
Android का In-App Review API: बिना परेशान किए रेटिंग माँगना
Google के In-App Review API की एक व्यावहारिक गाइड — यह असल में कैसे काम करता है, इसे कब ट्रिगर करना चाहिए, और सामान्य 'हमें रेट करें' पॉपअप आपकी Play Store रेटिंग को चुपचाप कैसे नुकसान पहुँचा रहा है।
Android ऐप शॉर्टकट्स और Quick Settings Tiles: बिना ऐप खोले पानी लॉग करना
Android के डायनामिक ShortcutManager API और TileService की एक व्यावहारिक गाइड — कैसे एक-टैप एक्शन को पूरी तरह ऐप को छोड़कर काम करने दें, साथ ही वे गड़बड़ियाँ जो ज़्यादातर इम्प्लीमेंटेशन को फँसा देती हैं।
2026 में Android पर फोरग्राउंड सर्विस टाइप्स: वह चुनना जो आपके फीचर पर सच में लागू हो
Android के फोरग्राउंड सर्विस टाइप प्रतिबंधों की एक व्यावहारिक गाइड — dataSync, mediaPlayback, specialUse, shortService — और बिना मारे या रिजेक्ट हुए सही वाला कैसे चुनें।