Flutter 實現 View 的移動拖拽

您好,歡迎關注我,本文章是關於 Flutter 的系列文,從簡單的 Flutter 介紹開始,一步步帶你瞭解進入 Flutter 的世界。你最好有一定的移動開發經驗,如果沒有也不要擔心,在我的專欄底部給我留言,我會盡我的能力給你解答。

上一篇專欄,是教大家如何實現Flutter的主題。本專欄介紹在Flutter中如何拖拽View,並講解會遇到的坑。

先來看效果:
Flutter 實現 View 的移動拖拽
第一步
在main方法中用MaterialApp和Scaffold作爲應用主框架,這裏我就不詳細展開說明了,這樣做主要是爲了顯示效果更好,你可以使用你熟悉的Widget控件完成。

void main() {
    runApp(MaterialApp(
        home: Scaffold(
            body: xxx
        )
    ));
}

第二步
自定義MyDragWidget類,集成StatefulWidget類,主要是爲了獲取手勢座標之後調用setState()方法刷新Widget的位置。

class MyDragWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyDragState();
}

class MyDragState extends State<MyDragWidget> {
    @override
    Widget build(BuildContext context) {
        return xxx;
    }
}

第三步
使用GestureDetector作爲父容器監聽手勢。

@override
Widget build(BuildContext context) {
    return GestureDetector(
        onHorizontalDragUpdate: dragEvent,
        onVerticalDragUpdate: dragEvent,
        child: xxx
    );
}

void dragEvent(DragUpdateDetails details) {
    final RenderObject box = context.findRenderObject();
    //  獲得自定義Widget的大小,用來計算Widget的中心錨點
    dx = details.globalPosition.dx - mykey.currentContext.size.width / 2;
    dy = details.globalPosition.dy - mykey.currentContext.size.height / 2;
    setState(() {});
  }

GestureDetector類是Flutter中處理手勢的Widget,它包括了我們常用到的手勢事件回調,例如:
onTap、onTapDown、onTapUp、onTapCancel、onDoubleTap、onLongPress等一系列手勢。
我們通過該類的這些回調方法可以直接獲取手勢座標以便處理。
比如我們例子中就要用到onHorizontalDragUpdate和onVerticalDragUpdate這兩個回調來處理Widget的拖動。
第四步
使用Transform.translate方法來移動Widget,通常我們會使用margin或者padding來移動Widget,剛開始我也是這麼做的,但是隨之而來的就是各種坑,比如明明固定了子Widget的大小,但是隨着padding或margin的改變Widget的大小也隨之改變了。而API提供的Transform.translate方法正是用來移動Widget的。

另外或許你還會遇到一個坑,那就是不管怎麼給Container容器設置高和寬都不生效。原因就是使用MaterialApp作爲基礎容器之後,系統默認會讓Container撐滿,無論怎麼設置高和寬都沒有效果,必須用Align Widget包一層纔可以。

也許你會思考在Flutter中如何像Android的findViewById一樣找到一個Widget的實例。你需要在Widget初始化的時候創建一個GlobalKey,就像這樣:final mykey = new GlobalKey<MyDragState>();然後在new Widget的時候設置進key,就像下面代碼一樣。

@override
  Widget build(BuildContext context) {
    return GestureDetector(
      onHorizontalDragUpdate: dragEvent,
      onVerticalDragUpdate: dragEvent,
      child: Container(
        color: Colors.red,
        child: Transform.translate(
          offset: Offset(dx, dy),
          child: Align(
            alignment: Alignment.topLeft,
            child: Container(
              width: 150.0,
              height: 100.0,
              alignment: Alignment.center,
              key: mykey,
              color: Colors.yellow,
              child: Text("Drag Box"),
            ),),),),);
  }

至此,就實現了Flutter拖動Widget。下一篇專欄會介紹Flutter中的動畫,並接着本次拖拽的例子實現鬆手後的動畫特效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章