忽略滚动视图中用于滚动交互的区域

2024-06-16 11:25:54 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个改编自ScrollView示例的UI:

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的交互延迟。是否可以定义ScrollView中的区域,其中touch事件直接传递给子对象而不延迟(也不启动滚动)?在


Tags: fromimportnoneaddappsizewidgetslider
2条回答

看看Widget touch event bubbling。在

我从来没有做过与您相同的事情,但也许您可以创建一个自定义类,继承ScrollView并重写{}事件,您可以:

  1. 禁用滚动
  2. 呼叫super.on_touch_down
  3. 启用滚动。在

另一种方法可能是创建一个自定义小部件,它继承用户单击的Slider类。然后用return True重载它的on_touch_down方法。Documentation says

In order to stop this event bubbling, one of these methods must return True

ScrollView也会触发on_scroll_start事件,所以也许你可以在那里做类似的事情。在

我想出了一个简单的覆盖ScrollView的{},目前看来它满足了我的需求。这样做的目的是测试触摸事件是否属于“排除区域”(在下面的示例中,只检查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)

相关问题 更多 >