代码之家  ›  专栏  ›  技术社区  ›  Arash GM

kivy多列回收视图

  •  4
  • Arash GM  · 技术社区  · 6 年前

    我只是在玩 Python kivy ,我已将字符串数据加载到 RecyclerView 根据Kivy官方文件。但我在将对象像表单数据一样加载到列表中的多个列上时遇到了困难。例如,我想将姓名、姓氏和年龄分列为三列,标题标题一行一行,我也尝试过 RecyclerGridLayout 有3列,但它可以将名称加载到网格中,而不考虑逐行要求。

    <RV>:
        viewclass: 'Label'
        RecycleBoxLayout:
            default_size: None, dp(56)
            default_size_hint: 1, None
            size_hint_y: None
            height: self.minimum_height
            orientation: 'vertical'
    

    将感谢任何提示或示例代码来了解RecyclerView的工作原理 基维

    2 回复  |  直到 6 年前
        1
  •  3
  •   VectorVictor    6 年前

    我也在寻找这个,我找不到具体的例子,所以我提供了我的解决方案。正如El3ien所说,您需要创建一个自定义类,该类将表示可选标签的每一行。

    <SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    label1_text: 'label 1 text'  # I have included two methods of accessing the labels
    label2_text: 'label 2 text'  # This is method 1
    label3_text: 'label 3 text'
    pos: self.pos
    size: self.size
    Label:
        id: id_label1  # method 2 uses the label id
        text: root.label1_text
    Label:
        id: id_label2
        text: root.label2_text
    Label:
        id: id_label3
        text: root.label3_text
    

    在将数据应用到RV中时,需要重新构造字典以反映标签布局。

    class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        paired_iter = zip(items_1, items_2)  # items_1 and items_2 are defined elsewhere
        self.data = []
        for i1, i2 in paired_iter:
            d = {'label2': {'text': i1}, 'label3': {'text': i2}}
            self.data.append(d)
    

    最后,在刷新视图中,您将指定绑定到每个标签的.label文本,或者可以使用标签ID。

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        self.label1_text = str(index)
        self.label2_text = data['label2']['text']
        self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)
    

    整个代码如下:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.recycleview import RecycleView
    from kivy.uix.recycleview.views import RecycleDataViewBehavior
    from kivy.uix.label import Label
    from kivy.uix.gridlayout import GridLayout
    from kivy.properties import BooleanProperty
    from kivy.uix.recycleboxlayout import RecycleBoxLayout
    from kivy.uix.behaviors import FocusBehavior
    from kivy.uix.recycleview.layout import LayoutSelectionBehavior
    
    Builder.load_string('''
    <SelectableLabel>:
        # Draw a background to indicate selection
        canvas.before:
            Color:
                rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
            Rectangle:
                pos: self.pos
                size: self.size
        label1_text: 'label 1 text'
        label2_text: 'label 2 text'
        label3_text: 'label 3 text'
        pos: self.pos
        size: self.size
        Label:
            id: id_label1
            text: root.label1_text
        Label:
            id: id_label2
            text: root.label2_text
        Label:
            id: id_label3
            text: root.label3_text
    
    <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: True
            touch_multiselect: True
    ''')
    
    
    items_1 = {'apple', 'banana', 'pear', 'pineapple'}
    items_2 = {'dog', 'cat', 'rat', 'bat'}
    
    
    class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                     RecycleBoxLayout):
        ''' Adds selection and focus behaviour to the view. '''
    
    
    class SelectableLabel(RecycleDataViewBehavior, GridLayout):
        ''' Add selection support to the Label '''
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
        cols = 3
    
        def refresh_view_attrs(self, rv, index, data):
            ''' Catch and handle the view changes '''
            self.index = index
            self.label1_text = str(index)
            self.label2_text = data['label2']['text']
            self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
            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]))
            else:
                print("selection removed for {0}".format(rv.data[index]))
    
    
    class RV(RecycleView):
        def __init__(self, **kwargs):
            super(RV, self).__init__(**kwargs)
            paired_iter = zip(items_1, items_2)
            self.data = []
            for i1, i2 in paired_iter:
                d = {'label2': {'text': i1}, 'label3': {'text': i2}}
                self.data.append(d)
            # can also be performed in a complicated one liner for those who like it tricky
            # self.data = [{'label2': {'text': i1}, 'label3': {'text': i2}} for i1, i2 in zip(items_1, items_2)]
    
    
    class TestApp(App):
        def build(self):
            return RV()
    
    if __name__ == '__main__':
        TestApp().run()
    
        2
  •  1
  •   el3ien    6 年前

    而不是使用 Label 作为视图类,创建一个自定义类。这可能是一个带有两个框的水平框布局。

    <CustomClass@BoxLayout>:
        orientation: "horizontal"
        Label:
        Label: