Search code examples
pythonkivykivy-language

How to move to next screen when button of viewclass in recycleview gets pressed that is on screen in kivy?


I am working on the app that contains several stages on different screens so I chose RecycleView for stage screen. Now I just want to reach different screens by clicking different buttons of RecycleView having viewclass Button.

The code that I am providing is not the actual code but it is the part of that that is having the required screens. Just help me to access screen(name: 'first') by clicking button having text '1' of RV ,rest I will do myself.

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.recycleview import RecycleView

Builder.load_string('''
<ExampleRV>:
    viewclass: 'Button'

    RecycleBoxLayout:

        size_hint_y: None
        size_hint_x: None
        pos_hint: {'x': 0,'top': 0}

        height: self.minimum_height
        width: self.minimum_width

        orientation: 'horizontal'

<Manager>:

    Screen:
        name: 'main'
        Button:
            text: "Press me"
            size_hint: 0.8, 0.2
            pos_hint: {"x":0.1, "y":0.1}
            on_release: root.current = 'next'
    Screen:
        name: 'next'
        ExampleRV:

    Screen:
        name: 'first'
        Button:
            text:'Press to go back'
            on_release:
                root.current= 'main'

''')

class ExampleRV(RecycleView):

    def __init__(self, **kwargs):
        super(ExampleRV, self).__init__(**kwargs)

        self.data = [{'text': str(x)} for x in range(1,21)]

class Manager(ScreenManager):
    pass

sm = Manager()

class myApp(App):
    def build(self):
        return sm

if __name__ == '__main__':
    myApp().run()

Solution

  • Custom Buttons must be created that have the ScreenManager as their property and the names of the screens that are pressed when the button is changed and the Screen changed. That information must be sent through the data property. Considering the above I have modified your code generating 2 screen: first and second associated with 2 buttons:

    from kivy.app import App
    
    from kivy.lang import Builder
    
    from kivy.properties import ListProperty
    
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.recycleview import RecycleView
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    
    Builder.load_string(
        """
    <ManagerButton@Button>:
        manager: None
        name_screen: ""
        on_press:
            self.manager.current = self.name_screen
    
    <ExampleRV>:
        viewclass: 'ManagerButton'
    
        RecycleBoxLayout:
    
            size_hint_y: None
            size_hint_x: None
            pos_hint: {'x': 0,'top': 0}
    
            height: self.minimum_height
            width: self.minimum_width
    
            orientation: 'horizontal'
    
    <Manager>:
        Screen:
            name: 'main'
            Button:
                text: "Press me"
                size_hint: 0.8, 0.2
                pos_hint: {"x":0.1, "y":0.1}
                on_release: root.current = 'next'
        Screen:
            name: 'next'
            ExampleRV:
                data: [ {"text": str(i), "manager": root, "name_screen": name} for i, name in enumerate(self.screen_names, 1) ]
    
        Screen:
            name: 'first'
            Button:
                text:'First: Press to go back'
                on_release:
                    root.current= 'main'
    
        Screen:
            name: 'second'
            Button:
                text:'Second: Press to go back'
                on_release:
                    root.current= 'main'
    
    """
    )
    
    
    class ExampleRV(RecycleView):
        screen_names = ListProperty(["first", "second"])
    
    
    class Manager(ScreenManager):
        pass
    
    
    sm = Manager()
    
    
    class myApp(App):
        def build(self):
            return sm
    
    
    if __name__ == "__main__":
        myApp().run()