Kivy's Screen Manager And Back Button
This is a follow up post to my previous one where I discuss how to capture the back button press in Kivy. In this post we will go over an example on how to use that knowledge to check if we can go back to any previous screen, just like any other regular Android/iOS app. First lets create two files, main.py
and example.kv
.
In main.py
put the following:
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
################################################################################
class ExampleRoot(BoxLayout):
""" Root widget for app """
screen_manager = ObjectProperty(None)
def __init__(self, *args, **kwargs):
super(ExampleRoot, self).__init__(*args, **kwargs)
# list to keep track of screens we were in
self.list_of_prev_screens = []
# --------------------------------------------------------------------------
def onNextScreen(self, btn, next_screen):
# add screen we were just in
self.list_of_prev_screens.append(btn.parent.name)
# Go to next screen
self.screen_manager.current = next_screen
################################################################################
class ExampleApp(App):
""" App to show how to use back button """
def __init__(self, *args, **kwargs):
super(ExampleApp, self).__init__(*args, **kwargs)
# --------------------------------------------------------------------------
def build(self):
return ExampleRoot()
if __name__ == "__main__":
ExampleApp().run()
The only thing that I feel needs to be explained is the onNextScreen
method. This will be called from our kv
file which we will create in just a moment, and its sole purpose is to switch screens and add the current screen it’s in to list_of_prev_screens
. This variable will keep a record of visited screens so that we can go to them when the user presses the beloved back button.
Now in example.kv
put the following:
<ExampleRoot>:
screen_manager: screen_manager
ScreenManager:
id: screen_manager
Screen:
name: "screen_hello"
Button:
text: "Hello Mate"
on_release: root.onNextScreen(self, "screen_scream")
Screen:
name: "screen_scream"
Button:
text: "SCREAM"
on_release: root.onNextScreen(self, "screen_spider_pig")
Screen:
name: "screen_spider_pig"
Button:
text: "Spider Pig!"
Pretty simple stuff so far, and as you can see we pass an instace of the button itself in onNextScreen
and the name of screen we want to go to next. If you run the app right now, you should be able to iterate through the screens but when you press the back button (in a deskop, press Esc
to simulate a back button press) the app should just close. Alright, now lets do all the binding and make it possible to go back to previous screens!
main.py
:
class ExampleRoot(BoxLayout):
# Previous code
# --------------------------------------------------------------------------
def onBackBtn(self):
# Check if there are any screens to go back to
if self.list_of_prev_screens:
# If there are then just go back to it
self.screen_manager.current = self.list_of_prev_screens.pop()
# We don't want to close app
return True
# No more screens so user must want to exit app
return False
class ExampleApp(App):
# Previous code
# --------------------------------------------------------------------------
def onBackBtn(self, window, key, *args):
""" To be called whenever user presses Back/Esc key """
# 27 is back press number code
if key == 27:
# Call the "OnBackBtn" method from the "ExampleRoot" instance
return self.root.onBackBtn()
return False
Sweet! If you run it now, you should be able to go back to previous screens and once there are no more screens to go to, it should just close. Pretty easy stuff, huh? I won’t go over the code since it’s small and the I think the comments describe what is happening pretty well.