更改回收视图列宽

Changing Recycle View Column Widths

RecycleView 给我带来了一些麻烦,尤其是将列更改为特定大小时。我用 RecycleView 上方的 GridLayout 对预期的列宽进行了编码。当一个单元格通过使用模数 selected 时,我还采用了一种奇怪的方式 select 整行。我不确定这是否是最好的方法,但我希望得到其他人对此方法的意见。

我最终希望能够删除整行,然后是 JSON 文件中的 selected 数据。但现在,我只希望宽度适当。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.storage.jsonstore import JsonStore
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

kv_string = """

ScreenManager:
    id: manager

    Screen:
        BoxLayout:
            orientation: 'vertical'
            canvas:
                Color:
                    rgba: .2,.2,.5,1
                Rectangle:
                    pos: self.pos
                    size: self.size

            GridLayout:
                size_hint_y: .3
                cols:4
                MyButton:
                    text: 'Num'
                    size_hint_x: 0.5
                MyButton:
                    text: 'Ratings'
                MyButton:
                    text: 'Name'
                    size_hint_x: 2
                MyButton:
                    text: 'Score'
                    on_press:
                        #arrange the boxing in ascending or descending order

            RecycleView:
                data: [{'text': str(x)} for x in app.data]
                viewclass: 'SelectableLabel'

                SelectableRecycleGridLayout:
                    cols: 4
                    #default_size: None, dp(26)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
                    multiselect: True
                    touch_multiselect: True

            ToggleButton:
                id: toggle_button
                size_hint_y: .3
                text: 'Delete Selected'
                state: 'normal'
                on_press:
                    app.data = [0]

<SelectableLabel>:
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size

<MyButton@Button>:
    background_color: 0,0,0,1
"""
class SelectableLabel(RecycleDataViewBehavior, Label):
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        if super(SelectableLabel, self).on_touch_down(touch):
            return True

        # *** This selects the whole row *** # Not sure if this is the best way.
        if self.collide_point(*touch.pos) and self.selectable:
            self.parent.select_with_touch(self.index, touch)
            if self.index % 4 == 0:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index + 2)
                self.parent.select_with_touch(self.index + 3)
                return
            elif self.index % 4 == 1:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index + 2)
                self.parent.select_with_touch(self.index -1)
                return
            elif self.index % 4 == 2:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index - 2)
                self.parent.select_with_touch(self.index -1)
                return
            elif self.index % 4 == 3:
                self.parent.select_with_touch(self.index - 1)
                self.parent.select_with_touch(self.index - 2)
                self.parent.select_with_touch(self.index - 3)
                return

    def apply_selection(self, rv, index, is_selected):
        self.selected = is_selected

        if App.get_running_app().root.ids.toggle_button.state == 'down':
            print('Deleted', index) #Still need to add delete function
            rv.layout_manager.clear_selection() #Not working
            self.remove_widget(index) #Also not working

class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior, RecycleGridLayout):
    pass

class MyApp(App):

    data = [] #ListProperty?

    store = JsonStore('file.json')
    store.put('Example: 1', value_1 = 'Rating: C', value_2 = 'Score: 10', value_3 = 'Name: Zack')
    store.put('Example: 2', value_1 = 'Rating: A', value_2 = 'Score: 32', value_3 = 'Name: Pete')
    store.put('Example: 3', value_1 = 'Rating: B', value_2 = 'Score: 24', value_3 = 'Name: Toby')
    store.put('Example: 4', value_1 = 'Rating: D', value_2 = 'Score: 03', value_3 = 'Name: Lars')

    x = 0

    for rows in store.keys():
        x += 1
        data.append(x)
        for row in store.get(rows):
            data.append(store.get(rows)[row])

    print(data) #shows successfully appended

    def build(self):
        root_widget = Builder.load_string(kv_string)
        return root_widget

if __name__ == "__main__":
    MyApp().run()

有点丑陋,但您可以将 refresh_view_layout 方法添加到 SelectableLabel class:

def refresh_view_layout(self, rv, index, layout, viewport):
    mod = index % 4
    if mod == 0:
        layout['size_hint'] = (0.15, None)
    elif mod == 1:
        layout['size_hint'] = (0.225, None)
    elif mod == 2:
        layout['size_hint'] = (0.225, None)
    elif mod == 3:
        layout['size_hint'] = (0.4, None)
    super(SelectableLabel, self).refresh_view_layout( rv, index, layout, viewport)

因此,您可以将每个 SelectableLabelsize_hint 设置为您想要的任何值。如果您使 size_hint_x 与用于 Button 列 headers 的 size_hint_x 一致,我想您会得到想要的。