Listener 它是主要的功能是用来监听屏幕触摸事件,取决于它的子组件区域范围,比如按下、移动、抬起、取消等操作时可以添加监听。
永平网站建设公司创新互联,永平网站设计制作,有大型网站制作公司丰富经验。已为永平成百上千家提供企业网站建设服务。企业网站搭建\成都外贸网站建设公司要多少钱,请找那个售后服务好的永平做网站的公司定做!
我们知道 Flutter 组件只有按钮才会有事件,那么如果我需要在文字或者某个容器上添加事件那我就需要借助 Listener
手势系列视频教程地址
Listener 常用于当手指滑动屏幕时进行隐藏键盘或者下拉刷新、上拉加载时进行事件监听。
一般在实际的开发过程中我们很少会用到 Listener 来监听手势,一般都是通过 GestureDetector 来进行监听或者使用 MouseRegion 来监听鼠标的事件,而 MouseRegion 常用于web开发中, GestureDetector 常用于app。
我们经常使用的回调函数主要有三个
我们这里主要是针对 onPointerDown 、 onPointerMove 、 onPointerUp 进行演示,因为我们在平时的开发过程中最常用到的属性就是这三个,而且其他的属性也都被废弃掉了。
我们这里先点击橙色容器,在点击一次红色容器,他们打印的结果如下。
PointerEvent 是触摸、手写笔、鼠标事件的基类。
在上文中,我们知道了什么是 Listener 并写了一个简单的案例,在使用案例的过程中我们的事件里面都带了一个 event 参数,而所有的事件最终都是继承自 PointerEvent ,那我们接下来看看 event 的参数有什么作用。
PointerEvent 的属性非常多,但在我们实际的开发过程中很少会使用到,只有在特定的情景下才会使用对应的属性。
如需要做一个全局悬浮的按钮我们会使用到 position
如需要做绘图软件我们需要用到 buttons 、 kind 等
所以大家可以根据实际的应用场景来使用对应的属性即可,下面是我对 PointerEvent 的属性进行的一个详细描述。
behavior 属性,它决定子组件如何响应命中测试,它的值类型为 HitTestBehavior ,这是一个枚举类,有三个枚举值
对子组件一个接一个的进行命中测试,如果子组件中有测试通过的,则当前组件通过,这就意味着,如果指针事件作用于子组件上时,其父级组件也肯定可以收到该事件。
在命中测试时,将当前组件当成不透明处理(即使本身是透明的),最终的效果相当于当前Widget的整个区域都是点击区域
点击组件透明区域时,可以对自身边界内及底部可视区域都进行命中测试,这意味着点击顶部组件透明区域时,顶部组件和底部组件都可以接收到事件
我们这里演示每次都是先点击绿色盒子在点击文字,以便大家能更好的分辨出这三个属性的使用区别
Listener 是 Flutter 中比较重要的功能性组件,它主要的功能是用来监听屏幕触摸事件,事件回调可以获取对应的属性来个性化定制app功能。
相信在方法当中,我们都会遇到让组件有拖拽效果的需求。在 Flutter 当中怎么实现拖拽需求呢?这篇博客分享关于 拖拽手势 的知识,希望对看文章的小伙伴有所启发。
拖拽手势 是指用户在长按屏幕的时候,移动手指的手势。会细分成:
我们可以理解成用户在触碰到屏幕的那一刻处于 按下 ,之后有可能触发 移动 手势,最后 抬起 离开屏幕,这就是完整的手势。
在 GestureDetector 当中,拖拽手势分为2种:
import 'package:flutter/material.dart';
void main() = runApp(MyApp());
class MyAppextends StatelessWidget {
// This widget is the root of your application.
@override
Widgetbuild(BuildContext context) {
return MaterialApp(
title:'Flutter Demo',
theme:ThemeData(
primarySwatch: Colors.blue, splashColor: Colors.transparent),
home:HYHomePage(),
);
}
}
class HYHomePageextends StatelessWidget {
@override
Widgetbuild(BuildContext context) {
return Scaffold(
appBar:AppBar(
title:Text("列表测试"),
),
body:GestureDemo(),
// Center(
// child: Stack(
// alignment: Alignment.center,
// children: [
// GestureDetector(
// onTapDown: (details) {
// print("outer click");
// },
// child: Container(
// width: 200,
// height: 200,
// color: Colors.yellow,
// alignment: Alignment.center,
// ),
// ),
// IgnorePointer(
// child: GestureDetector(
// onTapDown: (details) {
// print("inner click");
// },
// child: Container(
// width: 100,
// height: 100,
// color: Colors.red,
// ),
// ),
// )
// ],
// ),
// ),
);
}
}
class GestureDemoextends StatelessWidget {
const GestureDemo({
Key key,
}) :super(key: key);
@override
Widgetbuild(BuildContext context) {
return Center(
child:GestureDetector(
onTapDown: (details) {
print("手指按下");
print(details.globalPosition);
print(details.localPosition);
},
onTapUp: (details) {
print("手指抬起");
},
onTapCancel: () {
print("手势取消");
},
onTap: () {
print("手势点击");
},
onDoubleTap: () {
print("手指双击");
},
onLongPress: () {
print("长按手势");
},
onPanUpdate: (value){
print('当前我在滑动$value');
},
child:Container(
width:200,
height:200,
color: Colors.orange,
),
),
);
}
}
class ListenerDemoextends StatelessWidget {
const ListenerDemo({
Key key,
}) :super(key: key);
@override
Widgetbuild(BuildContext context) {
return Listener(
onPointerDown: (event) {
print("指针按下:$event");
print(event.position);
print(event.localPosition);
},
onPointerMove: (event) {
// print("指针移动:$event");
},
onPointerUp: (event) {
// print("指针抬起:$event");
},
child:Container(
width:200,
height:200,
color: Colors.red,
),
);
}
}
在Android中,每一个 View 都可以通过 onTouch 方法重写其触摸事件,也可以通过 setOnClickListener 方法来给 View 设置点击事件。但是Flutter中除了少部分组件,如 Button 相关的组件可以直接通过 onPressed 实现点击事件。其余组件想实现点击、长按等事件,都需要借助 GestureDetector 来实现手势监听
下面介绍比较常用的手势如 onTap (点击)、 onDoubleTap (双击)、 onLongPress (长按)
小球跟随手指移动的实现应该是属于各种移动端框架作为了解拖动手势的的典型案例,下面我们来看看用flutter如何实现小球跟随手指移动
拖动手势主要由 onPanDown (手指按下)、 onPanUpdate (手指滑动)、 onPanEnd (滑动结束)构成
缩放手势需要用到 onScaleUpdate 方法,下面是一个简单的图片缩放的实现
描述了屏幕上指针(触摸、鼠标、触控笔)的位置和移动。
Flutter中可以使用Listener(功能性组件)来监听原始触摸事件
例1
例2
例3
忽略PointerEvent
手势: 描述由一个或多个指针移动组成的语义动作,如拖动、缩放、双击等。
Material大多数widget已经对tap或手势做出了响应。 例如 IconButton和 FlatButton 响应单击,ListView响应滑动事件触发滚动。
用于手势识别的功能性组件,通过它可以来识别各种手势。
例(单击)
例(添加Material触摸水波效果 InkWell组件)
例(滑动关闭 Dismissable组件)
例(单击、双击、长按)
例(滑动)
例(扫动---单一方向)
例(缩放)
GestureRecognizer是一个抽象类。
一种手势的识别器对应一个GestureRecognizer的子类。
例
由于手势竞争最终只有一个胜出者,所以,当有多个手势识别器时,可能会产生冲突。
例
例
在APP中经常会需要一个广播机制,用以跨页面通知。比如一个需要登录的APP中,页面会关注用户登录或注销事件,来进行一些状态更新。
这时候,一个事件总线便会非常有用,事件总线通常实现了订阅者模式,订阅者模式包含发布者和订阅者两种角色,可以通过事件总线来触发事件和监听事件。
对于一些简单的应用,事件总线是足以满足业务需求的,如果决定使用状态管理包的话,一定要想清楚APP是否真的有必要使用它,防止“化简为繁”、过度设计。
例
在widget树中,每一个节点都可以分发通知,通知会沿着当前节点向上传递,所有父节点都可以通过NotificationListener来监听通知。
Flutter中将这种由子向父的传递通知的机制称为通知冒泡(Notification Bubbling)。
通知冒泡和用户触摸事件冒泡是相似的,但有一点不同:通知冒泡可以中止,但用户触摸事件不行。
通知冒泡和Web开发中浏览器事件冒泡原理是相似的,都是事件从出发源逐层向上传递,可以在上层节点任意位置来监听通知/事件,也可以终止冒泡过程,终止冒泡后,通知将不会再向上传递。
Flutter的UI框架实现中,除了在可滚动组件在滚动过程中会发出ScrollNotification之外,还有一些其它的通知,如SizeChangedLayoutNotification、KeepAliveNotification 、LayoutChangedNotification等,Flutter正是通过这种通知机制来使父元素可以在一些特定时机来做一些事情。
例
例
例
阻止冒泡
通知冒泡原理