Flutter 拖拽控制元件Draggable看這一篇就夠了

mengqingdong1發表於2020-03-10

注意:無特殊說明,Flutter版本及Dart版本如下:

  • Flutter版本: 1.12.13+hotfix.5
  • Dart版本: 2.7.0

Draggable系列元件可以讓我們拖動元件。

Draggable

Draggable元件有2個必須填寫的引數,child引數是子控制元件,feedback引數是拖動時跟隨移動的元件,用法如下:

Draggable(
  child: Container(
    height: 100,
    width: 100,
    alignment: Alignment.center,
    decoration: BoxDecoration(
      color: Colors.red,
      borderRadius: BorderRadius.circular(10)
    ),
    child: Text('孟',style: TextStyle(color: Colors.white,fontSize: 18),),
  ),
  feedback: Container(
    height: 100,
    width: 100,
    alignment: Alignment.center,
    decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(10)
    ),
    child: Text('孟',style: TextStyle(color: Colors.white,fontSize: 18),),
  ),
)複製程式碼

效果如下:

藍色的元件是feedback,如果想在拖動的時候子元件顯示其他樣式可以使用childWhenDragging引數,用法如下:

Draggable(
  childWhenDragging: Container(
    height: 100,
    width: 100,
    alignment: Alignment.center,
    decoration: BoxDecoration(
        color: Colors.grey, borderRadius: BorderRadius.circular(10)),
    child: Text(
      '孟',
      style: TextStyle(color: Colors.white, fontSize: 18),
    ),
  ),
  ...
)複製程式碼

效果如下:

我們還可以控制拖動的方向,比如只允許垂直方向移動,程式碼如下:

Draggable(
  axis: Axis.vertical,
  ...
)複製程式碼

Draggable元件為我們提供了4中拖動過程中的回撥事件,用法如下:

Draggable(
  onDragStarted: (){
    print('onDragStarted');
  },
  onDragEnd: (DraggableDetails details){
    print('onDragEnd:$details');
  },
  onDraggableCanceled: (Velocity velocity, Offset offset){
    print('onDraggableCanceled velocity:$velocity,offset:$offset');
  },
  onDragCompleted: (){
    print('onDragCompleted');
  },
  ...
)複製程式碼

說明如下:

  • onDragStarted:開始拖動時回撥。
  • onDragEnd:拖動結束時回撥。
  • onDraggableCanceled:未拖動到DragTarget控制元件上時回撥。
  • onDragCompleted:拖動到DragTarget控制元件上時回撥。

Draggable有一個data引數,這個引數是和DragTarget配合使用的,當使用者將控制元件拖動到DragTarget時此資料會傳遞給DragTarget。

DragTarget

DragTarget就像他的名字一樣,指定一個目的地,Draggable元件可以拖動到此控制元件,用法如下:

DragTarget(
  builder: (BuildContext context, List<dynamic> candidateData,
      List<dynamic> rejectedData) {
      ...
  }
)複製程式碼

onWillAccept返回true時, candidateData引數的資料是Draggable的data資料。

onWillAccept返回false時, rejectedData引數的資料是Draggable的data資料,

DragTarget有3個回撥,說明如下:

  • onWillAccept:拖到該控制元件上時呼叫,需要返回true或者false,返回true,鬆手後會回撥onAccept,否則回撥onLeave。
  • onAccept:onWillAccept返回true時,使用者鬆手後呼叫。
  • onLeave:onWillAccept返回false時,使用者鬆手後呼叫。

用法如下:

var _dragData;

@override
Widget build(BuildContext context) {
  return Center(
    child: Column(
      children: <Widget>[
        _buildDraggable(),
        SizedBox(
          height: 200,
        ),
        DragTarget<Color>(
          builder: (BuildContext context, List<Color> candidateData,
              List<dynamic> rejectedData) {
            print('candidateData:$candidateData,rejectedData:$rejectedData');
            return _dragData == null
                ? Container(
                    height: 100,
                    width: 100,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        border: Border.all(color: Colors.red)),
                  )
                : Container(
                    height: 100,
                    width: 100,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                        color: Colors.red,
                        borderRadius: BorderRadius.circular(10)),
                    child: Text(
                      '孟',
                      style: TextStyle(color: Colors.white, fontSize: 18),
                    ),
                  );
          },
          onWillAccept: (Color color) {
            print('onWillAccept:$color');
            return true;
          },
          onAccept: (Color color) {
            setState(() {
              _dragData = color;
            });
            print('onAccept:$color');
          },
          onLeave: (Color color) {
            print('onLeave:$color');
          },
        ),
      ],
    ),
  );
}

_buildDraggable() {
  return Draggable(
    data: Color(0x000000FF),
    child: Container(
      height: 100,
      width: 100,
      alignment: Alignment.center,
      decoration: BoxDecoration(
          color: Colors.red, borderRadius: BorderRadius.circular(10)),
      child: Text(
        '孟',
        style: TextStyle(color: Colors.white, fontSize: 18),
      ),
    ),
    feedback: Container(
      height: 100,
      width: 100,
      alignment: Alignment.center,
      decoration: BoxDecoration(
          color: Colors.blue, borderRadius: BorderRadius.circular(10)),
      child: DefaultTextStyle.merge(
        style: TextStyle(color: Colors.white, fontSize: 18),
        child: Text(
          '孟',
        ),
      ),
    ),
  );
}複製程式碼

效果如下:

LongPressDraggable

LongPressDraggable繼承自Draggable,因此用法和Draggable完全一樣,唯一的區別就是LongPressDraggable觸發拖動的方式是長按,而Draggable觸發拖動的方式是按下。

今天的文章對大家是否有幫助?如果有,請在文章底部留言和點贊,以表示對我的支援,你們的留言、點贊和轉發關注是我持續更新的動力! 我建立了一個關於Flutter的微信交流群,歡迎您的加入,讓我們一起學習,一起進步,開始我們的故事,生活不止眼前的苟且,還有詩和《遠方》。 ==微信:mqd_zzy==

當然我也非常希望您關注我個人的公眾號,裡面有各種福利等著大家哦。

相關文章