Flutter 事件与通知
Flutter中的触摸事件可分为两层来看待。第一层是触摸原事件(指针),有相应的四种事件类型:PointerDownEvent:用户与屏幕接触产生了联系。PointerMoveEvent:手指已从屏幕上的一个位置移动到另一个位置。PointerUpEvent:用户已停止接触屏幕。PointerCancelEvent:此指针的输入不再指向此应用程序。第二层就是检测到的手势,主要分为三大类,包括轻击、拖动和缩放
GestureDetector
GestureDetector 可以进行手势检测,共有7种类型事件。比如点击一次、双击、长按、垂直滑动及水平滑动等
| 属性 | 类型 | 简述 |
|---|---|---|
| onTapDown | GestureTapDownCallback |
手指按下时触发 |
| onTapUp | GestureTapUpCallback |
手指抬起时触发 |
| onTap | GestureTapCallback |
单击屏幕时触发 |
| onTapCancel | GestureTapCancelCallback |
没有完成Tap的动作时触发 |
| onDoubleTap | GestureTapCallback |
快速双击屏幕时触发 |
| onLongPress | GestureLongPressCallback |
长按屏幕时触发 |
| onLongPressStart | GestureLongPressStartCallback |
监听长按事件的开始 |
| onLongPressMoveUpdate | GestureLongPressMoveUpdateCallback |
长按屏幕且移动手指时触发 |
| onLongPressUp | GestureLongPressUpCallback |
手指完全离开屏幕时触发 |
| onLongPressEnd | GestureLongPressEndCallback |
手指开始离开屏幕时触发 |
| onVerticalDragDown | GestureDragDownCallback |
手指按下并在垂直方向上移动时触发 |
| onVerticalDragStart | GestureDragStartCallback |
触摸点开始在垂直方向上移动时触发(在onVerticalDragDown之后) |
| onVerticalDragUpdate | GestureDragUpdateCallback |
触摸点在垂直方向上移动时触发 |
| onVerticalDragEnd | GestureDragEndCallback |
停止移动,且该拖拽操作就被认为是完成了时触发 |
| onVerticalDragCancel | GestureDragCancelCallback |
突然停止拖拽时触发 |
| onHorizontalDragDown | GestureDragDownCallback |
参见onVerticalDragDown,为水平方向 |
| onHorizontalDragStart | GestureDragStartCallback |
参见onVerticalDragDown,为水平方向 |
| onHorizontalDragUpdate | GestureDragUpdateCallback |
参见onVerticalDragDown,为水平方向 |
| onHorizontalDragEnd | GestureDragEndCallback |
参见onVerticalDragDown,为水平方向 |
| onHorizontalDragCancel | GestureDragCancelCallback |
参见onVerticalDragDown,为水平方向 |
| onPanDown | GestureDragDownCallback |
手指接触屏幕,并且可能开始移动时触发 |
| onPanStart | GestureDragStartCallback |
触摸点开始移动时触发 |
| onPanUpdate | GestureDragUpdateCallback |
触摸点不断移动时触发 |
| onPanEnd | GestureDragEndCallback |
操作完成手指离开屏幕时触发 |
| onPanCancel | GestureDragCancelCallback |
先前触发onPanDown的指针未完成时触发 |
| onScaleStart | GestureScaleStartCallback |
触摸屏幕开始缩放操作时触发 |
| onScaleUpdate | GestureScaleUpdateCallback |
缩放过程中的监听 |
| onScaleEnd | GestureScaleEndCallback |
手指离开屏幕,缩放完成时触发 |
| onForcePressStart | GestureForcePressStartCallback |
触摸屏幕且有足够压力时触发(仅在具有压力检测的屏幕设备支持) |
| onForcePressPeak | GestureForcePressPeakCallback |
触摸屏幕压力达到最大时触发(需设备支持) |
| onForcePressUpdate | GestureForcePressUpdateCallback |
有足够的压力并在屏幕上移动时触发(需设备支持) |
| onForcePressEnd | GestureForcePressEndCallback |
离开屏幕时触发(需设备支持) |
| behavior | HitTestBehavior |
在命中测试期间,此手势检测器应如何表现 |
| excludeFromSemantics | bool |
是否从语义树中排除这些手势。 例如,用于显示工具提示的长按手势被排除在外,因为工具提示本身直接包含在语义树中,因此具有显示该工具提示的手势将导致信息重复 |
| dragStartBehavior | DragStartBehavior |
设定处理拖动开始行为的方式 |
需要注意,GestureDetector并不会监听所有的手势,只有传入的回调非空时,才会监听。所以,如果想要禁用某个手势时,可将对应的回调函数设置为null。
另外,GestureDetector的某些事件是互斥的,不能同时存在,例如onVerticalUpdate、onHorizontalUpdate、onPanUpdate这三个事件不能同时存在,onPanUpdate和onScaleUpdate也不能同时存在。
测试手势处理回调
GestureDetector( child: Container( width: 300.0, height: 500.0, color: Colors.amber, ), onTapDown: (_) => debugPrint("onTapDown"), onTapUp: (_) => debugPrint("onTapUp"), onTap: () => debugPrint("onTap"), onTapCancel: () => debugPrint("onTapCancel"), onDoubleTap: () => debugPrint("onDoubleTap"), onLongPress: () => debugPrint("onLongPress"), onLongPressUp: () => debugPrint("onLongPressUp"), onVerticalDragDown: (_) => debugPrint("onVerticalDragDown"), onVerticalDragStart: (_) => debugPrint("onVerticalDragStart"), onVerticalDragUpdate: (_) => debugPrint("onVerticalDragUpdate"), onVerticalDragEnd: (_) => debugPrint("onVerticalDragEnd"), onVerticalDragCancel: () => debugPrint("onVerticalDragCancel"), onHorizontalDragDown: (_) => debugPrint("onHorizontalDragDown"), onHorizontalDragStart: (_) => debugPrint("onHorizontalDragStart"), onHorizontalDragUpdate: (_) => debugPrint("onHorizontalDragUpdate"), onHorizontalDragEnd: (_) => debugPrint("onHorizontalDragEnd"), onHorizontalDragCancel: () => debugPrint("onHorizontalDragCancel"), onPanDown: (_) => debugPrint("onPanDown"), onPanStart: (_) => debugPrint("onPanStart"), onPanUpdate: (_) => debugPrint("onPanUpdate"), onPanEnd: (_) => debugPrint("onPanEnd"), onPanCancel: () => debugPrint("onPanCancel"), onScaleStart: (_) => debugPrint("onScaleStart"), onScaleUpdate: (_) => debugPrint("onScaleUpdate"), onScaleEnd: (_) => debugPrint("onScaleEnd"), )
通过手势处理实现一个拖动示例
class _HomePageState extends State<HomePage> { double _left = 0.0; double _top = 0.0; GlobalKey _gKey = GlobalKey(); double stackWidth = 0.0; double stackHeight = 0.0; @override void initState() { super.initState(); // 注册一个回调,当屏幕渲染第一帧的时候回调 WidgetsBinding.instance.addPostFrameCallback((_){ stackWidth = _gKey.currentContext.size.width; stackHeight = _gKey.currentContext.size.height; }); } @override Widget build(BuildContext context) { print("_HomePageState build ..."); return Scaffold( appBar: AppBar( title: Text("Flutter Widget"), ), body: GestureDetector( onPanUpdate: (DragUpdateDetails details){ setState(() { // 边界检查 if(_left + 200 > stackWidth){ _left = stackWidth- 200; }else if(_left < 0){ _left = 0; } else{ _left += details.delta.dx; } if(_top + 200 > stackHeight){ _top = stackHeight- 200; }else if(_top < 0){ _top = 0; }else{ _top += details.delta.dy; } }); }, child: Stack( key: _gKey, children: <Widget>[ Positioned( left: _left, top: _top, width: 200.0, height: 200.0, child: Container( color: Colors.amber, ), ) ], ), ), ); }
缩放示例
class _ScaleWidgetState extends State<ScaleWidget>{ double _width = 300.0; double _height = 200.0; @override Widget build(BuildContext context) { return Center( child: GestureDetector( child: Container( width: _width, height: _height, color: Colors.pink, ), onScaleUpdate: (e) { print(e); setState(() { // 限制缩放比例在0.7-1.2之间,超过范围则变为原大小 _width = 300* e.scale.clamp(0.7, 1.2); _height = 200*e.scale.clamp(0.7, 1.2); }); }, ) ); } }
InkWell
具有水波纹效果(或称为溅墨效果)的点击事件控件。能处理的触摸事件很少,如需处理复杂的手势事件,应使用GestureDetector。
需要注意,当InkWell的父控件设置了背景色时,是看不到溅墨效果效果的,此时需要进行特殊处理,当使用InkWell包裹image时,也无法显示出溅墨效果,这时建议使用Ink.Image控件。
// 需使用Matetial 以及 Ink控件包裹 Material( child: Ink( decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(10) ), child: InkWell( onTap: (){ print("onTap..."); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 16,vertical: 6), child: Text("这是按钮",style: TextStyle(color: Colors.white),), ), ), ), )
如需取消溅墨效果,可进行如下设置
// 设置highlightColor和radius取消溅墨效果 InkWell( highlightColor: Colors.transparent, radius: 0.0, child: Text( "click me", ), onTap: () { print("onTap"); }, ),
Snackbar
它是Material Design设计中的一个轻量级消息通知控件。
| 属性 | 类型 | 简述 |
|---|---|---|
| content | Widget |
展示的内容 |
| backgroundColor | Color |
背景色 |
| elevation | double |
阴影高度 |
| shape | ShapeBorder |
形状 |
| behavior | SnackBarBehavior |
位置,SnackBarBehavior.fixed 固定在底部;SnackBarBehavior.floating显示在底部导航栏上方 |
| action | SnackBarAction |
执行的动作(相当于按钮) |
| duration | Duration |
停留时间 |
| animation | animation |
显示或隐藏的动画效果 |
| onVisible | VoidCallback |
显示时的回调 |
Scaffold.of(context).showSnackBar(SnackBar( content: Text('这是一个 SnackBar'), backgroundColor: Colors.black26, duration: Duration(seconds: 1), behavior: SnackBarBehavior.floating, action: SnackBarAction( label: '我是按钮', onPressed: () { print('点击了按钮'); }), ));
小结:
- 显示
Snackbar:Scaffold.of(context).showSnackBar(snackBar) - 隐藏当前的
SnackBar:Scaffold.of(context).hideCurrentSnackBar()
THE END






暂无评论内容