在Kivy中使用带有RecycleView的ScreenManager

时间:2017-10-06 12:21:04

标签: python kivy

我有一个响应触摸输入的RecycleView小部件。我需要RecycleView上的每一行将用户带到特定的屏幕。现在我只有两个屏幕设置。

这是Python代码:

class Navigator(NavigationDrawer):
    image_source = StringProperty('images/1canaa.jpg')
    title = StringProperty('Navigation')

# This is the screen that is initiated when the app runs 
class MainScreen(Screen):
    pass

# This is the screen that is suppose to initiate when the first row is 
# touched
class MapScreen(Screen):
    pass


class Manager(ScreenManager):
    main_screen_obj = ObjectProperty(None)
    map_screen_obj = ObjectProperty(None)


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                             RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
        rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
            if rv.data[index] == {'text': 'FIRST ROW'}:
                Manager.current = 'mapScreen'
                print('The evaluation was executed')


        else:
            print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)

        Unidades = ['FIRST ROW', 'SECOND ROW', 'THIRD ROW', 'FORTH ROW']

        self.data = [{'text': x} for x in Unidades]


class Main(App):
    theme_cls = ThemeManager()
    nav_drawer = ObjectProperty()

    def build(self):
        self.nav_drawer = Navigator()
        return Manager()


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

如果你看一下selectableLabel类中的apply_selection方法,你会看到我试图通过检查来解决这个问题:

if the rv.data[index] == {'text': 'FIRST ROW'}:
    Manager.current = 'mapScreen'
    print('The evaluation was executed')

这不起作用。请注意,我打印了一条消息,以检查评估是否已经发生,并且确实如此。当我运行应用程序时,我收到消息:“评估已执行”。但是用户没有被带到MapScreen。

这是kv代码:

#:import MapSource mapview.MapSource
#:import Toolbar kivymd.toolbar.Toolbar
#:import hex kivy.utils.get_color_from_hex


<SelectableLabel>:
# Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: hex('#867979') if self.selected else hex('#808080')
        Rectangle:
            pos: self.pos
            size: self.size


<RV>:
    viewclass: 'SelectableLabel'

    SelectableRecycleBoxLayout:

        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: False
        touch_multiselect: True


<MainScreen>:
    BoxLayout:
        orientation: 'vertical'

        Label:
            size_hint: None, None
            height: 45
            width: 100
            pos_hint: {'center_y': 0.5, 'center_x': 0.5}
            text: '[size=40]Unidades de Assistência[/size]'
            color: hex('#676767')
            markup: True
            font_name: 'alex-brush.regular.ttf'

        RV: 

<MapScreen>:
    BoxLayout:
        Label:
            text: 'MapScreen'



<Manager>:
    id: screen_manager
    main_screen_obj: main_screen
    map_screen_obj: map_screen

    MainScreen:
        id: main_screen
        name: 'mainScreen'
        manager: screen_manager


    MapScreen:
        id: map_screen
        name: 'mapScreen'
        manager: screen_manager

所以,我在这里想要完成的事情非常简单,或者至少它应该是。这一切归结为:如果触摸了第一行,请将用户带到MapScreen ...如果触摸了第二行,请将用户带到其他屏幕......等等。

我希望这不是很混乱。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

有两种方法可以做到这一点,从头到尾。 一种是在kivy花园中使用路由器模块:

https://github.com/kivy-garden/garden.router

另一个是将screenmanager的引用传递给循环视图中的小部件,这样您就可以说self.manager.current = self.text,但这意味着您必须先将所有屏幕添加到管理器中。

我会用这个工厂:

from kivy.factory import Factory

class MyScreenManager(ScreenManager):
    def create_and_switch_screen(self, name):
        # This creates an instance of the class name you passed
        new_screen = getattr(Factory, name)()
        self.switch_to(my_screen)

通过这种方式,您可以以编程方式创建每个屏幕并将它们定义为单独的类。