忽略 ScrollView 中用于滚动交互的区域
Posted
技术标签:
【中文标题】忽略 ScrollView 中用于滚动交互的区域【英文标题】:Ignore area in ScrollView for scrolling interactions 【发布时间】:2016-06-13 03:04:46 【问题描述】:假设我的 UI 改编自 ScrollView
示例:
from kivy.app import App
from kivy.uix.slider import Slider
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
class ScrollViewApp(App):
def build(self):
layout = GridLayout(cols=1, padding=10, spacing=10,
size_hint=(None, None), width=500)
layout.bind(minimum_height=layout.setter('height'))
for i in range(15):
blt = BoxLayout(size_hint=(None, None), size=(480, 40))
blt.add_widget(Label(text="Slider %d" % i))
btn = Slider(value=i, min=0, max=42, size=(400, 40),
size_hint=(None, None))
blt.add_widget(btn)
layout.add_widget(blt)
scroll = ScrollView(size_hint=(None, None), size=(500, 320),
pos_hint='center_x': .5, 'center_y': .5, do_scroll_x=False)
scroll.add_widget(layout)
return scroll
if __name__ == '__main__':
ScrollViewApp().run()
由于scroll_timeout
,与Slider
s 的交互被延迟。是否可以在 ScrollView
中定义区域,其中 touch
事件只是无延迟(并且不启动滚动)传递给子级?
【问题讨论】:
等待船长 一年前我想要类似的东西,但没有成功。我认为这甚至可能无法实施。但为了确定起见,请在 irc 上询问。 @KeyWeeUsr 在下面看到我的答案,这似乎对我有用 【参考方案1】:看看Widget touch event bubbling。
我从来不需要和你做同样的事情,但也许你可以创建一个自定义类来继承 ScrollView
并在你可以覆盖的地方覆盖 on_touch_down
事件:
-
禁用滚动
致电
super.on_touch_down
启用滚动。
另一种方法可能是创建一个自定义小部件,该小部件继承用户单击的 Slider
类。然后用return True
重载它的on_touch_down
方法。 Documentation says:
为了阻止此事件冒泡,这些方法之一必须返回 True
ScrollView
也会触发 on_scroll_start
事件,所以也许你可以在那里做类似的事情。
【讨论】:
感谢您的回答,@Martin。我知道我必须篡改on_touch_down
,但不太清楚怎么做。好像我找到了一种方法(与您的建议不同)。【参考方案2】:
我想出了一个简单的覆盖ScrollView
的on_touch_down
,到目前为止似乎满足了我的需求。这个想法是测试触摸事件是否落入“排除区域”(在下面的示例中,仅检查 x 维度,但将其扩展到任意矩形区域是微不足道的)。如果它确实落入该禁区,on_touch_down
事件将被分派给ScrollView
的孩子。如果一个孩子抓住了它,这个事件就被吞没了。在所有其他情况下,将调用super.on_touch_down
,即启动正常的滚动行为。如果触摸没有落在Slider
上(在问题的示例中),这样做的好处是仍然能够滚动。
class MSV(ScrollView):
x_exclusion_lower = NumericProperty(None, allownone=True)
x_exclusion_upper = NumericProperty(None, allownone=True)
x_exclusion = ReferenceListProperty(x_exclusion_lower, x_exclusion_upper)
def on_touch_down(self, touch):
pos_in_sv = self.to_local(*touch.pos)
if (self.x_exclusion_lower is not None or self.x_exclusion_upper is not None) and (self.x_exclusion_lower is None or self.x_exclusion_lower <= pos_in_sv[0]) and \
(self.x_exclusion_upper is None or self.x_exclusion_upper >= pos_in_sv[0]):
touch.push()
touch.apply_transform_2d(self.to_local)
if self.dispatch_children('on_touch_down', touch):
return True
touch.pop()
super(MSV, self).on_touch_down(touch)
【讨论】:
以上是关于忽略 ScrollView 中用于滚动交互的区域的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView 可滚动区域未随 scrollView 框架约束更新而更新
UIColectionView Vertical Scrolling inside a Scrollview - 在集合视图区域中滚动时禁用滚动视图的滚动