Python kivy:嵌套滚动视图

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

我在垂直滚动视图中有一个嵌套的水平滚动视图,我跟踪了很多链接,什么也没找到,我需要一个清晰的滚动视图,这样如果我滚动嵌套的水平滚动视图,它将滚动而不会干扰父垂直滚动视图,如果我滚动垂直嵌套水平滚动视图,则只有父垂直滚动视图才会滚动!有什么建议 ?提前致谢! (我希望滚动视图与任何其他现代应用程序相同,例如 facebook 故事水平滚动视图等..)

python kivy nestedscrollview
3个回答
0
投票

这就是您实现您所寻求的目标的方法。

使用 KivyMD 为您的应用程序获取材料设计。 https://kivymd.readthedocs.io/en/latest/index.html

那就试试这个吧

scrollview.py

from kivymd.app import MDApp
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window

class MyScrollView(ScrollView):
    def on_touch_down(self, touch):
        # get touch position in coordinates of the main_box (parent of inner_scroll)
        x,y = self.ids.main_box.to_widget(*self.to_window(*touch.pos))

        # if converted position is within the inner_scroll, send touch to the inner_scroll
        if self.ids.inner_scroll.collide_point(x,y):
            touch.pos = (x,y)   # change touch position to coordinates in main_box
            return self.ids.inner_scroll.on_touch_down(touch)   # call on_touch of inner_scroll
        else:
            return super(MyScrollView, self).on_touch_down(touch)

class ScrolltwoApp(MDApp):
    
    def build(self):
        app=MDApp.get_running_app()
        Clock.schedule_once(self.add_members)
        return app.root
    
    def add_members(self,dt):
        app=MDApp.get_running_app()
        for i in range(15):
            app.root.ids.main_box.add_widget(Button(text='button'+str(i), size_hint=(1.0, None), height=50,background_color=[0,0,1,1]))
            app.root.ids.horizontal_grid.add_widget(Button(text='button' + str(i), size_hint=(None, None),height=130,width=100,background_color=[0,0,1,1]))
            app.root.ids.horizontal_grid2.add_widget(Button(text='button' + str(i), size_hint=(None, None),height=130,width=100,background_color=[0,0,1,1]))

if __name__ == '__main__':
    Window.show_cursor = True
    Window.size = (360, 680)
    ScrolltwoApp().run()

scrolltwo.kv

#: import Window kivy.core.window.Window
MyScrollView:
    bar_width: 5
    scroll_type:['bars', 'content']
    do_scroll: (False, True)
    size_hint_y: None
    height: Window.height
    GridLayout:
        id: main_box
        size_hint_y: None
        cols: 1
        height: self.minimum_height
        ScrollView:
            id: inner_scroll
            bar_width: 5
            scroll_type: ['bars', 'content']
            do_scroll: (True, False)
            size_hint_y: None
            effect_cls: "ScrollEffect"
            height: Window.height/4.5
            GridLayout:
                id: horizontal_grid
                rows: 1
                padding: [10, 10]
                size: self.minimum_size
                size_hint: None, None
        ScrollView:
            id: inner_scroll2
            bar_width: 5
            scroll_type: ['bars', 'content']
            do_scroll: (True, False)
            size_hint_y: None
            effect_cls: "ScrollEffect"
            height: Window.height/4.5
            GridLayout:
                id: horizontal_grid2
                rows: 1
                padding: [10, 10]
                size: self.minimum_size
                size_hint: None, None

输出

enter image description here


0
投票

我理解你,并且在尝试垂直滚动水平滚动视图时遇到了同样的问题,它应该滚动垂直父滚动视图。

我查看了scrollview的源代码,发现子scrollview在收到touchmove时停止向父级传播移动事件。

这是解决方案的演示(一些技巧),它允许您垂直滚动水平滚动视图,从而影响父滚动视图。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty

KV = """
<SomeText>
    id: some_text
    orientation: 'horizontal'
    ScrollText:
        Label:
            text: some_text.text
            max_lines: 1
            halign: 'left'
            padding_x: 20
            font_size: some_text.height
            width: self.texture_size[0]
            size_hint_x: None


<ScrollText>
    bar_color: (1,1,1,1)
    bar_width: 1

<VerticalScroll>
    some_text_list: some_text_list
    GridLayout:
        id: some_text_list
        cols: 1
        size_hint_y: None
        row_default_height: 80
        row_force_default: True
        height: self.minimum_height
"""

class SomeText(BoxLayout):
    text = StringProperty()
    

class ScrollText(ScrollView):
    # pass y-move event to parent instead of stopping
    def on_scroll_move(self, touch):
        super().on_scroll_move(touch)
        touch.ud['sv.handled']['y'] = False 

class VerticalScroll(ScrollView):
    def __init__(self, texts, **kwargs):
        super().__init__(**kwargs)
        for text in texts:
            self.some_text_list.add_widget(SomeText(text=text))

    # prevent stuck on overscroll
    def on_scroll_stop(self, touch, check_children=True):
        super().on_scroll_stop(touch, check_children=False)

if __name__ == "__main__":
    class TestApp(App):
        def build(self):
            Builder.load_string(KV)
            long_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
            texts = [long_text for _ in range(20)]
            return VerticalScroll(texts)
    TestApp().run()


0
投票

这是我的解决方法,所以我修改了 InnerScrollView 的 on_scroll_move 并检查 collide_point 然后比较 touch.dy 和 touch.dx 的绝对值以了解您是垂直滚动还是水平滚动如果您垂直滚动将 svavoid 设置为true 并返回 false,否则只需运行正常的 on_scroll_move。

`类 InnerScrollView(RecycleView):

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

def on_scroll_move(self, touch):
    if self.collide_point(touch.x,touch.y):
        # Vertical scrolling
        if abs(touch.dy) > abs(touch.dx):
            touch.ud[self._get_uid('svavoid')] = True
            return False
        # Horizontal scrolling
        else:
            return super(InnerScrollView, self).on_scroll_move(touch)`
© www.soinside.com 2019 - 2024. All rights reserved.