详解FLUTTER手势识别与事件通知

本文目录

前言

GestureDetector基本用法

常用事件

监听事件实现缩放

监听事件实现拖拽

事件通知

前言

在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事件,还有很多很多的常用事件,博主通过一张表格将它们全部列举了出来,方便大家查阅:

虽然说上面表格非常详细,但其中有些事件是互斥的,并不能同时存在,比如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,
              ),
              onScaleUpdate: (e){
                setState(() {
                  this._size=300*e.scale.clamp(.5, 10.0);////缩放倍数在0.5到10倍之间
                });
              },
            ),
          ),
        ],
      ),
    );
  }
}

仅仅改变了事件的代码,前面说过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"),);
                  }),
            ),
          ),
        ],
      ),
    );
  }
}

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

学习分享,共勉

题外话,毕竟我在三星小米工作多年,深知技术改革和创新的方向,Flutter作为跨平台开发技术、Flutter以其美观、快速、高效、开放等优势迅速俘获人心,但很多FLutter兴趣爱好者进阶学习确实资料,今天我把我搜集和整理的这份学习资料分享给有需要的人,若有关Flutter学习进阶可以与我在Flutter跨平台开发终极之选交流群一起讨论交流。下载地址:https://shimo.im/docs/yTD3t8Pjq3XJtGv8

下载地址:https://shimo.im/docs/yTD3t8Pjq3XJtGv8

原文作者:李元静

原文链接:CSDN-专业IT技术社区-登录

来源:CSDN

发布了422 篇原创文章 · 获赞 718 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/weixin_43901866/article/details/104180017