欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

40 Flutter Gesture手势处理

程序员文章站 2024-03-24 14:56:52
...

Flutter Gesture手势处理

1.简介

GestureDetector在Flutter中负责处理跟用户的简单手势交互,GestureDetector控件没有图像展示,只是检测用户输入的手势,并作出相应的处理,包括点击、拖动和缩放。许多控件使用GestureDetector为其他控件提供回调,比如IconButton、RaisedButton和FloatingActionButton控件有onPressed回调,当用户点击控件时触发回调,当用户点击控件时触发回调。
我们来一起看下GestureDetector的构造方法:

2.属性

 GestureDetector({
    Key? key,
    this.child,
    this.onTapDown,   //单击 down
    this.onTapUp,	//单击 up
    this.onTap,	   //点击
    this.onTapCancel,
    this.onSecondaryTap,
    this.onSecondaryTapDown,
    this.onSecondaryTapUp,
    this.onSecondaryTapCancel,
    this.onTertiaryTapDown,
    this.onTertiaryTapUp,
    this.onTertiaryTapCancel,
    this.onDoubleTapDown,
    this.onDoubleTap,  //双击
    this.onDoubleTapCancel,
    this.onLongPress, //长安
    this.onLongPressStart, 
    this.onLongPressMoveUpdate,
    this.onLongPressUp, 
    this.onLongPressEnd,
    this.onSecondaryLongPress,
    this.onSecondaryLongPressStart,
    this.onSecondaryLongPressMoveUpdate,
    this.onSecondaryLongPressUp,
    this.onSecondaryLongPressEnd,
    this.onVerticalDragDown, //drag–拖拽事件
    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.start,
  })

3.属性分类介绍

属性介绍

GestureWidget除key以外有39个属性,但大部分是成组出现的。大致分为以下几组:child、tap、longPress、drag、forcePress、pan、scale、behavior以及excludeFromSemantics,下边列出了其中比较常用的几个。

tap–点击事件

不同于Android中通过View.SetOnClickListener()来给组件添加点击事件,Flutter中绝大多数的组件是不能响应点击事件的。通常做法是在目标Widget外层包裹一个GestureDetector,这也就是child属性的作用,GestureDetector的大小等于子Widget的大小,也就是触控区域的大小。

onTap() :发生点击。
onDoubleTap():双击。
onTapCancel():手指离开屏幕时,触控位置不在GestureDetector范围内。
onTapDown(TapXXXDetails) :手指落在触控范围内时的回调,details参数中包含触控点的全局位置(相对于屏幕左上角)和本地位置(相对于触控区左上角)。
onTapUp(TapXXXDetails):同上。

longPress–长按事件
onLongPress() :手指在触控区停留一段时间,检测出长按(不用放手)。
onLongPressStart(LongPressXXXDetails):同上,获得检测到长按时的触控点坐标(Global和Local)。
onLongPressMoveUpdate(LongPressXXXDetails):检测到长按,手指在屏幕内(而非仅仅在触控区域内),得到触控点坐标。
onLongPressUp() :检测到长按,手指离开屏幕时。
onLongPressEnd(LongPressXXXDetails):同上,获得该点坐标。

drag–拖拽事件
onVerticalDragDown(DragDownDetails) :实际上不用拖拽,当手指接触触控区,就会产生该回调,获得该点坐标。
onVerticalDragStart(DragStartDetails):开始拖拽,details不仅包含该点坐标,而且记录了开始拖拽的时间戳。
onVerticalDragUpdate(DragUpdateDetails):纵向拖拽过程中,参数不仅包含该点坐标,且记录了当前时间戳。可以与startDrag的时间戳联合使用。
onVerticalDragEnd(DragEndDetails) :产生纵向拖拽,手指离开屏幕,获得该点坐标。
onVerticalDragCancel():点击了触控区但没有产生拖拽,或者横向拖拽至触控区外。
Horizontal横向,略。

forcePress–压感检测
哇咔咔,GestureDetector这么厉害,居然支持压力检测。
这里的压力是没有单位的,默认范围是startPressure0.0-peakPressure1.0代表从没有压力到最大压力。
onForcePressStart(ForcePressDetails) :触碰屏幕且有一定压力,压力值大于startPressure,获得压力值和触控点坐标。
onForcePressPeak(ForcePressDetails):触屏屏幕的压力大于peakPreasure,获得压力值和触控点坐标。
onForcePressUpdate(ForcePressDetails):已经被检测到产生压力的情况下,在屏幕上滑动,或者在原地改变压力大小,亦或是两者都有。同时获得压力值和触控点坐标。
onForcePressEnd(ForcePressDetails) :已检测到产生压力的情况下,手指离开屏幕。
然而,在所有的压力检测回调中都有这样一则注释:

/// Note that this callback will only be fired on 
final GestureForcePressEndCallback onForcePressEnd;

也就是说,只有在具有压感屏的设备上,这些API才起作用。

pan-综合横向与纵向拖拽的拖拽事件 ————————类似于Android 中onTouch
onPanDown(DragDownDetails) :手指与屏幕接触时,获得该点坐标。 down
onPanStart(DragStartDetails):手指开始在屏幕上移动。 down
onPanCancel():
取消拖拽,暂未回调到该方法。
onPanEnd(DragEndDetails) :产生拖拽,手指离开屏幕,获得该点坐标。
onPanUpdate(DragUpdateDetails):在出发onPanDown的前提下,手指在屏幕上滑动,获得触控点坐标。

——————onPanUpdate,记录移动的过程

4.使用

1 widget 添加单击事件

Widget buildOnTab() {
   return Padding(
     padding: EdgeInsets.all(10),
     child: GestureDetector(
       onTap: () {
         print("");
       },
       child: Container(
         alignment: Alignment(0, 0),
         color: Colors.grey,
         height: 28,
         width: 120,
         child: Text(""),
       ),
     ),
   );
 }

2 widget 添加长按事件

Widget buildLongTab() {
   return Padding(
     padding: EdgeInsets.all(10),
     child: GestureDetector(
       onLongPress: () {
         print("长按事件 ");
       },
       child: Container(
         alignment: Alignment(0, 0),
         color: Colors.grey,
         height: 28,
         width: 120,
         child: Text("长按事件"),
       ),
     ),
   );
 }

3 widget 添加双击事件

 Widget buildDoTab() {
   return Padding(
     padding: EdgeInsets.all(10),
     child: GestureDetector(
       onDoubleTap: () {
         print("双击事件 ");
       },
       child: Container(
         alignment: Alignment(0, 0),
         color: Colors.grey,
         height: 28,
         width: 120,
         child: Text("双击事件"),
       ),
     ),
   );
 }

4 widget 添加按下与抬起监听事件

Widget buildDownUp() {
   return Padding(
     padding: EdgeInsets.all(10),
     child: GestureDetector(
       onTapDown: (tapDown) {
         print("按下 ");
       },
       onTapUp: (tapUp) {
         print("抬起 ");
       },
       child: Container(
         alignment: Alignment(0, 0),
         color: Colors.grey,
         height: 28,
         width: 120,
         child: Text("监听按下与放开"),
       ),
     ),
   );
 }

5.移动监听,实现Android中onTouchEvent的功能

        onPanDown: (details) {
          print("onPanDown:" + details.globalPosition.toString());
        },
        onPanUpdate: (details) {
          print("onPanUpdate:" + details.globalPosition.toString());
        },

5.使用inWell实现添加事件监听

使用 InkWell 同样可以实现 GestureDetector的添加事件监听功能,两者的区别是GestureDetector的child 点击无水波纹效果,而 InkWell 的child 触发事件时会有水波纹效果。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text("flutter demo")), body: InWellDemo()));
  }
}

class InWellDemo extends StatefulWidget {
  InWellDemo({Key key}) : super(key: key);

  @override
  _InWellDemoState createState() {
    return _InWellDemoState();
  }
}

class _InWellDemoState extends State<InWellDemo> {
  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Padding(
      padding: EdgeInsets.all(10),
      child: InkWell(
        onTap: () {
          print("InkWell单击事件 ");
        },
        highlightColor: Colors.yellow, //长按时,高亮颜色
        splashColor: Colors.green,  //单击时,颜色
        child: Container(
          alignment: Alignment(0, 0),
          color: Colors.white54,
          height: 50,
          width: 200,
          child: Text("InkWell单击事件"),
        ),
      ),
    );
  }
}

6.代码示例

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(home: new MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Gestures"),
      ),
      body: new Center(
          child: new GestureDetector(
        child: Padding(
          padding: EdgeInsets.all(10),
          child: GestureDetector(
            onTap: () {
              print("单击事件 ");
            },
            child: Container(
              alignment: Alignment(0, 0),
              color: Colors.grey,
              height: 50,
              width: 120,
              child: Text("单击事件"),
            ),
          ),
        ),
        onTap: () {
          print("------onTap");
        },
        onTapDown: (tapDown) {
          print("按下 ");
        },
        onTapUp: (tapUp) {
          print("------onTap");
        },
        onDoubleTap: () {
          print("------onDoubleTap");
        },
        onLongPress: () {
          print("-----onLongPress");
        },
        onVerticalDragStart: (details) {
          print("在垂直方向开始位置:" + details.globalPosition.toString());
        },
        onVerticalDragDown: (details) {
          print("在垂直向下压的位置" + details.globalPosition.toString());
        },
        onVerticalDragEnd: (details) {
          print("在垂直方向结束位置:" + details.primaryVelocity.toString());
        },
        onPanDown: (details) {
          print("onPanDown:" + details.globalPosition.toString());
        },
        onPanUpdate: (details) {
          print("onPanUpdate:" + details.globalPosition.toString());
        },
      )),
    );
  }
}

相关标签: Flutter flutter