Flutter(十三)——事件处理:手势识别与事件通知

简介: Flutter(十三)——事件处理:手势识别与事件通知

前言


Flutter开发App的过程中,我们除了需要灵活的使用各种组件之外,还需要掌握手势的识别,比如我们常常需要在操作App的时候使用到缩放,双击,放大,缩小等操作,这些Flutter都给我们提供了监听的组件GestureDetector。这篇博文将详细介绍GestureDetector手势识别的使用规则。(拖动手势监听)


GestureDetector基本用法


我们前面提到过,在Flutter开发中,一切皆是组件,所以GestureDetector同样是一个组件,我们使用它,通常是作为一个父Widget包裹一个子Widget外面(也就是你需要捕捉那个组件的手势,就把GestureDetector套在外外面),而内部我们通过onTap回调来实现其点击的效果,代码如下:

GGestureDetector(
  onTap:(){
  print("tap");
  },
  child:Container{
  padding:EdgeInsets.all(20),
  decoration:BoxDecoration(
    color:Theme.of(context).buttonColor,
    borderRadius:BorderRadius.circular(8.0),
  ),
  child:new Text("文本"),
  }
);


比如上面的代码就是改造Text组件成为按钮的方式,这里捕捉了点击事件。


常用事件


GestureDetector手势识别不仅仅只有onTap事件,还有很多很多的常用事件,博主通过一张表格将它们全部列举了出来,方便大家查阅:

属性 取值意义

onTapDwon

当按下屏幕时触发
onTap 当与屏幕短暂地触碰时触发,最常用
onTapUp 当用户停止触碰屏幕时触发
onTapCancel 当用户触摸屏幕,但没有完成Tap事件时触发
onDoubleTap 快速双击屏幕时触发
onLongPress 当长按屏幕时触发(与屏幕接触事件必须超过500ms)
onPanUpdate 当在屏幕上移动时触发
onVerticalDragDown 当手指触碰屏幕且准备往屏幕垂直方向移动时触发
onVerticalDragStart 当手指触碰屏幕且开始往屏幕垂直方向移动时触发
onVerticalDragUpdate 当手指触碰屏幕且开始往屏幕垂直方向移动并发生位移时触发
onVerticalDragEnd 当用户完成垂直方向触摸屏幕时触发
onVerticalDragCancel 当用户中断了onVerticalDragDown时触发
onHorizontalDragDown 当手指触摸屏幕且准备往屏幕水平方向移动时触发
onHorizontalDragStart 当手指触摸屏幕且开始往屏幕水平方向移动时触发
onHorizontalDragUpdate 当手指触摸屏幕且开始往屏幕水平方向移动并发生位移时触发
onHorizontalDragEnd 当用户完成水平方向触摸屏幕时触发
onHorizontalDragCancel 当用户中断了onHorizontalDragDown时触发
onPanDown 当用户触摸屏幕时触发
onPanStart 当用户触摸屏幕并开始移动时触发
onPanUpdate 当用户触摸屏幕并产生移动时触发
onPanEnd 当用户完成触摸屏幕时触发
onScaleStart 当用户触摸屏幕并开始缩放时触发
onScaleUpdate 当用户触摸屏幕并产生缩放时触发
onScaleEnd 当用户完成缩放时触发

虽然说上面表格非常详细,但其中有些事件是互斥的,并不能同时存在,比如onVerticalUpdate,onHorizontalUpdate,onPanUpdate这些三个事件都不能同时存在,否则会报错。


另外,onPanUpdate和onScaleUpdate也不能同时存在,这是因为在Gesture识别器里,Scale操作是Pan操作的超集。


监听事件实现缩放


既然我们了解了如何使用这些事件,那么,我们就应该实践起来,这里小编将用上面的事件实现一个缩放效果,代码如下:

class _MyHomePageState extends State<MyHomePage>{
  double _top=0.0;
  double _left=0.0;
  double _size=100.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: new Text("忽略事件"),),
      body: Stack(
        children: <Widget>[
          Positioned(
            top: this._top,
            left: this._left,
            child: GestureDetector(
              child: FlutterLogo(
                size: this._size,
              ),
              onScaleUpdate: (e){
                setState(() {
                  this._size=300*e.scale.clamp(.5, 10.0);缩放倍数在0.5到10倍之间
                });
              },
            ),
          ),
        ],
      ),
    );
  }
}


代码非常的简单,就是缩放FlutterLogo的大小,实现的效果如下图所示:


监听事件实现拖拽


既然我们已经了解这么多事件,不妨多来一个事件,也就是App中常用的拖拽操作,代码如下(略微改改上上面的代码就行):

class _MyHomePageState extends State<MyHomePage>{
  double _top=0.0;
  double _left=0.0;
  double _size=100.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: new Text("忽略事件"),),
      body: Stack(
        children: <Widget>[
          Positioned(
            top: this._top,
            left: this._left,
            child: GestureDetector(
              child: FlutterLogo(
                size: this._size,
              ),
              onPanUpdate: (e){
                setState(() {
                  this._left+=e.delta.dx;
                  this._top+=e.delta.dy;
                });
              },
            ),
          ),
        ],
      ),
    );
  }
}


仅仅改变了事件的代码,前面说过onPanUpdate与onScaleUpdate不能同时存在,所以不能直接添加事件,需要删除onScaleUpdate后在添加。


事件通知


Notification是“通知”的意思,这和Android中不一样。在Flutter里,Notification会沿着当前的context节点从下往上传递,所有父节点都可以通过NotificationListener来监听通知,这种由子向父的传递方式,我们称为“通知冒泡”,并继承至Notification,而父Widget使用NotificationListener进行监听并捕获通知。常用的NotificatioListener有LayoutChangeNotification,SizeChangedLayoutNotifier,ScrollNotification等。比如本篇将监听ListView滚动状态:是通过NotificationListener里的onNotification回调方法来判断状态。代码如下:

class _MyHomePageState extends State<MyHomePage> {
  String _message = "我是通知";
  void _onScrollStart(ScrollMetrics scrollMetrics){
    print(scrollMetrics.pixels);
    setState(() {
      this._message="滚动开始";
    });
  }
  void _onScrollEnd(ScrollMetrics scrollMetrics){
    print(scrollMetrics.pixels);
    setState(() {
      this._message="滚动结束";
    });
  }
  void _onScrollUpdate(ScrollMetrics scrollMetrics){
    print(scrollMetrics.pixels);
    setState(() {
      this._message="滚动进行时";
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: new Text("事件通知"),
      ),
      body: Column(
        children: <Widget>[
          Container(
            height: 50.0,
            color: Colors.green,
            child: Center(
              child: new Text(this._message),
            ),
          ),
          Expanded(
            child: NotificationListener<ScrollNotification>(
              // ignore: missing_return
              onNotification: (scrollNotification) {
                if (scrollNotification is ScrollStartNotification) {
                  this._onScrollStart(scrollNotification.metrics);
                } else if (scrollNotification is ScrollUpdateNotification) {
                  this._onScrollUpdate(scrollNotification.metrics);
                } else if (scrollNotification is ScrollEndNotification) {
                  this._onScrollEnd(scrollNotification.metrics);
                }
              },
              child: ListView.builder(
                  itemCount: 30,
                  itemBuilder: (context, index) {
                    return ListTile(title: Text("索引:$index"),);
                  }),
            ),
          ),
        ],
      ),
    );
  }
}


实现效果如下图所示,代码很好理解,这里就不在赘述了:

相关文章
|
2月前
|
传感器 Android开发 iOS开发
Flutter插件开发指南02: 事件订阅 EventChannel
上一节我们讲了 Channel 通道,但是如果你是卫星定位业务,原生端主动推消息给 Flutter 这时候就要用到 EventChannel 通道了。 本节会写一个 1~50 的计数器,到 50 后自动关闭原生的消息订阅。
Flutter插件开发指南02:  事件订阅 EventChannel
|
Dart JavaScript
Flutter | 事件处理(下)
Flutter | 事件处理(下)
Flutter | 事件处理(下)
|
API 容器
Flutter | 事件处理(上)
Flutter | 事件处理(上)
Flutter | 事件处理(上)
flutter事件evevt详解
在Flutter中,手势有两个不同的层次: 第一层:原始指针事件(Pointer Events):描述了屏幕上由触摸板、鼠标、指示笔等触发的指针的位置和移动。 第二层:手势识别(Gesture Detector):这个是在原始事件上的一种封装。
150 0
Flutter中焦点FocusNode使用分析Flutter输入框焦点事件的捕捉与监听
在Flutter使用FocusNode来捕捉监听TextField的焦点获取与失去,同时也可通过FocusNode来使用绑定对应的TextField获取焦点与失去焦点。
Flutter中焦点FocusNode使用分析Flutter输入框焦点事件的捕捉与监听
|
3月前
|
监控 Dart 安全
创建一个Dart应用,监控局域网上网记录的软件:Flutter框架的应用
在当今数字时代,网络安全变得愈发重要。为了监控局域网上的上网记录,我们可以借助Flutter框架创建一个强大的Dart应用。在这篇文章中,我们将深入讨论如何使用Flutter框架开发这样一个监控局域网上网记录的软件,并提供一些实用的代码示例。
274 1
|
6月前
|
Dart Android开发 UED
带你读《深入浅出Dart》二十七、Flutter路由管理
带你读《深入浅出Dart》二十七、Flutter路由管理
|
2月前
|
Dart JavaScript
Flutter - Dart 基础(数据类型)
【2月更文挑战第3天】
64 1
|
2月前
|
Dart JavaScript 安全