【问题标题】:RecycleView change index when using refresh_from_data() in Kivy在 Kivy 中使用 refresh_from_data() 时 RecycleView 更改索引
【发布时间】:2019-02-13 15:51:39
【问题描述】:

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

通过改变 index = 0 的 togglebutton 的状态,可以观察 index[0] 如何在 RecycleView 的左上角和 RecycleView 的右下角之间切换。我下面的代码说明了这一点。只要按下任何按钮,我就将 index[0] 设置为“向下”。

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】:

    我认为稍微不同的方法会更好。而不是设置特定按钮的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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      相关资源
      最近更新 更多