在Flutter中使用GestureDetector可以来完成对手势的识别,包括长按、滑动、双击等手势。
一、GestureDetector中的手势
下表是对GestureDetector中所有手势的说明。
事件名 | 说明 |
---|---|
onTapDown | 手指开始触摸屏幕触发 |
onTapUp | 手指从屏幕抬起触发 |
onTap | 一次完成的单击事件结束后触发,onTapUp之后触发 |
onTapCancel | 触摸屏幕后,未完成触摸动作,即未抬起手指可触发,如长按方可触发改事件 |
onSecondaryTapDown | |
onSecondaryTapUp | |
onSecondaryTapCancel | |
onDoubleTap | 短时间内触发屏幕两次触发 |
onLongPress | 长按触发 |
onLongPressStart | 长按开始时触发 |
onLongPressMoveUpdate | 长按时手指移动触发 |
onLongPressUp | 长按结束时触发 |
onLongPressEnd | 长按结束时触发,在onLongPressUp之前触发 |
onVerticalDragDown | 手指按下并在垂直方向上移动时触发 |
onVerticalDragStart | 当触摸点开始在垂直方向上移动时触发,在onVerticalDragDown之后触发 |
onVerticalDragUpdate | 触摸点在垂直方向上位置每发生改变就会触发 |
onVerticalDragEnd | 手指离开屏幕后方可触发 |
onVerticalDragCancel | 用户突然停止拖拽时触发 |
onHorizontalDragDown | 同onVerticalDragDown,水平方向 |
onHorizontalDragStart | 同onVerticalDragStart,水平方向 |
onHorizontalDragUpdate | 同onVerticalDragUpdate,水平方向 |
onHorizontalDragEnd | 同onVerticalDragEnd,水平方向 |
onHorizontalDragCancel | 同onVerticalDragCancel |
onForcePressStart | |
onForcePressPeak | |
onForcePressUpdate | |
onForcePressEnd | |
onPanDown | |
onPanStart | 同onVerticalDragStart,任意方向 |
onPanUpdate | 同onVerticalDragUpdate,任意方向 |
onPanEnd | 同onVerticalDragEnd,任意方向 |
onPanCancel | 同onVerticalDragCancel |
onScaleStart | 双指开始捏合时触发 |
onScaleUpdate | 双指捏合缩放触发 |
onScaleEnd | 双指结束结合后触发 |
二、拖动
拖动示例
class DragWidget extends StatefulWidget{
@override
_DragWidgetState createState() {
// TODO: implement createState
return _DragWidgetState();
}
}
class _DragWidgetState extends State<DragWidget> {
GlobalKey stackKey = GlobalKey();
GlobalKey btnKey = GlobalKey();
double _left = 0.0;
double _top = 0.0;
double _areaWidth = 0.0;
double _areaHeight = 0.0;
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((duration) {
setState(() {
_areaWidth = stackKey.currentContext.size.width - btnKey.currentContext.size.width;
_areaHeight = stackKey.currentContext.size.height - btnKey.currentContext.size.height;
});
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Stack(
key: stackKey,
children: <Widget>[
Positioned(
top: _top,
left: _left,
child: GestureDetector(
child: FloatingActionButton(
key: btnKey,
child: Text('drag'),
),
onPanUpdate: (e) {
setState(() {
_left += e.delta.dx;
_top += e.delta.dy;
if (_left < 0) {
_left = 0;
} else if (_left > _areaWidth) {
_left = _areaWidth;
}
if (_top < 0) {
_top = 0;
} else if (_top > _areaHeight) {
_top = _areaHeight;
}
});
},
)
)
],
);
}
}
效果展示
将onPanUpdate改为onVerticalDragUpdate即可变为只能在竖直方向上拖动,onHorizontalDragUpdate同理。
三、缩放
class ScaleWidget extends StatefulWidget{
@override
_ScaleWidgetState createState() {
// TODO: implement createState
return _ScaleWidgetState();
}
}
class _ScaleWidgetState extends State<ScaleWidget>{
double _width = 300.0;
double _height = 200.0;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: GestureDetector(
child: Container(
constraints: BoxConstraints.tight(Size(_width, _height)),
color: Colors.blue,
),
onScaleUpdate: (e) {
print(e);
setState(() {
// 限制宽度缩放比例在0.7-1.2之间,如果超过这个范围,Container会变为原来的大小
_width = 300* e.scale.clamp(0.7, 1.2);
_height = 200*e.scale.clamp(0.7, 1.2);
});
},
)
);
}
}