美文网首页
Flutter中Draggable和DragTarget组合成一

Flutter中Draggable和DragTarget组合成一

作者: 平静的阿卿达 | 来源:发表于2018-10-09 19:15 被阅读67次

本例使用Draggable和DragTarget嵌套使用,完成一个可拖拽并且可接受数据的Widget

用DragTarget作为Draggable的child,真正展示的UI通过DragTarget的builder来完成。

本例效果如下:

有上下两个可拖拽的Widget,都可以接收拖拽过来的数据并处理。


Draggable3.gif Draggable4.gif

和之前一样,先来一个空白页。

void main() => runApp(new MyApp());

///用于展示Demo的界面,其中的MaterialApp、ThemeData、AppBar都是不必要的,只是稍微美观一点。
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Scaffold(
          appBar: new AppBar(
            title: new Text("DraggableDemo"),
          ),
//          body: MyDraggable()),
//          body: Drag2TargetPage()),
          body: DraggableItemDemo()),//这个是Draggable和DragTarget的组合Widget
    );
  }
}

由于组合后的Widget是需要状态可变的,使用StatefulWidget作为父类。
将上一篇中的DragTarget作为Draggable的child,DragTarget的构成可以保持不变。

class MyDraggableTarget<T> extends StatefulWidget {
  final T data;

  MyDraggableTarget({@required this.data, Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _MyDraggableTargetState(text: data);
}

class _MyDraggableTargetState extends State<MyDraggableTarget> {
  var text;

  _MyDraggableTargetState({@required this.text});
  @override
  Widget build(BuildContext context) {
    return Draggable(
      data: text,
      child: Container(//仅用于保持样式,可以使用DragTarget作为直接child。
        width: 150.0,
        height: 150.0,
        color: Colors.red[500],
        child: DragTarget(
          onWillAccept: (data) {
            print("data = $data onWillAccept");
            return data != null;
          },
          onAccept: (data) {
            print("data = $data onAccept");
            setState(() {
              text = data;
            });
          },
          onLeave: (data) {
            print("data = $data onLeave");
          },
          builder: (context, candidateData, rejectedData) {
            return Container(
              width: 150.0,
              height: 150.0,
              color: Colors.blue[500],
              child: Center(
                child: Text(text),
              ),
            );
          },
        ),
      ),
      feedback: Container(
        width: 150.0,
        height: 150.0,
        color: Colors.blue[500],
        child: Icon(Icons.feedback),
      ),
    );
  }
}

这样一个可拖拽可接受数据的Widget就组合好了,
使用一个Column存放两个这样的Widget,即可实现互相拖动和接收。


class DraggableItemDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Divider(),
        MyDraggableTarget(
          data: "123",
        ),
        Divider(),
        MyDraggableTarget(
          data: "456",
        ),
      ],
    );
  }
}

基于这样一个组合Widget,我们可以尝试让ListView/GridView的item可拖动,进而实现拖动排序。

相关文章

网友评论

      本文标题:Flutter中Draggable和DragTarget组合成一

      本文链接:https://www.haomeiwen.com/subject/eqeyaftx.html