Flutter--手勢

2020-10-15 15:00:01

手勢

說明:

Flutter的手勢系統分為兩層,第一層是觸控原事件(指標),有相應的四種事件型別:

  1. PointerDownEvent:使用者與螢幕接觸產生了聯絡;
  2. PointerMoveEvent:手指已從螢幕上的一個位置移動到另一個位置;
  3. PointUpEvent:使用者已停止接觸控螢幕幕;
  4. PointerCancelEvent:此指標的輸入不再指向此應用程式。

第二層就是我們可以檢測到的手勢,主要分為三大類,包括輕擊、拖動和縮放

下面,我們來學習GestureDetector(進行手勢檢測)、Dismissible(實現滑動刪除)

用GestureDetector進行手勢檢測

手勢事件以及描述表:

事件名描述
onTapDown點選螢幕立即觸發此方法
onTapUp手指離開螢幕
onTap點選螢幕
onTapCancel此次點選事件結束,onTapDown不會再產生點選事件
onDoubleTap使用者快速連續兩次在同一位置點選螢幕
onLongPress長時間保持與相同位置的螢幕接觸
onVerticalDragStart與螢幕接觸,可能會開始垂直移動
onVerticalDragUpdate與螢幕接觸並垂直移動的指標在垂直方向上移動
onVerticalDragEnd之前與螢幕接觸並垂直移動的指標不再與螢幕接觸,並且在停留接觸控螢幕幕時以特定的速度移動垂直拖動
onHorizontalDragStart與螢幕接觸,可能開始水平移動
onHorizontalDragUpdate與螢幕接觸並水平移動的指標在水平方向上移動
onHorizontalDragEnd先前與螢幕接觸並且水平移動的指標不再與螢幕接觸,並且當它停止接觸控螢幕幕時以特定速度移動水平拖動

例子:製作一個自定義的按鈕,當點選時顯示文字「你已按下」

​ 程式碼:

main.dart

import 'package:flutter/material.dart';
import 'package:route_page/route/page_jumps.dart';
import 'package:route_page/route/return_message.dart';
import 'package:route_page/route/send_message.dart';

import 'gesture/test_button.dart';

void main() {
  runApp(
  //   new MaterialApp(
  //   title: "導航頁面範例",
  //   home: new FirstScreen(),
  // )
  //   new MaterialApp(
  //     title: "傳遞資料範例",
  //     home: new ProductList(
  //         products:
  //         new List.generate(20, (i) => new Product('商品 $i', "這是一個商品詳情 $i"))),
  //   )
  //   new MaterialApp(
  //     title: '頁面跳轉發、返回資料',
  //     home: new FirstPage(),
  //   )
      new MaterialApp(
        title: '頁面跳轉發、返回資料',
        home: new MyButton(),
      )
  );
}

test_button.dart

import 'package:flutter/material.dart';
class MyButton extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text("按下處理Demo"),
      ),

    //   注意:在同一個函數中實際建立了Scaffold時,該build函數的context引數不能用於查詢Scaffold
    // (因為它在小部件樹返回的小部件上方)。在這種情況下,可以使用帶有Builder來提供一個行的作用域,該作用域具有位於Scaffold下方的BuildContext.
      body: Builder(
        builder: (BuildContext context){
          return new Center(
            // 一定要把被觸控的元件放在GestureDetector中
            child: GestureDetector(
              onTap: (){
                // 底部資訊揭示
                final snackBar = new SnackBar(content: new Text("你已按下按鈕"));
                Scaffold.of(context).showSnackBar(snackBar);
              },
              // 容器接收觸控動作
              child: new Container(
                child: new Text("測試按鈕"),
                padding: EdgeInsets.all(12.0),
                decoration: BoxDecoration(
                    color: Theme.of(context).buttonColor,
                    borderRadius: new BorderRadius.circular(10.0)
                ),
              ),
            ),
          );
        },
      )
    );
  }
}

用Dismissible實現滑動刪除

  1. Dismissible元件屬性及描述表

    屬性名型別說明
    onDismissedDismissDirectionCallback當包裹的元件消失後回撥的函數
    movementDurationDuration定義元件訊息的時長
    onResizeVoidCallback元件大小改變時回撥的函數
    resizeDurationDuration元件大小改變時長
    childWidget元件包裹的子元素,即被隱藏的對像
  2. 例子:實現滑動列表中的某一項資料,就可以刪除的效果

    main.dart

    iimport 'package:flutter/material.dart';
    import 'package:route_page/route/page_jumps.dart';
    import 'package:route_page/route/return_message.dart';
    import 'package:route_page/route/send_message.dart';
    
    import 'gesture/dismissible.dart';
    import 'gesture/test_button.dart';
    
    void main() {
      runApp(
      //   new MaterialApp(
      //   title: "導航頁面範例",
      //   home: new FirstScreen(),
      // )
      //   new MaterialApp(
      //     title: "傳遞資料範例",
      //     home: new ProductList(
      //         products:
      //         new List.generate(20, (i) => new Product('商品 $i', "這是一個商品詳情 $i"))),
      //   )
      //   new MaterialApp(
      //     title: '頁面跳轉發、返回資料',
      //     home: new FirstPage(),
      //   )
      //     new MaterialApp(
      //       title: '頁面跳轉發、返回資料',
      //       home: new MyButton(),
      //     )
          new MaterialApp(
            title: '  滑動刪除範例',
            home: new MyApp(),
          )
      );
    }
    
    
    

    dismissible.dart

    import 'package:flutter/material.dart';
    class MyApp extends StatelessWidget{
      List<String> items = new List<String>.generate(30, (i) => "列表項 ${i+1}");
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          appBar: AppBar(
            title: Text("滑動刪除範例"),
          ),
        //   使用ListView.builder生成列表,將列表中的每一項子項(ListTile)包裝在Dismissible中;
        // 在onDismissed執行真正的刪除操作
          body: new ListView.builder(
            itemCount: items.length,//決定itemBuilder回撥函數的次數
            itemBuilder: (context,index){
              final item = items[index];
              // 對需要實現滑動清除的Widget包裝在child中
              return new Dismissible(
                  key: new Key(item),//key是widget的唯一標示,因為有了key,widget tree才知道我們刪除了什麼widget
                  // 可以被刪除的元件
                  child: new ListTile(title: new Text('$item'),),
                  // 完成清除後,進行的操作
                  onDismissed: (direction){
                    // 刪除後重新整理列表,已到達真正的刪除
                    items.removeAt(index);
                    Scaffold.of(context).showSnackBar(new SnackBar(content: new Text("$item 被刪除來")));
                },
              );
            },
          )
        );
      }
    }
    

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-ibZZnPU4-1602670548406)(/Users/bf/Library/Application Support/typora-user-images/image-20201014163820440.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-tNfDmszk-1602670548411)(/Users/bf/Library/Application Support/typora-user-images/image-20201014163843086.png)]