Back Press Handling v Androidu: podstata, mechanismy a implementace

Autor: IT Sectr Publikováno: 2026-06-10 Doba čtení: 9 min

Back Press Handling — je mechanismus zachycení a zpracování systémového tlačítka „Zpět” v Androidu, který určuje, jaká akce se provede při jeho stisknutí. Podle Android Developers (2024) byl od Androidu 11 tradiční metoda onBackPressed() nahrazena OnBackPressedDispatcher. Nové API umožňuje komponentám na jakékoli úrovni hierarchie zachytit stisk, nejen Activity. Klíčový rozdíl — podpora více callbacků v řetězci s prioritami.

Hlavní body

  • Back Press Handling — mechanismus zpracování systémového tlačítka „Zpět” v Androidu
  • OnBackPressedDispatcher — nové API, které nahradilo zastaralý onBackPressed()
  • Callback se registrují s prioritou a provádějí se v pořadí řetězce
  • Jetpack Compose používá BackHandler k zachycení stisku v composable
  • Support Library poskytuje zpětnou kompatibilitu až do API Level 14

Co je Back Press Handling

Back Press Handling — je systémový mechanismus Androidu, který určuje, co se stane, když uživatel stiskne hardwarové nebo softwarové tlačítko „Zpět”. V závislosti na kontextu může stisk: zavřít aktuální obrazovku a vrátit se na předchozí, skrýt klávesnici, zavřít Drawer nebo Bottom Sheet, ukončit aplikaci, pokud je uživatel na kořenové obrazovce.

Chování tlačítka „Zpět” se vyvíjelo s každou verzí Androidu. V Androidu 10 se objevila navigační gesta, v Androidu 11 — OnBackPressedDispatcher jako standardní API, a v Androidu 13 — vylepšená podpora predictive back gesture, kde systém zobrazuje animaci přechodu před skutečným provedením akce. Google se důsledně pohybuje směrem k předvídatelnému a konzistentnímu chování Back Press na všech zařízeních.

Správné zpracování tlačítka „Zpět” — kritický prvek UX v aplikaci pro Android. Uživatel očekává, že stisknutí „Zpět” ho vrátí na předchozí obrazovku v navigačním zásobníku, ne že neočekávaně ukončí aplikaci. Porušení tohoto očekávání je jedním z hlavních důvodů negativních recenzí a nízkého hodnocení v Google Play.

Evoluce Back Press API: od onBackPressed k OnBackPressedDispatcher

Historie Back Press API v Androidu odráží obecný vývoj platformy: od jednoduché metody v Activity po flexibilní systém callbacků s podporou lifecycle a Compose. Podívejme se na tři fáze vývoje.

Éra onBackPressed (API Level 1–30)

Od úplně prvního Android API bylo tlačítko „Zpět” zpracováváno v metodě onBackPressed třídy Activity. Vývojář tuto metodu přepisoval a psal svou vlastní logiku. Problém byl v tom, že Fragment a View nemohly zachytit stisk — vše řízení šlo přes Activity. To vedlo k nafouklým Activity a složitému řetězci if-else pro určení toho, kdo by měl stisk zpracovat.

Objevení OnBackPressedDispatcher (Activity 1.0.0)

S Activity 1.0.0 (AndroidX) Google představil OnBackPressedDispatcher. To je centrální dispečer, který přijímá callbacky od jakékoli komponenty — Activity, Fragment, Dialog, vlastního View. Callbacky se registrují s určením pořadí (přes priority) a mohou být dynamicky přidávány nebo odebírány. OnBackPressedDispatcher je volán dříve než starý onBackPressed, což umožňuje zachytit stisk dříve, než ho zpracuje Activity.

Predictive Back Gesture (Android 13+)

Android 13 zavedl predictive back gesture — systémovou animaci, která ukazuje, kam vede stisknutí „Zpět”, ještě předtím, než uživatel dokončí gesto. Pro podporu této animace musí vývojáři používat OnBackPressedDispatcher a určit, zda callback podporuje systémovou animaci prostřednictvím vlastnosti isEnabled. Pokud callback nepodporuje predictive animation, systém zobrazí výchozí animaci, která nemusí odpovídat kontextu aplikace.

APIMinimální SDKPodpora FragmentPredictive Back
onBackPressedAPI Level 1Přes ActivityNe
OnBackPressedDispatcherActivity 1.0.0PřímáČástečná
OnBackPressedDispatcher + lifecycleActivity 1.3.0Lifecycle-awarePlná

OnBackPressedDispatcher — architektura a řetězec callbacků

OnBackPressedDispatcher — je jádrem nového Back Press API. Spravuje řetězec callbacků, volá je v pořadí až do prvního, který zpracuje událost. Pokud žádný callback nezpracuje stisk, dispečer provede výchozí akci — volání finish() pro Activity nebo popBackStack() pro Navigation Component.

Registrace callbacku s prioritou

Callback se registruje přes addCallback s uvedením LifecycleOwner a objektu OnBackPressedCallback. Callback obsahuje vlastnost isEnabled — pokud je nastavena na false, callback je přeskočen. Pro priority lze předat hodnotu od 0 (nejnižší) do Integer.MAX_VALUE. Fragment Activity Result API používá tento mechanismus pro automatickou registraci callbacků vázaných na životní cyklus.

kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val callback = object : OnBackPressedCallback(enabled = true) {
        override fun handleOnBackPressed() {
            if (isDrawerOpen) { closeDrawer() }
            else { isEnabled = false; onBackPressed() }
        }
    }
    onBackPressedDispatcher.addCallback(this, callback)
}

Lifecycle-aware čištění

Callback je automaticky odstraněn, když LifecycleOwner přejde do stavu DESTROYED. To řeší starý problém úniků callbacků při otáčení obrazovky. Pokud je callback přidán do Fragmentu, je zaručeno, že bude odstraněn při zničení Fragmentu. Pro dočasné vypnutí callbacku se používá vlastnost isEnabled — lze ji přepínat bez odstranění a opětovné registrace.

Řetězec volání

Pořadí volání je obrácené pořadí přidávání: naposledy přidaný callback dostává řízení jako první. To je logické, protože nejvíce vnořený prvek UI (např. Bottom Sheet uvnitř Fragmentu) by měl zpracovat stisk dříve než nadřazený Fragment. Pokud nejhlubší callback nezpracovává stisk (isEnabled = false), řízení se předá dalšímu v řetězci.

Back Press ve Fragmentu a dialozích

Fragment API poskytuje vlastní integraci s OnBackPressedDispatcher prostřednictvím metody requireActivity().onBackPressedDispatcher. Od Fragmentu 1.2.0 může každý Fragment registrovat svůj vlastní callback, který se automaticky váže k životnímu cyklu Fragmentu a je odstraněn při jeho zničení.

Callback ve Fragmentu

Registrace callbacku ve Fragmentu probíhá v onCreate, onViewCreated nebo dokonce v samotném View — důležité je pouze, aby LifecycleOwner (Fragment) byl aktivní. Když Fragment přejde do stavu STARTED, callback se zapne, při STOPPED — vypne. To zaručuje, že skrytý Fragment (ve ViewPager) nebude zpracovávat stisk „Zpět”.

kotlin
class EditorFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                showDiscardDialog()
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this, callback)
    }
}

Dialog a BottomSheetDialog

Dialogy a BottomSheet automaticky zachycují stisk „Zpět” pro zavření. Pokud potřebujete provést dodatečnou akci před zavřením — zaregistrujte callback s vyšší prioritou. Důležité: pokud jste nastavili setCancelable(false) na Dialog, callback nebude fungovat — to je systémové chování.

Back Press Handling v Jetpack Compose

Jetpack Compose poskytuje deklarativní API pro zpracování tlačítka „Zpět” prostřednictvím composable funkce BackHandler. BackHandler přijímá enabled (booleovskou hodnotu) a onBack — callback, který je volán při stisku. Pokud je enabled = false, stisk je předán dále v řetězci.

BackHandler v Compose

BackHandler automaticky registruje OnBackPressedCallback v OnBackPressedDispatcher nadřazené Activity. Zohledňuje životní cyklus composable: při opuštění kompozice je callback odstraněn. enabled může být svázán se stavem — například zobrazovat potvrzovací dialog pouze v případě, že jsou ve formuláři neuložené změny.

kotlin
@Composable
fun EditScreen(hasUnsavedChanges: Boolean) {
    BackHandler(enabled = hasUnsavedChanges) {
        // Zobrazit potvrzovací dialog
    }

    Column {
        TextField(value = ..., onValueChange = ...)
    }
}

Predictive Back v Compose

Predictive back gesture v Compose je podporováno od Compose 1.5.0. BackHandler automaticky zpracovává systémovou animaci přechodu, pokud je na zařízení zapnuta. Pro vlastní predictive-animaci použijte modifikátor predictiveBackHandler, který vrací průběh gesta od 0 do 1.

Typické chyby a best practices

Back Press Handling se zdá jednoduchý, ale v praxi vývojáři dělají řadu systematických chyb. Podívejme se na nejčastější problémy a způsoby jejich řešení na základě doporučení Google a zkušeností komunity.

Chyba: volání finish() bez kontroly navigačního zásobníku

Přímé volání finish() v handleOnBackPressed může vést k neočekávanému ukončení aplikace, pokud jsou v navigačním zásobníku obrazovky na pozadí. Vždy kontrolujte NavController.backStack prostřednictvím Navigation Component nebo Coordinator před zavřením Activity.

Chyba: ignorování lifecycle při registraci callbacku

Pokud zaregistrujete callback bez LifecycleOwner (pomocí starého addCallback bez parametru), callback bude žít věčně a může způsobit NullPointerException, pokud je Activity již zničeno. Vždy používejte addCallback(this, callback) s LifecycleOwner.

Best Practice: přerušení řetězce pro modální okna

Pro modální okna (Bottom Sheet, Dialog) vždy nastavujte isEnabled = true pouze když je okno viditelné. Použijte addCallback s lambdou, která kontroluje stav okna. Navigation Component to automaticky spravuje pro NavHost.

Best Practice: zpracování dvojitého stisku

Rychlý dvojitý stisk „Zpět” může vést k dvojitému volání finish(). Použijte flag nebo throttleLast pro ochranu proti opakovaným voláním během 500 ms. Navigation Component vestavěně zpracovává tuto situaci, ale ve vlastních scénářích musíte implementovat ochranu ručně.

kotlin
private var lastBackPressTime = 0L

override fun handleOnBackPressed() {
    val currentTime = System.currentTimeMillis()
    if (currentTime - lastBackPressTime > 500) {
        lastBackPressTime = currentTime
        navigateBack()
    }
}

Často kladené otázky

Proč se onBackPressed stal deprecated?

onBackPressed se stal deprecated v Androidu 11, protože funguje pouze na úrovni Activity. OnBackPressedDispatcher umožňuje jakékoli komponentě (Fragment, Dialog, View) zachytit stisk prostřednictvím jednotného mechanismu s podporou životního cyklu.

Jak rozeznat stisk „Zpět” od gesta swipu?

Systém Android převádí gesto swipu od okraje na systémový stisk „Zpět” dříve, než ho aplikace obdrží. Na úrovni OnBackPressedDispatcher nelze tyto dvě události rozlišit — obě přicházejí jako handleOnBackPressed.

Je třeba podporovat tlačítko „Zpět” na zařízeních s gesty?

Ano, zpracování OnBackPressedDispatcher je stejné pro zařízení se třemi tlačítky a s gestovou navigací. Kód zachycení nezávisí na typu navigace — systém sám převádí gesto na volání dispečera.

Jak otestovat predictive back gesture na emulátoru?

Zapněte predictive back v Developer Options emulátoru Android 13+. Použijte ADB: `adb shell settings put global enable_back_animation 1`. Po zapnutí systémová animace zobrazí náhled přechodu při stisku „Zpět”.

Co dělat, když se callback nevolá?

Zkontrolujte dvě podmínky: LifecycleOwner musí být ve stavu STARTED nebo RESUMED a isEnabled callbacku musí být true. Pokud jsou obě podmínky splněny, ujistěte se, že callback byl přidán do správného OnBackPressedDispatcher — použijte requireActivity().onBackPressedDispatcher ve Fragmentu.

Shrnutí

  • Back Press Handling — mechanismus zpracování systémového tlačítka „Zpět” v Androidu
  • OnBackPressedDispatcher — moderní API, které nahradilo onBackPressed() od Androidu 11
  • Callback se registrují přes addCallback s LifecycleOwner a automaticky se čistí
  • Řetězec volání — naposledy přidaný callback s isEnabled=true zpracovává stisk první
  • Ve Fragmentu se callback váže k životnímu cyklu a vypíná se při skrytí fragmentu
  • Jetpack Compose používá BackHandler composable pro deklarativní zpracování
  • Predictive back gesture — systémová animace přechodu, dostupná od Androidu 13+

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také