Flutter學習筆記(33)--GestureDetector手勢識別

如需轉載,請註明出處:Flutter學習筆記(33)--GestureDetector手勢識別html

這篇隨筆主要記錄的學習內容是GestureDetector手勢識別,內容包括識別單擊、雙擊、長按、組件拖拽和縮放處理。app

  • 單擊、雙擊、長按

先看下demo,很簡單,GestureDetector自己也是一個組件,GestureDetector識別其內部子組件的手勢動做,GestureDetector的構造方法內給咱們提供了onTap單擊、onDoubleTap雙擊、onLongPress長按的是回調方法。ide

識別到用戶的手勢操做後會執行對應的回調方法,demo的處理就是簡單的更新一下text的文案。post

import 'package:flutter/material.dart';

class GestureDetectorDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _GestureDetectorDemo();
  }
}

class _GestureDetectorDemo extends State {
  String _operation = "No Gesture detected!"; //保存事件名
  @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'),//單機回調
          onDoubleTap: () => setState(() => _operation = 'onDoubleTap'),//雙擊回調
          onLongPress: () => setState(() => _operation = 'onLongPress'),//長按回調
        ),
      ),
    );
  }
}

注:這裏要說明一下,若是同時監聽的onTap和onDoubleTap這兩個事件的話,onTap會有200ms的延時,由於由於用戶在點擊一次以後頗有可能會再點擊一次來觸發雙擊的事件,因此GestureDetector會等一段時間來肯定用戶是否是要雙擊,若是隻是監聽了onTap而沒有監聽onDoubleTap的話,就不會有延時了。學習

  • 組件拖動

老樣子先看demo再講解:動畫

import 'package:flutter/material.dart';

class GestureDragDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _GestureDragDemoState();
  }
}

class _GestureDragDemoState extends State<GestureDragDemo> {
  double _top = 0.0; //距離頂部的偏移量
  double _left = 0.0; //距離底部的偏移量
  @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) {
                    //手指按下時會執行此回調
//                    print('手指按下的位置:$downDetails.globalPosition');
                  },
                  onPanUpdate: (DragUpdateDetails dragUpdateDetails) {
                    //手指滑動時會執行次回調
                    setState(() {
                      //手指滑動時會屢次觸發onPanUpdate回調,更新偏移量並從新繪製
                      //dragUpdateDetails.delta.dx獲取y軸方向的偏移量
                      _top += dragUpdateDetails.delta.dy;
                      //dragUpdateDetails.delta.dy獲取x軸方向的偏移量
                      _left += dragUpdateDetails.delta.dx;
                    });
                  },
                  onPanEnd: (DragEndDetails dragEndDetails) {
                    //打印滑動結束時在x、y軸上的速度
//                    print(dragEndDetails.velocity);
                  },
                ),
              ),
            ],
          )),
    );
  }
}
  • DragDownDetails.globalPosition:當用戶按下時,此屬性爲用戶按下的位置相對於屏幕(而非父組件)原點(左上角)的偏移。
  • DragUpdateDetails.delta:當用戶在屏幕上滑動時,會觸發屢次Update事件,delta指一次Update事件的滑動的偏移量。
  • DragEndDetails.velocity:該屬性表明用戶擡起手指時的滑動速度(包含x、y兩個軸的),示例中並無處理手指擡起時的速度,常見的效果是根據用戶擡起手指時的速度作一個減速動畫。

也很簡單,咱們主要看下onPanUpdate這個回調方法,在咱們手指滑動的過程當中,會屢次執行這個回調,在回調中咱們處理下x、y方向的偏移量讓後從新繪製就ok了。ui

偏移量打印:url

  •  單一方向拖動

上面的拖動是能夠往任意方向拖動的,在平常的開發中,有可能會遇到只容許水平(拼圖驗證)或豎直方向上進行拖動,DestureDetector也爲咱們提供了對應的響應事件:spa

看下demo示例:code

import 'package:flutter/material.dart';

class GestureDragDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _GestureDragDemoState();
  }
}

class _GestureDragDemoState extends State<GestureDragDemo> {
  double _top = 0.0; //距離頂部的偏移量
  double _left = 0.0; //距離底部的偏移量
  @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) {
                    //手指按下時會執行此回調
//                    print('手指按下的位置:$downDetails.globalPosition');
                  },
//                  onPanUpdate: (DragUpdateDetails dragUpdateDetails) {
//                    //手指滑動時會執行次回調
//                    setState(() {
//                      //手指滑動時會屢次觸發onPanUpdate回調,更新偏移量並從新繪製
//                      //dragUpdateDetails.delta.dx獲取y軸方向的偏移量
//                      _top += dragUpdateDetails.delta.dy;
//                      print('Y:$dragUpdateDetails.delta.dy');
//                      //dragUpdateDetails.delta.dy獲取x軸方向的偏移量
//                      _left += dragUpdateDetails.delta.dx;
//                      print('X:$dragUpdateDetails.delta.dx');
//                    });
//                  },
                onHorizontalDragUpdate: (DragUpdateDetails dragUpdateDetails){
                    setState(() {
                      _left += dragUpdateDetails.delta.dx;
                    });
                },
                  onPanEnd: (DragEndDetails dragEndDetails) {
                    //打印滑動結束時在x、y軸上的速度
//                    print(dragEndDetails.velocity);
                  },
                ),
              ),
            ],
          )),
    );
  }
}

 

  •  縮放
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(() {
                //縮放倍數在0.8到10倍之間
                _width=200*scaleUpdateDetails.scale.clamp(.8, 10.0);
              });
            },
          ),
        ),
      ),
    );
  }
}
相關文章
相關標籤/搜索