我在垂直滚动视图中有一个嵌套的水平滚动视图,我跟踪了很多链接,什么也没找到,我需要一个清晰的滚动视图,这样如果我滚动嵌套的水平滚动视图,它将滚动而不会干扰父垂直滚动视图,如果我滚动垂直嵌套水平滚动视图,则只有父垂直滚动视图才会滚动!有什么建议 ?提前致谢! (我希望滚动视图与任何其他现代应用程序相同,例如 facebook 故事水平滚动视图等..)
这就是您实现您所寻求的目标的方法。
使用 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
输出
我理解你,并且在尝试垂直滚动水平滚动视图时遇到了同样的问题,它应该滚动垂直父滚动视图。
我查看了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()
这是我的解决方法,所以我修改了 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)`