Flutter---事件处理

原始指针事件

概念

指针事件是Flutter中最基础的事件类型,直接对应触摸屏、鼠标、手写笔等输入设备的原始交互。一个完整的原始指针事件主要由手指按下、手指移动、手指抬起,以及触摸取消构成,更高级别的手势都基于这些原始事件。

PointerEvent是Flutter原始指针事件的基础类

Dart 复制代码
position:全局坐标的偏移量

delta:两次指针移动事件的距离

pressure:按压力度,如果手机屏幕支持压力传感器,此属性会返回压力值,如果手机不支持,则始终返回1。

orientation:指针移动方向,是一个角度值

核心指针事件类型

Dart 复制代码
- PointerDownEvent  : 手指/指针按下
- PointerMoveEvent  : 手指/指针移动  
- PointerUpEvent    : 手指/指针抬起
- PointerCancelEvent: 事件取消(如被手势识别器拦截)
- PointerSignalEvent: 滚轮等信号

指针事件监听器的一个小案例

Dart 复制代码
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Listener(
          onPointerDown: (PointerDownEvent event) {
            print('按下 - 位置: ${event.position}');
            print('本地位置: ${event.localPosition}');
            print('指针ID: ${event.pointer}');
            print('压力: ${event.pressure}');
            print('设备类型: ${event.kind}'); // touch, mouse, stylus等
          },
          onPointerMove: (PointerMoveEvent event) {
            print('移动 - 当前位置: ${event.position}');
            print('移动距离: ${event.delta}');
            print('globalPosition: ${event.globalPosition}');  // 相对于整个屏幕
            print('localPosition: ${event.localPosition}'); //相对于当前 Listener 的坐标
          },
          onPointerUp: (PointerUpEvent event) {
            print('抬起');
          },
          onPointerCancel: (PointerCancelEvent event) {
            print('事件取消');
          },
          onPointerSignal: (PointerSignalEvent event) {
            if (event is PointerScrollEvent) {
              print('滚轮滚动: ${event.scrollDelta}');
            }
          },
          behavior: HitTestBehavior.opaque, // 事件穿透行为
          child: Container(
            width: 200,
            height: 200,
            color: Colors.blue,
          ),
        ),
      )
    );
  }

PointerEvent 对象的详细属性

Dart 复制代码
Listener(
  onPointerDown: (event) {
    // 基本信息
    print('位置: ${event.position}');          // 全局坐标
    print('本地位置: ${event.localPosition}');  // 相对于当前widget的坐标
    print('指针ID: ${event.pointer}');          // 用于追踪同一触摸点
    print('时间戳: ${event.timeStamp}');        // 事件发生时间
    
    // 触摸信息
    print('压力: ${event.pressure}');            // 触摸压力(0-1)
    print('压力最大值: ${event.pressureMax}');   
    print('接触面积: ${event.size}');             // 触摸面积
    
    // 设备信息
    print('设备类型: ${event.kind}');             // PointerDeviceKind.touch/mouse/stylus等
    print('设备是否支持压力: ${event.synthesized}');
    
    // 辅助信息
    print('按钮: ${event.buttons}');              // 鼠标按钮
    print('倾斜: ${event.tilt}');                  // 手写笔倾斜角度
    print('方位角: ${event.orientation}');         // 手写笔方向
  },
  child: Container(...),
)

behavior属性:决定子组件如何响应命中测试,它的值的类型为HitTestBehavior,是一个枚举类型,有3个枚举值

Dart 复制代码
enum HitTestBehavior {
  /// 透明区域不响应,只响应不透明区域
  deferToChild,
  
  /// 透明区域也响应,但不阻止事件传递
  translucent,
  
  /// 总是响应,并阻止事件传递
  opaque,
}
手势识别组件(Gesture API )

常用事件的小案例

Dart 复制代码
 return Scaffold(
      body: Center(
        child: GestureDetector(
          // 点击相关
          onTap: () => print('点击'),
          onTapDown: (details) => print('按下: ${details.globalPosition}'),
          onTapUp: (details) => print('抬起'),
          onTapCancel: () => print('点击取消'),

          // 双击
          onDoubleTap: () => print('双击'),
          onDoubleTapDown: (details) => print('双击按下'),
          onDoubleTapCancel: () => print('双击取消'),

          // 长按
          onLongPress: () => print('长按'),
          onLongPressStart: (details) => print('长按开始'),
          onLongPressEnd: (details) => print('长按结束'),
          onLongPressMoveUpdate: (details) => print('长按移动'),
          onLongPressUp: () => print('长按抬起'),

          // 水平拖动
          onHorizontalDragStart: (details) => print('水平拖动开始'),
          onHorizontalDragUpdate: (details) => print('水平拖动中'),
          onHorizontalDragEnd: (details) => print('水平拖动结束'),

          // 垂直拖动
          onVerticalDragStart: (details) => print('垂直拖动开始'),
          onVerticalDragUpdate: (details) => print('垂直拖动中'),
          onVerticalDragEnd: (details) => print('垂直拖动结束'),

          // 其他
          behavior: HitTestBehavior.opaque, // 命中测试行为
          excludeFromSemantics: false, // 是否排除语义

          child: Container(
            width: 200,
            height: 200,
            color: Colors.blue,
            child: Center(child: Text('点击我')),
          ),
        )
      )
    );

缩放的小案例

Dart 复制代码
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<StatefulWidget> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  // 当前缩放和位置
  double _scale = 1.0; //当前缩放比例
  Offset _position = Offset.zero; //当前位置

  // 用于平滑缩放的中间变量
  double _previousScale = 1.0; //上一次缩放开始前的比例
  Offset _previousPosition = Offset.zero;//上一次缩放开始前的位置

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('图片手势'),
        actions: [
          IconButton(
            icon: const Icon(Icons.restore),
            onPressed: _resetImage,
            tooltip: '恢复默认大小和位置',
          ),
        ],
      ),

      body: Column(
        children: [
          Expanded(
            child: GestureDetector(
              // 缩放开始
              onScaleStart: (details) {
                // 保存开始缩放前的状态
                _previousScale = _scale;
                _previousPosition = _position;
              },

              // 缩放更新
              onScaleUpdate: (details) {
                setState(() {

                  double scaleChange = details.scale; //表示相对于上一次的缩放比例变化
                  
                  _scale = _previousScale * scaleChange;//计算新的缩放值

                  // 限制缩放范围
                  _scale = _scale.clamp(0.5, 3.0);

                  // 更新位置
                  _position = _previousPosition + details.focalPointDelta;
                });
              },

              // 缩放结束
              onScaleEnd: (details) {
                // 可以在这里添加回弹效果等
              },

              // 双击重置
              onDoubleTap: _resetImage,

              child: Center(
                child: Transform.scale(
                  scale: _scale,
                  child: Transform.translate(
                    offset: _position,
                    child: Image.asset(
                      'assets/images/apple.png',
                      // 添加错误处理
                      errorBuilder: (context, error, stackTrace) {
                        return Container(
                          width: 200,
                          height: 200,
                          color: Colors.grey[300],
                          child: const Center(
                            child: Text('图片加载失败'),
                          ),
                        );
                      },
                    ),
                  ),
                ),
              ),
            ),
          ),

        ],
      ),
    );
  }

  // 重置图片到原始大小和位置
  void _resetImage() {
    setState(() {
      _scale = 1.0;
      _position = Offset.zero;
    });
  }
}

拖拽的小案例

Dart 复制代码
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<StatefulWidget> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  double _top = 0.0;
  double _left = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('图片拖拽'),
        actions: [
          IconButton(
            icon: const Icon(Icons.restore),
            onPressed: _resetImage,
            tooltip: '恢复默认大小和位置',
          ),
        ],
      ),

      body: Stack(
        children: [
         Positioned(
              top: _top,
              left: _left,
              child: GestureDetector(
                child: Image.asset("assets/images/apple.png"),

                onPanDown: (DragDownDetails e){
                  print("onPanDown:${e.globalPosition}");
                },

                onPanUpdate: (DragUpdateDetails e){
                  setState(() {
                    _left += e.delta.dx;
                    _top += e.delta.dy;
                  });
                },

                onPanEnd: (DragEndDetails e){
                  print('onPanEnd:'+e.velocity.toString());
                },
              ),
            )
        ],
      ),
    );
  }

  // 重置图片到原始大小和位置
  void _resetImage() {
    setState(() {
      _top = 0.0;
      _left = 0.0;
    });
  }
}

InkWell - 带有水波纹效果的点击组件

Dart 复制代码
 @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 基础用法
            InkWell(
              onTap: () => print('InkWell 点击'),
              onDoubleTap: () => print('InkWell 双击'),
              onLongPress: () => print('InkWell 长按'),
              splashColor: Colors.blue.withOpacity(0.5), // 水波纹颜色
              highlightColor: Colors.red.withOpacity(0.2), // 高亮颜色
              radius: 100, // 水波纹半径
              borderRadius: BorderRadius.circular(10), // 圆角
              child: Container(
                width: 200,
                height: 100,
                child: Center(child: Text('带水波纹的点击区域')),
              ),
            ),

            SizedBox(height: 20),

            // 带边框的 InkWell
            Material(
              borderRadius: BorderRadius.circular(15),
              child: InkWell(
                onTap: () => print('带边框的点击'),
                borderRadius: BorderRadius.circular(15),
                child: Container(
                  width: 200,
                  height: 100,
                  child: Center(child: Text('带边框的水波纹')),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

待学习

自定义组件

手势密码锁

相关推荐
lqj_本人4 小时前
Flutter三方库适配OpenHarmony【apple_product_name】deviceInfo系统API调用
flutter
littlegnal4 小时前
Flutter Android如何延迟加载代码
android·flutter
松叶似针5 小时前
Flutter三方库适配OpenHarmony【doc_text】— onMethodCall 分发与文件路径参数提取
flutter
卢叁5 小时前
Flutter之路由监听器
前端·flutter
恋猫de小郭5 小时前
Android 17 有什么需要适配的?2026 Android 禁止侧载又是什么?
android·前端·flutter
阿林来了5 小时前
Flutter三方库适配OpenHarmony【flutter_web_auth】— EntryAbility 深度链接回调集成
flutter
阿林来了5 小时前
Flutter三方库适配OpenHarmony【flutter_web_auth】— OpenHarmony 插件工程搭建与配置文件详解
flutter·harmonyos
2601_949593655 小时前
Flutter for Harmony 跨平台开发实战:递归分形树——L-系统的生长逻辑
flutter
lqj_本人5 小时前
Flutter三方库适配OpenHarmony【apple_product_name】用户反馈系统集成设备信息
flutter