在Kivy中使用refresh_from_data()时,RecycleView更改索引

问题描述 投票:0回答:1

我正在尝试创建一个简单的表,在RecycleView中选择一个项目选择整行。这已通过更改单击行上每个togglebutton的状态,通过其索引来解决。但是,如果我想手动将一些数据添加到我的recycleview中,然后使用refresh_from_data()方法更新表,则会导致一些奇怪的行为。 refresh_from_data()方法更改recycleview中按钮的索引。

通过使用index = 0更改togglebutton的状态,可以观察索引[0]如何在RecycleView的左上角和RecycleView的右下角之间切换。我的代码说明了这一点。只要按下任何按钮,我就将index [0]设置为等于'down'。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.recycleview.views import RecycleDataViewBehavior


class MyButton(RecycleDataViewBehavior, ToggleButton):
    index = None

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


class TestRecycleView(RecycleView):
    items_per_row = 3
    selected_data = None
    selected_row = None

    def find_row(self, instance):
        rgl = self.ids.gl
        num_buttons = len(rgl.children)
        num_rows = num_buttons // self.items_per_row
        self.selected_row = instance.index // self.items_per_row + 1
        print('Row: ', self.selected_row)
        self.selected_data = self.data[(self.selected_row - 1) * self.items_per_row: self.items_per_row
                                                                                     * self.selected_row]
        print('Data: ', self.selected_data)
        index1 = (num_rows - self.selected_row + 1) * self.items_per_row - 1
        index2 = index1 - self.items_per_row
        state = instance.state
        for index in range(index1, index2, -1):
            rgl.children[index].state = state

        print('======================')
        print('    Add some data     ')
        print('======================')

        # See how index[0] changes between the refresh()
        rgl.children[0].state = "down"
        root = App.get_running_app().root
        root.refresh_from_data()


KV = '''

<MyButton>:
    on_release:
        app.root.find_row(self)

TestRecycleView:
    data: [{'text': str(x)} if x not in range(9,12) else {'text': 'Press here'} for x in range(21)]
    viewclass: 'MyButton'
    id: rv_controller
    target_id: None
    RecycleGridLayout:
        id: gl
        cols: 3
        default_size_hint: 1, None
        orientation: 'vertical'
        key_selection: 'selectable'
        default_size: None, dp(26)
        size_hint_y: None
        height: self.minimum_height
        multiselect: True
        touch_multiselect: True

'''


class Test(App):
    def build(self):
        root = Builder.load_string(KV)
        # root.data = items
        return root


Test().run()

我得出结论,索引在0,1,2,3 ....和end,end-1,end-2之间切换,...​​意味着所选行在每个按钮之间的中间行上“镜像”按。

但是为什么RecycleView会以这种方式运行,我该怎么做呢?我想做的就是能够一键选择整行,手动添加/更改数据,我也只想在任何给定时间选择一行。

但是refresh_from_data()方法让我很难做到。

python android-recyclerview kivy kivy-language recyclerview-layout
1个回答
0
投票

我认为略有不同的方法会更好。不是设置特定按钮的state,而是将state属性添加到数据中,并更改数据中的state。这样,RecycleView将根据数据设置状态,并且按钮的交换无关紧要。所以在kv中,将数据更改为:

TestRecycleView:
    data: [{'text': str(x), 'state': 'normal'} for x in range(21)]

并将find_row()更改为:

def find_row(self, instance):
    self.selected_row = instance.index // self.items_per_row + 1
    start_index = (self.selected_row - 1) * self.items_per_row
    for index in range(start_index, start_index + self.items_per_row):
        self.data[index]['state'] = 'down' # change data, not button state
    self.refresh_from_data()
© www.soinside.com 2019 - 2024. All rights reserved.