• Flutter:手势识别组件


    前言

    参考:老孟Flutter教程

    GestureDetector

    GestureDetector 是手势识别的组件,可以识别点击、双击、长按事件、拖动、缩放等手势

    点击事件

    点击相关事件包括:

    • onTapDown:按下时回调。
    • onTapUp:抬起时回调。
    • onTap:点击事件回调。
    • onTapCancel:点击取消事件回调。

    按下然后抬起调用顺序

    onTapDown-> onTapUp-> onTap
    
    • 1

    按下后移动调用顺序

    onTapDown-> onTapCancel
    
    • 1

    示例

    class _YcHomeBodyState extends State<YcHomeBody> {
      String desc = '';
      Color containerColor = Colors.red;
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          child: Column(
            children: [
              Container(
                width: 420,
                height: 330,
                color: containerColor,
              ),
              const SizedBox(
                width: 100,
                height: 20,
              ),
              Text("点击事件:$desc")
            ],
          ),
          onTapDown: (TapDownDetails tapDownDetails) {
            setState(() {
              desc += '按下,';
              containerColor = Colors.blue;
            });
          },
          onTapUp: (TapUpDetails tapUpDetails) {
            setState(() {
              desc += '抬起,';
              containerColor = Colors.red;
            });
          },
          onTap: () {
            setState(() {
              desc += '点击,';
              containerColor = Colors.yellow;
            });
          },
          onTapCancel: () {
            setState(() {
              desc += '取消,';
              containerColor = Colors.pink;
            });
          },
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述

    双击事件

    双击是快速且连续2次在同一个位置点击,双击监听使用onDoubleTap方法

    return GestureDetector(
      child: Column(
        children: [
          Container(
            width: 420,
            height: 330,
            color: containerColor,
          ),
          const SizedBox(
            width: 100,
            height: 20,
          ),
          Text("点击事件:$desc")
        ],
      ),
      onDoubleTap: () {
        setState(() {
          desc = '双击了';
        });
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    长按事件

    长按事件(LongPress)包含长按开始、移动、抬起、结束事件,说明如下:

    • onLongPressStart:长按开始事件回调。
    • onLongPressMoveUpdate:长按移动事件回调。
    • onLongPressUp:长按抬起事件回调。
    • onLongPressEnd:长按结束事件回调。
    • onLongPress:长按事件回调。

    示例

    return GestureDetector(
      child: Column(
        children: [
          Container(
            width: 420,
            height: 330,
            color: containerColor,
          ),
          const SizedBox(
            width: 100,
            height: 20,
          ),
          Text("点击事件:$desc")
        ],
      ),
      onLongPressStart: (v) {
        setState(() {
          desc += '长按开始,';
          print("长按开始:$v");
        });
      },
      onLongPressMoveUpdate: (v) {
        setState(() {
          desc += '长按移动,';
          print("长按移动:$v");
        });
      },
      onLongPressUp: () {
        setState(() {
          desc += '长按抬起,';
          print("长按抬起");
        });
      },
      onLongPressEnd: (v) {
        setState(() {
          desc += '长按结束,';
          print("长按结束:$v");
        });
      },
      onLongPress: () {
        setState(() {
          desc += '长按回调,';
          print("长按回调");
        });
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在这里插入图片描述
    执行顺序

    1、长按开始->回调->结束->抬起
    2、长按开始->回调->移动->结束->抬起
    
    • 1
    • 2

    水平/垂直拖动事件

    垂直/水平拖动事件包括按下、开始、移动更新、结束、取消事件,以垂直为例说明如下:

    • onVerticalDragDown:垂直拖动按下事件回调
    • onVerticalDragStart:垂直拖动开始事件回调
    • onVerticalDragUpdate:指针移动更新事件回调
    • onVerticalDragEnd:垂直拖动结束事件回调
    • onVerticalDragCancel:垂直拖动取消事件回调
    GestureDetector(
      onVerticalDragStart: (v) => print('onVerticalDragStart'),
      onVerticalDragDown: (v) => print('onVerticalDragDown'),
      onVerticalDragUpdate: (v) => print('onVerticalDragUpdate'),
      onVerticalDragCancel: () => print('onVerticalDragCancel'),
      onVerticalDragEnd: (v) => print('onVerticalDragEnd'),
      child: Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
        ),
      ),
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    缩放事件

    缩放(Scale)包含缩放开始、更新、结束。说明如下:

    • onScaleStart:缩放开始事件回调。
    • onScaleUpdate:缩放更新事件回调。
    • onScaleEnd:缩放结束事件回调。
    GestureDetector(
      onScaleStart: (v) => print('onScaleStart'),
      onScaleUpdate: (ScaleUpdateDetails v) => print('onScaleUpdate'),
      onScaleEnd: (v) => print('onScaleEnd'),
      child: Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
        ),
      ),
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    InkWell

    InkWell 组件在用户点击时出现“水波纹”效果。事件和属性挺多的,就看一下常用的

    设置水波纹颜色
    点击和长按都能够触发水波纹,点击波纹效果快,长按波纹效果慢

     return  InkWell(
          onTap: (){
            print("点击了");
          },
          splashColor: Colors.red,
          child: const Text('点击InkWell,水波纹'),
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    给字体添加边距和圆角边框,扩大“水波纹”效果:

    Center(
          child: InkWell(
              onTap: () {
                print("点击了");
              },
              splashColor: Colors.red,
              child: Container(
                  padding: const EdgeInsets.all(10),
                  decoration: BoxDecoration(
                      border: Border.all(color: Colors.red),
                      borderRadius: const BorderRadius.all(Radius.circular(20))),
                  child: const Text('点击InkWell,水波纹'))),
        );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    可以看到水波纹会超出圆角,为了解决这个问题可以使用Ink

    Ink

    Ink控件用于在[Material]控件上绘制图像和其他装饰,以便[InkWell]、[InkResponse]控件的“水波纹”效果在其上面显示。

      return Center(
            child: Ink(
          decoration: const BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [Color(0xFFDE2F21), Color(0xFFEC592F)]),
              borderRadius: BorderRadius.all(Radius.circular(20))),
          child: InkWell(
            borderRadius: const BorderRadius.all(Radius.circular(20)),
            child: Container(
              padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
              child: const Text(
                '这是InkWell的点击效果',
                style: TextStyle(color: Colors.white),
              ),
            ),
            onTap: () {},
          ),
        ));
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述
    总感觉有点复杂,InkWell 会导致水纹超出边框,就需要外面再套一层组件,然后还要写个渐变,不知道咋形容。

    Listener

    Listener 是一个监听指针事件的控件,比如按下、移动、释放、取消等指针事件,但Listener无法监听鼠标特有的事件,比如:移入、悬停、移出事件。鼠标事件使用MouseRegion监听。

    通常情况下,监听手势事件使用GestureDetector,GestureDetector是更高级的手势事件。

    Listener的事件介绍如下:

    • onPointerDown:按下时回调
    • onPointerMove:移动时回调
    • onPointerUp:抬起时回调
    Listener(
      onPointerDown: (PointerDownEvent pointerDownEvent) {
        print('$pointerDownEvent');
      },
      onPointerMove: (PointerMoveEvent pointerMoveEvent) {
        print('$pointerMoveEvent');
      },
      onPointerUp: (PointerUpEvent upEvent) {
        print('$upEvent');
      },
      child: Container(
        height: 200,
        width: 200,
        color: Colors.blue,
        alignment: Alignment.center,
      ),
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    常用属性说明如下:

    • position:相对屏幕的坐标的偏移。

    • localPosition:相对当前控件的偏移。

    • pressure:按压力度。

    • delta:2次指针移动事件的偏移。

    • orientation:指针移动方向

    案例

    进度按钮

    // 使用枚举定义按钮的状态
    enum ButtonStates { none, loading, done }
    
    class YcHomeBody extends StatefulWidget {
      const YcHomeBody({Key? key}) : super(key: key);
      @override
      State<YcHomeBody> createState() => _YcHomeBodyState();
    }
    
    class _YcHomeBodyState extends State<YcHomeBody> {
      //定义按钮的状态
      ButtonStates _buttonStates = ButtonStates.none;
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: MaterialButton(
            color: Colors.blue,
            textColor: Colors.white,
            minWidth: 200,
            height: 40,
            //通过自定义方法,根据情况返回相应的组件
            child: _build(),
            onPressed: () {
              //点击按钮后将按钮状态变为加载中
              setState(() {
                _buttonStates = ButtonStates.loading;
                //延迟2s后将状态变为完成
                Future.delayed(const Duration(seconds: 2), () {
                  setState(() {
                    _buttonStates = ButtonStates.done;
                  });
                });
              });
            },
          ),
        );
      }
    
      //自定义方法
      _build() {
        if (_buttonStates == ButtonStates.none) {
          //无状态
          return const Text("登录");
        } else if (_buttonStates == ButtonStates.loading) {
          //进度条组件
          return const CircularProgressIndicator(
            backgroundColor: Colors.white,
            strokeWidth: 2,
          );
        } else if (_buttonStates == ButtonStates.done) {
          return const Icon(
            Icons.check,
            color: Colors.white,
          );
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    代码看着很长但是逻辑很简单,定义了一个枚举类型的按钮类型。一开始类型为无状态,此时显示登录;当点击按钮后,状态变为加载中,显示圆形进度条组件;2s后将按钮状态变为加载完成,现成完成的图标

    在这里插入图片描述

  • 相关阅读:
    基于libmpv内核设计开发的视频播放器-高级版(四)
    SpringBoot + Redis + Token 解决接口幂等性问题
    用 ESP32 做了一个 AI Agent 桌面状态核心,科技感直接拉满
    iNeuOS工业互联网操作系统,增加2154个视图建模(WEB组态)行业矢量图元、大屏背景及相关图元
    【智能家居】
    计算机毕业设计之java+javaweb的面向学生成绩分析系统
    [附源码]计算机毕业设计JAVAjsp校外教育机构类网站
    谷粒学院 —— 10、课程管理:整合阿里云视频点播
    股票数据接口l2有哪些过人之处?
    C++ 多态
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/127778262