For reprint, please indicate the source: Flutter learning notes (33) -- GestureDetector gesture recognition
The main learning content recorded in this essay is GestureDetector gesture recognition, including recognition of click, double-click, long press, component drag and zoom processing.
- Click, double-click, long press
First look at the demo. It's very simple. GestureDetector itself is also a component. GestureDetector recognizes the gesture actions of its internal sub components. In the construction method of GestureDetector, onTap click, onDoubleTap double click and onLongPress long press are callback methods.
After recognizing the user's gesture operation, the corresponding callback method will be executed. The demo processing is to simply update the text copy.
import 'package:flutter/material.dart'; class GestureDetectorDemo extends StatefulWidget { @override State<StatefulWidget> createState() { return _GestureDetectorDemo(); } } class _GestureDetectorDemo extends State { String _operation = "No Gesture detected!"; //Save event name @override Widget build(BuildContext context) { return MaterialApp( title: 'GestureDetectorDemo', home: new Scaffold( appBar: AppBar( title: Text('GestureDetectorDemo'), leading: Icon(Icons.arrow_back), ), body: new GestureDetector( child: Container( alignment: Alignment.center, color: Colors.red, width: 300, height: 200, child: Text( _operation, style: TextStyle(color: Colors.teal), ), ), onTap: () => setState(() => _operation = 'onTap'),//Single machine callback onDoubleTap: () => setState(() => _operation = 'onDoubleTap'),//Double click callback onLongPress: () => setState(() => _operation = 'onLongPress'),//Long press callback ), ), ); } }
Note: it should be noted here that if the two events onTap and onDoubleTap are monitored at the same time, onTap will have a delay of 200ms, because users are likely to click again to trigger the event of double click after clicking once, so GestureDetector will wait a while to determine whether users want to double-click. If only onTap is monitored but not onDoubleTap Then there will be no delay.
- Component drag
It's the same as before
import 'package:flutter/material.dart'; class GestureDragDemo extends StatefulWidget { @override State<StatefulWidget> createState() { return _GestureDragDemoState(); } } class _GestureDragDemoState extends State<GestureDragDemo> { double _top = 0.0; //Offset from top double _left = 0.0; //Offset from bottom @override Widget build(BuildContext context) { return MaterialApp( title: 'GestureDragDemo', home: Scaffold( appBar: AppBar( title: Text('GestureDragDemo'), leading: Icon(Icons.keyboard_backspace), ), body: Stack( children: <Widget>[ Positioned( top: _top, left: _left, child: GestureDetector( child: CircleAvatar( backgroundColor: Colors.red, child: Text( 'A', style: TextStyle(color: Colors.white), ), ), onPanDown: (DragDownDetails downDetails) { //This callback is executed when the finger is pressed // print('Where fingers are pressed: $downDetails.globalPosition'); }, onPanUpdate: (DragUpdateDetails dragUpdateDetails) { //The callback will be executed when the fingers slide setState(() { //Trigger multiple times when fingers slide onPanUpdate Callback, update offset and redraw //dragUpdateDetails.delta.dx obtain y Offset in axis direction _top += dragUpdateDetails.delta.dy; //dragUpdateDetails.delta.dy obtain x Offset in axis direction _left += dragUpdateDetails.delta.dx; }); }, onPanEnd: (DragEndDetails dragEndDetails) { //At the end of the print slide x,y Speed on axis // print(dragEndDetails.velocity); }, ), ), ], )), ); } }
- DragDownDetails.globalPosition : when the user presses, this property is the offset of the user's pressed position relative to the origin (upper left corner) of the screen (not the parent component).
- DragUpdateDetails.delta : when the user swims on the screen, multiple Update events will be triggered. Delta refers to the offset of one Update event's slide.
- DragEndDetails.velocity : this attribute represents the sliding speed (including x and y axes) when the user raises the finger. The example does not deal with the speed when the finger is raised. The common effect is to make a deceleration animation according to the speed when the user raises the finger.
It's also very simple. We mainly lo ok at the callback method onPanUpdate. In the process of finger sliding, this callback will be executed many times. In the callback, we can handle the offset in x and y directions and then draw again.
Offset printing:
- Single drag
The above drag can be dragged in any direction. In daily development, you may encounter drag only in the horizontal (Jigsaw verification) or vertical direction. The destredetector also provides us with corresponding response events:
Look at the demo example:
import 'package:flutter/material.dart'; class GestureDragDemo extends StatefulWidget { @override State<StatefulWidget> createState() { return _GestureDragDemoState(); } } class _GestureDragDemoState extends State<GestureDragDemo> { double _top = 0.0; //Offset from top double _left = 0.0; //Offset from bottom @override Widget build(BuildContext context) { return MaterialApp( title: 'GestureDragDemo', home: Scaffold( appBar: AppBar( title: Text('GestureDragDemo'), leading: Icon(Icons.keyboard_backspace), ), body: Stack( children: <Widget>[ Positioned( top: _top, left: _left, child: GestureDetector( child: CircleAvatar( backgroundColor: Colors.red, child: Text( 'A', style: TextStyle(color: Colors.white), ), ), onPanDown: (DragDownDetails downDetails) { //This callback is executed when the finger is pressed // print('Where fingers are pressed: $downDetails.globalPosition'); }, // onPanUpdate: (DragUpdateDetails dragUpdateDetails) { // //The callback will be executed when the fingers slide // setState(() { // //Trigger multiple times when fingers slide onPanUpdate Callback, update offset and redraw // //dragUpdateDetails.delta.dx obtain y Offset in axis direction // _top += dragUpdateDetails.delta.dy; // print('Y: $dragUpdateDetails.delta.dy'); // //dragUpdateDetails.delta.dy obtain x Offset in axis direction // _left += dragUpdateDetails.delta.dx; // print('X: $dragUpdateDetails.delta.dx'); // }); // }, onHorizontalDragUpdate: (DragUpdateDetails dragUpdateDetails){ setState(() { _left += dragUpdateDetails.delta.dx; }); }, onPanEnd: (DragEndDetails dragEndDetails) { //At the end of the print slide x,y Speed on axis // print(dragEndDetails.velocity); }, ), ), ], )), ); } }
- Zoom
import 'package:flutter/material.dart'; class GestureScaleDemo extends StatefulWidget{ @override State<StatefulWidget> createState() { return _GestureScaleDemoState(); } } class _GestureScaleDemoState extends State { double _width = 200.0; @override Widget build(BuildContext context) { return MaterialApp( title: 'GestureScaleDemo', home: Scaffold( appBar: AppBar( title: Text('GestureScaleDemo'), ), body: Center( child: GestureDetector( child: Image.asset('images/banner.png',width: _width), onScaleUpdate: (ScaleUpdateDetails scaleUpdateDetails){ setState(() { //Zoom multiple at 0.8 Between 10 times _width=200*scaleUpdateDetails.scale.clamp(.8, 10.0); }); }, ), ), ), ); } }