Flutter:如何響應互動事件?

CoorChice發表於2019-04-06

目錄傳送門:《Flutter快速上手指南》先導篇

思考一個問題,在 Flutter 中如何處理點選、長按等手勢互動呢 ? ?

事實上,Flutter 提供了多種處理手勢互動的方案,本篇文章介紹一種比較通用和全能的方案: GestureDetector

使用 GestureDetector 可以獲得各種型別的點選事件回撥,因此你可以建立出能夠處理各種點選事件的 Widget 來。

1.GestureDetector 常用手勢

現在,看看 GestureDetector 有些什麼常用的互動事件吧:

  • onTap:單擊

  • onDoubleTap:雙擊

  • onLongPress:長按

  • onTapUp:手指抬起來時

  • onTapDown:手指觸碰螢幕時

  • onTapCancel:點選沒有完成

  • onVerticalDragDown:手指剛接觸螢幕時,隨後開始垂直方向上的拖動

  • onVerticalDragStart:垂直方向上的拖動開始時

  • onVerticalDragUpdate:垂直方向上的拖動更新時

  • onVerticalDragEnd:垂直方向上的拖動結束時

  • onVerticalDragCancel:垂直拖動沒有完成

  • onHorizontallyDragDown:手指剛接觸螢幕時,隨後開始水平方向上的拖動

  • onHorizontallyDragStart:水平方向上的拖動開始時

  • onHorizontallyDragUpdate:水平方向上的拖動更新時

  • onHorizontallyDragEnd:水平方向上的拖動結束時

  • onHorizontallyDragCancel:水平拖動沒有完成

  • onScaleStart:開始縮放時,初始 scale 為 1.0

  • onScaleUpdate:縮放更新時

  • onScaleEnd:縮放結束

  • onPanDown:手指觸控螢幕時

  • onPanUpdate:手指移動時

  • onPanEnd:滑動結束時

2.如何使用 GestureDetector

  1. 使用 GestureDetector 建立一個可互動的 Widget。

    class TapBox extends StatefulWidget {
    
      final bool active;
      // 定義一個函式,外界傳入後可被呼叫
      final ValueChanged<bool> onChanged;
    
      TapBox({Key key, this.active, this.onChanged}) : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        return _TabBox();
      }
    }
    
    class _TabBox extends State<TapBox> {
      bool _highlight = false;
    
      void _handleTapDown(TapDownDetails details) {
        setState(() {
          _highlight = true;
        });
      }
    
      void _handleTapUp(TapUpDetails details) {
        setState(() {
          _highlight = false;
        });
      }
    
      void _handleTapCancel() {
        setState(() {
          _highlight = false;
        });
      }
    
      void _handleTap() {
        // 通過 widget 可以獲得其成員變數
        widget.onChanged(!widget.active);
      }
    
      Widget build(BuildContext context) {
        // 把你的 Widget 使用 GestureDetector 包裹?起來
        return GestureDetector(
          // 處理按下手勢
          onTapDown: _handleTapDown,
          // 處理抬起手勢
          onTapUp: _handleTapUp,
          // 處理點選手勢
          onTap: _handleTap,
          // 處理取消手勢
          onTapCancel: _handleTapCancel,
          child: Container(
            child: Center(
              child: Text(widget.active ? 'Active' : 'Inactive',
                  style: TextStyle(fontSize: 32.0, color: Colors.white)),
            ),
            width: 200.0,
            height: 200.0,
            decoration: BoxDecoration(
              color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
              border: _highlight
                  ? Border.all(
                      color: Colors.teal[700],
                      width: 10.0,
                    )
                  : null,
            ),
          ),
        );
      }
    }
    複製程式碼

    你看,GestureDetector 也是一個 Widget,通過使用它來包裹目標 Widget,就使得目標 Widget 具有處理事件的能力。

  2. 使用這個 Widget。

    class ParentWidget extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _ParentWidget();
      }
    }
    
    class _ParentWidget extends State<ParentWidget> {
      bool _active = false;
    
      void _handleTapBoxChanged(bool newValue) {
        setState(() {
          _active = newValue;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: TapBox(
            active: _active,
            // 傳入函式
            onChanged: _handleTapBoxChanged,
          ),
        );
      }
    }
    複製程式碼

    執行效果:

目錄傳送門:《Flutter快速上手指南》先導篇

如何找到我?

傳送門:CoorChice 的主頁

傳送門:CoorChice 的 Github


相關文章