Kivy ScreenManager

Deep dive · part of Python Kivy

The ScreenManager switches between full-screen Screen objects with optional transitions - the Kivy equivalent of mobile app navigation stacks.

ScreenManager switches between Screen widgets—mobile-style navigation stacks with optional transitions (SlideTransition, FadeTransition). Each screen has a unique name; changing current property shows that screen.

KV Builder.load_string declaratively wires buttons to app.root.current = 'settings', keeping navigation logic visible in UI files.

Production code combines this topic with logging, tests, and clear module boundaries so refactors stay safe when requirements grow.

ScreenManager.add_widget(Screen(name='home')) registers routes.

current property accepts name string; invalid names raise errors.

Transitions live on ScreenManager.transition attribute.

Multiple managers possible for tabs vs modal flows—keep names unique.

Screen subclasses define on_enter/on_leave for refresh hooks.

App.root in KV refers to the widget returned from build().

Practice explaining kivy screenmanager aloud with a concrete example from your current project so the abstraction sticks beyond copy-paste exercises.

Pass data between screens via app object attributes or a lightweight state dict—Kivy has no built-in global store. Deep linking on desktop may map URLs to screen names manually.

Back button on Android should pop screen history—you may implement a stack list alongside manager.current.

Maintain a screen history stack for Android back: push the previous name before navigating forward, pop on back binding.

Track a history stack for hardware back: push current screen name before setting manager.current forward.

Read the parent tutorial on pythondeck.com for runnable snippets, then reproduce them locally in a virtual environment with pinned dependency versions matching your deployment target.

When pairing with teammates, agree on one idiomatic pattern per concern—mixed styles in one repo slow reviews and invite subtle integration bugs during merges.

Duplicate screen names causing ambiguous current switches.

Forgetting to add_screen before setting current.

Heavy on_enter network calls blocking transition animation.

Mixing ScreenManager with ModalView without z-order planning.

Centralize screen names as constants (SCREEN_HOME = 'home').

Use on_enter to refresh lists from database each visit.

Pick one transition style per app for visual consistency.

Document navigation graph for QA test scripts.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates two screens. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: Two screens
# Run in the REPL or save as a .py file and execute with python.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.lang import Builder

kv = '''
<Home@Screen>:
    Button:
        text: 'Go to settings'
        on_release: app.root.current = 'settings'
<Settings@Screen>:
    Button:
        text: 'Back'
        on_release: app.root.current = 'home'
'''
Builder.load_string(kv)

class Demo(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(Screen(name='home'))
        sm.add_widget(Screen(name='settings'))
        return sm
Demo().run()

This sample walks through two screens in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# ScreenManager switches between Screen widgets
from kivy.uix.screenmanager import ScreenManager, Screen  # navigation
from kivy.uix.button import Button  # UI

sm = ScreenManager()  # manager
home = Screen(name="home")  # first screen
settings = Screen(name="settings")  # second screen
home.add_widget(Button(text="Go settings", on_release=lambda *_: setattr(sm, "current", "settings")))  # nav
settings.add_widget(Button(text="Back", on_release=lambda *_: setattr(sm, "current", "home")))  # back
sm.add_widget(home); sm.add_widget(settings)  # register
print(sm.screen_names)  # ['home','settings']

Here is a hands-on illustration of transition swap. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# transition property animates screen changes
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition  # FX
sm = ScreenManager(transition=SlideTransition())  # slide animation
for name in ("a", "b"):  # two screens
    sc = Screen(name=name)  # screen
    sm.add_widget(sc)  # add
sm.current = "a"  # start screen
sm.current = "b"  # switch triggers transition
print(sm.current)  # b

« back to Python Kivy All tutorials