使用 RecycleView 滚动时如何保持我的 Kivy ToggleButton 状态?

How can I keep my Kivy ToggleButton state when scrolling using a RecycleView?

如果我创建一个 ToggleButton 列表并将它们放在 RecycleView 中,切换一个 ToggleButton 会导致视图外的 ToggleButton 通过滚动进出视图来更改状态。我是否错误地实施了 RecycleView?

如果我使用按钮而不是切换按钮,我的 RecycleView 会按预期工作。

from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.properties import StringProperty,NumericProperty
Builder.load_string("""
<MyLayout>:
    orientation: 'vertical'
    spacing: 10
    RV:
<RV>:
    viewclass: 'RecycleViewRow'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'

<RecycleViewRow>:
    orientation: 'horizontal'
    ToggleButton:
        text: root.text
""")

class MyLayout(BoxLayout):
    pass

class RecycleViewRow(BoxLayout):
    text = StringProperty()

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x+1)} for x in range(30)]

class MainscreenApp(App):
    def build(self):
        return MyLayout()

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

这里是对执行 self.data 更新的代码的修改:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.properties import StringProperty

Builder.load_string("""
<MyLayout>:
    orientation: 'vertical'
    spacing: 10
    RV:
        id: rv
<RV>:
    viewclass: 'RecycleViewRow'
    RecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'

<RecycleViewRow>:
    orientation: 'horizontal'
    ToggleButton:
        id: tb
        text: root.text
        state: root.state
        on_release: app.root.ids.rv.adjust_data(root)
""")

class MyLayout(BoxLayout):
    pass

class RecycleViewRow(BoxLayout):
    text = StringProperty()
    state = StringProperty('normal')

class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': "Button " + str(x+1), 'state': "normal"} for x in range(30)]

    def adjust_data(self, rvRow):
        for d in self.data:
            if d['text'] == rvRow.text:
                d['state'] = rvRow.ids.tb.state
                rvRow.state = rvRow.ids.tb.state
                break

class MainscreenApp(App):
    def build(self):
        return MyLayout()

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