您好,歡迎關注我,本文章是關於 Flutter 的系列文,從簡單的 Flutter 介紹開始,一步步帶你瞭解進入 Flutter 的世界。你最好有一定的移動開發經驗,如果沒有也不要擔心,在我的專欄底部給我留言,我會盡我的能力給你解答。
上一篇專欄,是教大家如何實現Flutter的主題。本專欄介紹在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中的動畫,並接着本次拖拽的例子實現鬆手後的動畫特效。