Kivy Multiple Column RecyclerView

Ara*_* GM 5 python python-3.x kivy kivy-language

我只是在玩Pythonkivy,我已经RecyclerView按照 kivy 官方文档将我的字符串数据加载到 a中。但是我在将对象加载到列表中的多列(如表单数据)时遇到了麻烦。例如,我想将姓名、姓氏和年龄设置为三列,标题标题逐行,我也尝试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'
Run Code Online (Sandbox Code Playgroud)

将欣赏任何提示或示例代码以了解 RecyclerView 如何工作 kivy

Vec*_*tor 5

我也在寻找这个,但找不到具体的例子,所以我提供了我的解决方案。正如 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
Run Code Online (Sandbox Code Playgroud)

在将您的数据应用到 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)
Run Code Online (Sandbox Code Playgroud)

最后在 refresh_view_attrs 中,您将指定绑定到每个标签的 .label_text,或者您可以使用标签 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)
Run Code Online (Sandbox Code Playgroud)

整个代码如下:

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()
Run Code Online (Sandbox Code Playgroud)