Flutter實戰之手勢基礎篇

JulyYu 發表於 2019-08-11

前言

日常開發應用中少不了互動功能,而互動就包括了點選觸碰。比如點選一個按鈕對操作做出響應又或者是拖拽列表做下拉重新整理操作等一些常規互動的實現離不開手勢功能。那麼在Flutter中是如何實現通過手勢操作實現互動操作的,下面就來介紹一下Flutter手勢功能。

手勢(GestureDetector)

Flutter通過使用GestureDetector元件使得其他Widget支援手勢功能。手勢可以響應多種操作,主要分為以下幾類:Tap、Double tap、Long press、Vertical drag、Horizontal drag、Pan。同時可以通過動作分為點選、雙擊、長按、拖拽、縮放等。

點選(Tap)& 雙擊(DoubleTap)& 長按(LongPress)

通用的操作方法,例如點選、雙擊、長按功能,只需要編寫Function就能實現功能。當然在這些操作過程中也具備中間過程的狀態監聽,例如點選按下時,抬起時,取消點選等。

Flutter實戰之手勢基礎篇

GestureDetector(
  onTap: (){
    showSnack(context, "OnTap");
  },
  onDoubleTap: (){
    showSnack(context, "onDoubleTap");
  },
  onLongPress: (){
    showSnack(context, "onLongPress");
  },
  child: Transform.translate(
    offset: offset,
    child: Text(
      "Transform",
      style: TextStyle(fontSize: 25),
    ),
  ),
);
複製程式碼

拖拽(Drag)

GestureDetector為拖拽功能提供水平方向拖拽(Horizontal drag)、垂直方向拖拽(Vertical drag)、同時支援兩個方向拖拽(Pan)。

Flutter實戰之手勢基礎篇
水平和垂直兩個拖拽監聽只能獲取對應方向偏移量變化,對應的垂直方向的數值返回始終為0,若在開發需求中若同時需要監聽兩個方向則推薦使用綜合拖拽監聽回撥Pan同時監聽水平和垂直方向的偏移量的變化。

在監聽中Down、Start、Update三個過程可以監聽到Details物件,從而知道當前手勢定位值對於元件頂點位置的偏移量。

偏移量

在GestureDetector中兩個重要屬性值globalPosition和localPosition,兩者都是Offset物件。globalPosition就像它的命名錶示當前手勢觸點在全域性座標系位置與對應元件頂點座標的偏移量(dx,dy),而localPosition則就表示當前手勢觸點在對應元件座標系位置與對應元件頂點座標的偏移量(dx,dy)也就是說如果當前手勢位置在元件頂點座標那麼dx和dy都為0。

例如如下程式碼中,為Container設定了GestureDetector手勢監聽,在update回撥中獲取updateDetail物件,在Text中顯示globalPosition偏移量。從中獲取到的globalPosition和localPosition中dx都是相同值,dy卻不同。也就是因為Scaffold中設定了AppBar,相對於body他的全域性座標系並非它自身。但若將Scaffold中的AppBar去除,讓body撐滿整個Scaffold,那麼在手勢監聽中獲取到的globalPosition和localPosition將相同。

需要注意的是對於globalPosition在安卓中還包含了手機狀態列的高度。

MaterialApp(
      theme: AppTheme.themes[store.state.appThemeState.themeType],
      home: Scaffold(
        appBar: AppBar(),
        body: GestureDetector(
          onPanStart: (detail) {
            showLog(detail.runtimeType, detail.localPosition,
                detail.globalPosition);
          },
          onPanUpdate: (detail) {
            showLog(detail.runtimeType, detail.localPosition,
                detail.globalPosition);
            setState(() {
              offsetText = "globalPosition: ${Offset(detail.globalPosition.dx, detail.globalPosition.dy).toString()} \n"
                  "localPosition: ${Offset(detail.localPosition.dx, detail.localPosition.dy).toString()}";
            });
          },
          onPanEnd: (detail) {
            setState(() {
              offsetText = "end";
            });
          },
          child: Container(
            color: Colors.red,
            width: double.infinity,
            height: double.infinity,
            child: Center(
              child: Text(
                 offsetText,
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 25,
                ),
              ),
            ),
          ),
        ),
      ),
    );
複製程式碼

可以看到當Scaffold包含和未包含AppBar時,Container兩個偏移量輸出的差異。

Flutter實戰之手勢基礎篇 Flutter實戰之手勢基礎篇

縮放(Scale)

縮放操作則需要兩個指標物件配合才能發揮作用。當在螢幕上只有一個指標物件時也就是一個觸點時,對應的縮放比為1和角度為0;當螢幕上出現兩個指標物件時,根據兩個初始位置作為基準點,也就是起始位置初始化縮放比為1和角度為0,通過手勢變化得出兩點的距離位置和夾角大小來計算縮放比和角度值。

Flutter實戰之手勢基礎篇 Flutter實戰之手勢基礎篇
GestureDetector(
          onScaleStart: (detail) {
            print(detail);
            setState(() {
              offsetText = "focalPoint: ${detail.focalPoint.toString()} \n"
                  "localFocalPoint: ${detail.localFocalPoint.toString()}";
            });
          },
          onScaleUpdate: (details) {
            print(details);
            Vector.Matrix3 matrix3 = Vector.Matrix3.zero();
            setState(() {
              offsetText = "focalPoint: ${details.focalPoint.toString()} \n"
                  "localFocalPoint: ${details.localFocalPoint.toString()}";
              scaleUpdateDetails = details;
            });
          },
          onScaleEnd: (details) {
            print(details);
            setState(() {
              scaleUpdateDetails = ScaleUpdateDetails();
            });
          },
          child: Container(
            color: Colors.red,
            width: double.infinity,
            height: double.infinity,
            child: Center(
                // 元件的動畫效果
              child: Transform(
                transform: Matrix4.rotationZ(scaleUpdateDetails.rotation)
                    .scaled(
                        scaleUpdateDetails.scale),
                child: Text(
                  offsetText,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20,
                  ),
                ),
              ),
            ),
          ),
        ),
複製程式碼

在onScaleUpdate方法中獲取ScaleUpdateDetails物件,其包含了兩觸點實現的縮放值scale、角度值rotation、偏移量focalPoint資訊。通過上述程式碼並可實現手勢再結合上Transform的元件動效,關於Transform做過多介紹,主要為實現元件動畫效果的元件之後若有時間再做學習。

Flutter實戰之手勢基礎篇

結尾

這篇只能算是手勢功能基礎篇,還有一些手勢高階功能實現未探究類似於Android中的手勢衝突等一些功能性自定義開發,暫且先熟悉手勢基本功能之後若有對這方面開發需求再做更深層次學習和研究。


相關文章

Flutter 滾動控制元件篇-->ListView Flutter

Flutter 滾動控制元件篇-->ListView

Flutter 中的ListView是最常用的可滾動的元件之一,它可以沿一個方向線性排布所有子元件,並且它也支援基於Sliver的延遲構建模型。基於Sliver的延遲構建什麼是基於Sliver的延遲構
Flutter學習系列之Flutter上手環境準備 Flutter

Flutter學習系列之Flutter上手環境準備

記錄一下入門flutter的過程,遇到的問題以及解決的辦法。一、本地環境Windows10 + 牆內+Android Studio。二、安裝Flutter映象環境國內環境需要配置一下以下映象環境。PU
Flutter 基礎控制元件篇-->進度指示器 Flutter

Flutter 基礎控制元件篇-->進度指示器

Flutter 中的Material 元件庫中提供了兩種進度指示器:LinearProgressIndicator和CircularProgressIndicator。它們都可以同時用於精確的進度指示
flutter新手集訓營(上) Flutter

flutter新手集訓營(上)

前端開發是否迎來大統一?flutter是否可以勝任原生開發的效能?帶著一個有一個的疑問,去了解flutter。flutter開發語言上的選擇。為什麼最終使用了dart一個曾經js熱度大增的時刻卻不溫不
Flutter 基礎控制元件篇-->輸入框(TextField)、表單(Form) Flutter

Flutter 基礎控制元件篇-->輸入框(TextField)、表單(Form)

Flutter 的Material元件庫中提供了輸入框元件TextField和表單元件Form。輸入框(TextField)TextField主要用於文字輸入。原始碼示例建構函式如下:const Te
Flutter(十一)之封裝幾個小Widget Flutter

Flutter(十一)之封裝幾個小Widget

更新地點: 首發於公眾號,第二天更新於掘金、思否、開發者頭條等地方;更多交流: 可以新增我的微信 372623326,關注我的微博:coderwhy學習完列表渲染後,我打算做一個綜合一點的練習小專案:
Flutter(十二)之練習高仿豆瓣電影列表 Flutter

Flutter(十二)之練習高仿豆瓣電影列表

更新地點: 首發於公眾號,第二天更新於掘金、思否、開發者頭條等地方;更多交流: 可以新增我的微信 372623326,關注我的微博:coderwhy由於Mac的檔期問題(Mac忙其他前些的),這裡給出
Flutter動畫實現粒子漂浮效果 Flutter

Flutter動畫實現粒子漂浮效果

本文所有原始碼見github.com/MoonRiser/F…要問2019年最火的移動端框架,肯定非Google的Flutter莫屬。本著學習的態度,基本的Dart語法(個人感覺語法風格接近Java+
flutter 支付寶APP支付 (包含後臺) Flutter

flutter 支付寶APP支付 (包含後臺)

支付寶app支付,最全攻略,看完了你就會了,這裡就是實際執行把每一步都寫下來,和看視訊是沒有區別的,而且我這個是一個系列,歡迎關注,點贊最好啦。博主這裡全部都是一字不漏的,和操作一個不漏的記錄下來,並
FLUTTER混合工程踩坑之旅 Flutter

FLUTTER混合工程踩坑之旅

簡介Flutter 是 Google推出並開源的移動應用開發框架,主打跨平臺、高保真、高效能。開發者可以通過 Dart語言開發 App,一套程式碼同時執行在 iOS 和 Android平臺。 Flut
Flutter很好用,but…… Flutter

Flutter很好用,but……

前言為什麼有這篇文章?這篇文章可以說是個人Flutter問題隨筆吧,雖然Flutter可以方便的做到跨平臺,但是畢竟是新專案,功能沒那麼全面也是意料之中,所以在此記錄跟蹤一下目前在使用Flutter過
把Flutter擴充套件到微信小程式端的探索 Flutter

把Flutter擴充套件到微信小程式端的探索

Google Flutter是一個非常優秀的跨端框架,不僅可以執行在Android、 iOS平臺,而且可以支援Web和桌面應用。在國內小程式是非常重要的技術平臺,我們也一直思考能否把Flutter擴充