本文档介绍了如何在Flutter中监听并响应手势(点击、拖动和缩放)。
Flutter中的手势系统有两个独立的层。第一层有原始指针(pointer)事件,它描述了屏幕上指针(例如,触摸,鼠标和触控笔)的位置和移动。 第二层有手势,描述由一个或多个指针移动组成的语义动作。
指针(Pointer)代表用户与设备屏幕交互的原始数据。有四种类型的指针事
在指针按下时,框架对您的应用程序执行_命中测试_,以确定指针与屏幕相接的位置存在哪些widget。 指针按下事件(以及该指针的后续事件)然后被分发到由_命中测试_发现的最内部的widget。 从那里开始,这些事件会冒泡在widget树中向上冒泡,这些事件会从最内部的widget被分发到到widget根的路径上的所有小部件(译者语:这和web中事件冒泡机制相似), 没有机制取消或停止冒泡过程(译者语:这和web不同,web中的时间冒泡是可以停止的)。
To listen to pointer events directly from the widgets layer, use a Listener widget. However, generally, consider using gestures (as discussed below) instead. 要直接从widget层监听指针事件,可以使用Listenerwidget。 但是,通常,请考虑使用手势(如下所述)
手势表示可以从多个单独的指针事件(甚至可能是多个单独的指针)识别的语义动作(例如,轻敲,拖动和缩放)。 完整的一个手势可以分派多个事件,对应于手势的生命周期(例如,拖动开始,拖动更新和拖动结束):
要从widget层监听手势,请使用 GestureDetector.
如果您使用的是Material Components,那么大多数widget已经对tap或手势做出了响应。 例如 IconButton和 FlatButton 响应presses(taps),ListView响应滑动事件触发滚动。 如果您不使用这些widget,但想要在点击时上出现“墨水飞溅”效果,可以使用InkWell。
在屏幕上的指定位置,可能会有多个手势检测器。所有这些手势检测器在指针事件流经过并尝试识别特定手势时监听指针事件流。 GestureDetector widget决定是哪种手势。
当屏幕上给定指针有多个手势识别器时,框架通过让每个识别器加入一个“手势竞争场”来确定用户想要的手势。“手势竞争场”使用以下规则确定哪个手势胜出
例如,在消除水平和垂直拖动的歧义时,两个识别器在接收到指针向下事件时进入“手势竞争场”。识别器观察指针移动事件。 如果用户将指针水平移动超过一定数量的逻辑像素,则水平识别器将声明胜利,并且手势将被解释为水平拖拽。 类似地,如果用户垂直移动超过一定数量的逻辑像素,垂直识别器将宣布胜利。
当只有水平(或垂直)拖动识别器时,“手势竞争场”是有益的。在这种情况下,“手势竞争场”将只有一个识别器,并且水平拖动将被立即识别,这意味着水平移动的第一个像素可以被视为拖动,用户不需要等待进一步的手势消歧。