旋转木马滑动方向的 Kivy RecycleView 不起作用

Kivy RecycleView for Carousel slide direction not working

每个 kivy 旋转木马幻灯片都由顶部的图像(带有复选框)和下面的文本组成。轮播的方向是'right'(横向一个接一个)。图像和文本数据通过回收视图传送到轮播。

最小代码结果为 a) 每张幻灯片垂直堆叠; b) 复选框不显示。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.properties import StringProperty, ListProperty, NumericProperty

Builder.load_string("""
<CarouselSlide>:
    BoxLayout:
        orientation: 'vertical'
        size_hint_y: 1
        AsyncImage:
            source: root.tile
            size_hint_y: 0.5
            CheckBox:
                id: cb
                root_ref: root.index
                on_press: app.on_checkbox_press(self, self.active, self.state, self.root_ref)
        TextInput:
            text: root.text
            size_hint_y: 0.5
            multiline: True

<CarouselScreen>:
    name: 'carousel_screen'
    Carousel:
        direction: 'right'
        ignore_perpendicular_swipes: True
        size: root.width, root.height
        RV:
            id: rv
            viewclass: 'CarouselSlide'
            RecycleBoxLayout:
                orientation: 'vertical'
                size_hint_y: None
                default_size_hint: 1, None
                height: self.minimum_height
                default_size: 1, root.height
""")

class CarouselScreen(Screen):
    pass

class CarouselSlide(Screen):
    tile = StringProperty('')
    text = StringProperty('')
    index = NumericProperty(-1)
    cb_state = StringProperty('normal')

    def __init__(self, **kwargs):
        super(CarouselSlide, self).__init__(**kwargs)
        self.bind(cb_state=self.set_cb_state)

    def set_cb_state(self, carouselslide, cb_state_value):
        self.ids.cb.state = cb_state_value

class RV(RecycleView):
    data = ListProperty('[]')

    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.get_slide_data()

    def get_slide_data(self):
        text="Ooh, a storm is threatening. My very life today. If I don't get some shelter. Ooh yeah I'm gonna fade away. War, children. It's just a shot away. It's just a shot away. War, children. It's just a shot away. It's just a shot away."
        self.data = [{'tile': 'The Rolling Stones', 'text': text, "index": i, "cb_state": 'normal'} for i in range(41)]

class ThisApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def build(self):
        self.sm = ScreenManager()
        self.sm.add_widget(CarouselScreen(name="carousel_screen"))
        return self.sm

    def on_checkbox_press(self, checkbox, active, state, root_ref):
        if active:
            print(active, state, root_ref)
        else:
            print(active, state, root_ref)

        new_state = checkbox.state
        checkbox.state = 'normal'

        rv = self.root.get_screen('carousel_screen').ids.rv
        rv.data[root_ref]['cb_state'] = new_state
        rv.refresh_from_data()

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

我认为问题在于您将 CheckBox 定义为 AsyncImage 的子项。 AsyncImage 不是一个容器。尝试取消缩进 kv 中的 CheckBox,并添加 size/position 属性:

<CarouselSlide>:
    BoxLayout:
        orientation: 'vertical'
        size_hint_y: 1
        AsyncImage:
            source: root.tile
            size_hint_y: 0.5
        CheckBox:
            id: cb
            size_hint: None, None
            size: 48, 48
            pos_hint: {'center_x':0.5}
            root_ref: root.index
            on_press: app.on_checkbox_press(self, self.active, self.state, self.root_ref)
        TextInput:
            text: root.text
            size_hint_y: 0.5
            multiline: True