1. 秦子帅的博客首页
  2. Flutter

Flutter-触摸

作者 |  前行的乌龟
地址 |  juejin.im/post/5dcea24ff265da0bd05e5236

前言

Flutter 的触摸原理和 android 一样,但是再使用上有很大区别,Flutter 比 android 好用多了,android 里我们要写个类继承目标 view 重写 onTouchEvent 方法,这样我们会多写一个类,这个类只是重新定义了触摸事件的处理方法而已,其实得不偿失,还会造成类爆炸,不方便理解的问题

Flutter 中一切都是 Widget,触摸事件也是一个 Widget:GestureDetector,我们只要用 GestureDetector 包裹内容 Widget 就行了,不需要我们单独搞一个类出来,方便阅读,方便理解,也方便编写,是编程语言发展的趋势

GestureDetector方法大全

GestureDetector 的构造函数中有很多方法,我们用不上,只用那么常用的就行,下面的这样监听函数大家看一下就行了

class GestureDetector extends StatelessWidget {
GestureDetector({
Key key,
this.child,
this.onTapDown,
this.onTapUp,
this.onTap,
this.onTapCancel,
this.onDoubleTap,
this.onLongPress,
this.onLongPressUp,
this.onLongPressDragStart,
this.onLongPressDragUpdate,
this.onLongPressDragUp,
this.onVerticalDragDown,
this.onVerticalDragStart,
this.onVerticalDragUpdate,
this.onVerticalDragEnd,
this.onVerticalDragCancel,
this.onHorizontalDragDown,
this.onHorizontalDragStart,
this.onHorizontalDragUpdate,
this.onHorizontalDragEnd,
this.onHorizontalDragCancel,
this.onForcePressStart,
this.onForcePressPeak,
this.onForcePressUpdate,
this.onForcePressEnd,
this.onPanDown,
this.onPanStart,
this.onPanUpdate,
this.onPanEnd,
this.onPanCancel,
this.onScaleStart,
this.onScaleUpdate,
this.onScaleEnd,
this.behavior,
this.excludeFromSemantics = false,
this.dragStartBehavior = DragStartBehavior.down,
})

}

监听单击,双击,长按

这是最常用的触摸处理了:

  • onTap – 单击
  • onDoubleTap – 双击
  • onLongPress – 长按
注意: 像是 双击,长按 这样的处理不可能像 单击 那样立马就响应的,而是有 200ms 的延迟,因为要在 200ms 内判断您是不是一直按着或者又按了一下
Widget build(BuildContext context) {
return RaisedButton(
child: Center(
child: GestureDetector(
child: Container(
alignment: Alignment.center,
color: Colors.blue,
width: 200.0,
height: 100.0,
child: Text(
value,
style: TextStyle(color: Colors.white),
),
),
onTap: () => print(“点击”), //点击
onDoubleTap: () => print(“双击”), //双击
onLongPress: () => print(“长安”), //长按
),
),
);
}

获取触摸数值

上面的监听方法是用来处理一般事件的,下面的方法我们可以直接拿到数值,并且 Flutter 初步给我们整理好了,划分了数值类型
  • onPanDown – 用户按下时触发,数据类型:DragDownDetails.globalPosition 是触摸点相对于屏幕的坐标,看名字有 global 就知道了
onPanDown: (DragDownDetails e) {
// 手指按下的位置(相对于屏幕)
print(“用户手指按下:${e.globalPosition}”);
},
  • onPanUpdate – 用户在屏幕上滑动时触发,数据类型:DragUpdateDetails.delta 其数值是用户一次触摸的偏移量,注意不是总的偏移量,是每一次的
onPanUpdate: (DragUpdateDetails e) {
//用户手指滑动时,更新偏移,重新构建
print(“单次偏移量:${e.delta.dx} :${e.delta.dy} “);
},
  • onPanEnd – 户抬起手指时触发,数据类型:DragEndDetails.velocity.pixelsPerSecond 其数据是用户手离开时 view 残留的滑动速度(包含x、y两个轴的)
 
onPanEnd: (DragEndDetails e){
//打印滑动结束时在x、y轴上的速度
print(e.velocity.pixelsPerSecond.dx,e.velocity.pixelsPerSecond.dy);
},
  • onVerticalDragUpdate – 垂直方面上手指触摸的变化值,数据类型:DragUpdateDetails
onVerticalDragUpdate: (DragUpdateDetails e){
……
},
  • onHorizontalDragUpdate – 水平方面上手指触摸的变化值,数据类型:DragUpdateDetails
onHorizontalDragUpdate: (DragUpdateDetails e){
……
},

第一个例子

这里我们搞一个拖动 widget 的小 demo
Flutter - 触摸
class TestWidgetState extends State<TestWidget> {
num top = 0.0;
num left = 0.0;

@override
Widget build(BuildContext context){
return Stack(
children: <Widget>[
Positioned(
top: top,
left: left,
child: GestureDetector(
child: Container(
alignment: Alignment.center,
color: Colors.blue,
width: 100.0,
height: 100.0,
child: Text(
“AAAAAAAA”,
style: TextStyle(color: Colors.white),
),
),
onPanUpdate: (DragUpdateDetails e) {
setState(() {
left += e.delta.dx;
top += e.delta.dy;
});
},
),
),
],
);
}

}

废话不多说,我们使用 stack 这个布局来做,利用 top,left 定位来改变 widget 的位置

缩放

  • onScaleUpdate – 数据类型:ScaleUpdateDetails,缩放值是:details.scale.clamp,clamp 方法中的参数是缩放范围,实测貌似不管用,不知道是不是我这的原因
 
onScaleUpdate: (ScaleUpdateDetails details) {
setState(() {
//缩放倍数在0.8到10倍之间
_width=200*details.scale.clamp(.8, 10.0);
});
我是不知道打击缩放都是怎么做的,我自己跑了个例子,我写的这个那手感是烂的一B啊
Flutter - 触摸
class TestWidgetState extends State<TestWidget> {
var width = 150.0;
var height = 150.0;

@override
Widget build(BuildContext context) {
return Center(
child: (GestureDetector(
child: Container(
alignment: Alignment.center,
color: Colors.blue,
width: width,
height: height,
child: Text(
“AAAAAAAA”,
style: TextStyle(color: Colors.white),
),
),
onScaleUpdate: (ScaleUpdateDetails details) {
setState(() {
if ((width *= details.scale.clamp(0.5, 1.5)) > 300) width = 200;
if ((width *= details.scale.clamp(0.5, 1.5)) < 50) width = 100;
if ((height *= details.scale.clamp(0.5, 1.5)) > 300) height = 200;
if ((height *= details.scale.clamp(0.5, 1.5)) < 50) height = 100;
print(“scale: ${details.scale.clamp}”);
});
},
)),
);
}

后来想了想手感烂应该是我没加系数进去,我试了下,加入了系数,系数=0.1,但是感觉还是没啥用…
—END—
Flutter - 触摸

发布者:秦子帅,转转请注明出处:http://qinzishuai.cn/7054/85a442e772/