📜  扑手势

📅  最后修改于: 2021-01-02 04:48:56             🧑  作者: Mango

颤抖的手势

手势是Flutter中一个有趣的功能,它使我们能够与移动应用程序(或任何基于触摸的设备)进行交互。通常,手势定义了用户对移动设备进行特定控制的任何物理动作或运动。手势的一些示例是:

  • 锁定手机屏幕后,在屏幕上滑动手指即可将其解锁。
  • 点击手机屏幕上的按钮,然后
  • 在基于触摸的设备上点击并按住应用程序图标可将其拖到屏幕上。

我们在日常生活中会使用所有这些手势来与您的手机或基于触摸的设备进行交互。

Flutter将手势系统分为两个不同的层,如下所示:

  • 指针
  • 手势

指针

指针是代表有关用户交互的原始数据的第一层。它具有事件,这些事件描述了指针在屏幕上的位置移动,例如触摸,鼠标和样式。 Flutter不提供任何取消或停止指针事件进一步分发的机制。 Flutter提供了一个侦听器窗口小部件,以直接从窗口小部件层监听指针事件。指针事件主要分为以下四种类型:

  • PointerDownEvents
  • PointerMoveEvents
  • PointerUpEvents
  • PointerCancelEvents

PointerDownEvents:它允许指针在特定位置接触屏幕。

PointerMoveEvents:它允许指针从屏幕上的一个位置移动到另一位置。

PointerUpEvents:它允许指针停止接触屏幕。

PointerCancelEvents:取消指针交互时发送此事件。

手势

它是第二层,表示从多个单独的指针事件中识别出的语义动作,例如轻击,拖动和缩放。它还能够调度与手势生命周期相对应的多个事件,例如拖动开始,拖动更新和拖动结束。下面列出了一些常用的手势:

点击:这意味着从指尖短时间触摸屏幕表面,然后释放它们。此手势包含以下事件:

  • onTapDown
  • onTapUp
  • onTap
  • onTapCancel

双击:类似于点击手势,但您需要在短时间内点击两次。此手势包含以下事件:

  • onDoubleTap

拖动:它使我们可以用指尖触摸屏幕表面,然后将其从一个位置移动到另一位置,然后释放它们。 Flutter将拖动分为两种类型:

  • 水平拖动:此手势允许指针在水平方向上移动。它包含以下事件:
    • onHorizontalDragStart
    • onHorizontalDragUpdate
    • onHorizontalDragEnd
  • 垂直拖动:此手势允许指针沿垂直方向移动。它包含以下事件:
    • onVerticalDragStart
    • onVerticalDragStart
    • onVerticalDragStart

长按:这意味着长时间触摸屏幕表面的特定位置。此手势包含以下事件:

  • onLongPress

平移:表示用指尖触摸屏幕表面,可以在不松开指尖的情况下向任何方向移动。此手势包含以下事件:

  • onPanStart
  • onPanUpdate
  • onPanEnd

捏:表示用两根手指放大或缩小屏幕(在触摸屏上移动手指或拇指,或将它们放在一起)。

手势探测器

Flutter提供了一个小部件,该小部件通过使用GestureDetector小部件为所有类型的手势提供了出色的支持。 GestureWidget是非可视的小部件,主要用于检测用户的手势。手势检测器的基本思想是一个无状态的小部件,该小部件的构造函数中包含用于不同触摸事件的参数。

在某些情况下,屏幕上的特定位置可能有多个手势检测器,然后框架消除了应该调用哪个手势的歧义。 GestureDetector小部件基于其回调中的哪些为非空值来决定要识别的手势。

让我们学习如何通过简单的onTap()事件在应用程序中使用这些手势,并确定GestureDetector如何处理此手势。在这里,我们将创建一个盒子小部件,根据所需的规范对其进行设计,然后向其添加onTap()函数。

现在,创建一个新的Flutter项目,并在main.dart文件中替换以下代码。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo Application', theme: ThemeData(
      primarySwatch: Colors.green,),
      home: MyHomePage(),
    );
  }
}
class MyHomePage extends StatefulWidget {
  @override
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Gestures Example'),
        centerTitle: true,
      ),
      body: new Center(child: GestureDetector(
          onTap: () {
            print('Box Clicked');
          },
          child: Container(
            height: 60.0,
            width: 120.0,
            padding: EdgeInsets.all(10.0),
            decoration: BoxDecoration(
              color: Colors.blueGrey,
              borderRadius: BorderRadius.circular(15.0),
            ),
            child: Center(child: Text('Click Me')),
          )
      )),
    );
  }
}

输出量

当您在Android Studio中运行此dart文件时,它将在模拟器中提供以下输出。

在上图中,您可以在屏幕中心看到带有圆角边缘的按钮。当您点击它时,它的行为就像一个按钮,并且可以在控制台中看到输出。

Flutter还提供了一组小部件,可让您执行特定手势以及高级手势。这些小部件如下所示:

Dismissible(可禁用):这是一种小部件,支持轻拂手势以关闭小部件。

可拖动:这是一种小部件,支持拖动手势来移动小部件。

LongPressDraggable:这是一种小部件,它支持拖动手势以将小部件及其父小部件一起移动。

DragTarget:这是一种小部件,可以接受任何Draggable小部件

IgnorePointer:这是一种小部件,可从手势检测过程中隐藏小部件及其子级。

AbsorbPointer:它是一种小部件,可以停止手势检测过程本身。因此,任何重叠的窗口小部件都无法参与手势检测过程,因此不会引发任何事件。

Scrollable:这是一种小部件,它支持小部件内部可用内容的滚动。

多手势示例

在本节中,我们将看到多个手势在Flutter应用程序中如何工作。该演示应用程序由父级和子级两个容器组成。在这里,所有操作都通过使用'RawGestureDetector'和自定义的'GestureRecognizer'进行手动处理。自定义的GestureRecognizer为手势列表提供'AllowMultipleGestureRecognizer'属性,并创建一个'GestureRecognizerFactoryWithHandlers'。接下来,当onTap()事件被调用时,它将文本输出到控制台。

打开flutter项目,并在main.dart文件中替换以下代码,

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

//It is the entry point for your Flutter app.
void main() {
  runApp(
    MaterialApp(
      title: 'Multiple Gestures Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Multiple Gestures Demo'),
        ),
        body: DemoApp(),
      ),
    ),
  );
}

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: {
        AllowMultipleGestureRecognizer: GestureRecognizerFactoryWithHandlers<
            AllowMultipleGestureRecognizer>(
              () => AllowMultipleGestureRecognizer(),
              (AllowMultipleGestureRecognizer instance) {
            instance.onTap = () => print('It is the parent container gesture');
          },
        )
      },
      behavior: HitTestBehavior.opaque,
      //Parent Container
      child: Container(
        color: Colors.green,
        child: Center(
          //Now, wraps the second container in RawGestureDetector
          child: RawGestureDetector(
            gestures: {
              AllowMultipleGestureRecognizer:
              GestureRecognizerFactoryWithHandlers<
                  AllowMultipleGestureRecognizer>(
                    () => AllowMultipleGestureRecognizer(),  //constructor
                    (AllowMultipleGestureRecognizer instance) {  //initializer
                  instance.onTap = () => print('It is the nested container');
                },
              )
            },
            //Creates the nested container within the first.
            child: Container(
              color: Colors.deepOrange,
              width: 250.0,
              height: 350.0,
            ),
          ),
        ),
      ),
    );
  }
}

class AllowMultipleGestureRecognizer extends TapGestureRecognizer {
  @override
  void rejectGesture(int pointer) {
    acceptGesture(pointer);
  }
}

输出量

当您运行该应用程序时,它将提供以下输出。

接下来,点击橙色框,控制台上将显示以下输出。

It is the nested container.
It is the parent container gesture.