Flutter提供了强大的拖拽控件,可以灵活定制,并且非常简单。这节课就学习一下Flutter拖拽控件,并根据学到的知识作一个拖拽案例>
Draggable Widget
Draggable控件负责就是拖拽,父层使用了Draggable,它的子元素就是可以拖动的,子元素可以实容器,可以是图片。用起来非常的灵活。
参数说明:
- data: 是要传递的参数,在DragTarget里,会接受到这个参数。当然要在拖拽控件推拽到DragTarget的时候。
- child:在这里放置你要推拽的元素,可以是容器,也可以是图片和文字。
- feedback: 常用于反馈(设置)推拽元素时的样子,在案例中当推拽的时候,我们把它的颜色透明度变成了50%。当然你还可以改变它的大小。
- onDraggableCanceled:是当松开时的相应事件,经常用来改变推拽时到达的位置,改变时用setState来进行。
代码:
Draggable(
data:widget.widgetColor,
child: Container(
width: 100,
height: 100,
color:widget.widgetColor,
),
feedback:Container(
width: 100.0,
height: 100.0,
color: widget.widgetColor.withOpacity(0.5),
),
onDraggableCanceled: (Velocity velocity, Offset offset){
setState(() {
this.offset = offset;
});
},
DragTarget Widget
DragTarget是用来接收拖拽事件的控件,当把Draggable放到DragTarget里时,他会接收Draggable传递过来的值,然后用生成器改变组件状态。
- onAccept:当推拽到控件里时触发,经常在这里得到传递过来的值。
- builder: 构造器,里边进行修改child值。
DragTarget(onAccept: (Color color) {
_draggableColor = color;
}, builder: (context, candidateData, rejectedData) {
return Container(
width: 200.0,
height: 200.0,
color: _draggableColor,
);
}),
实例代码DEMO
主文件main.dart
import 'package:flutter/material.dart';
import 'drag_drop.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title:'Flutter Demo',
theme:ThemeData(
primarySwatch: Colors.blue
),
home:DraggableDemo()
);
}
}
drag_drop.dart 文件
import 'package:flutter/material.dart';
import 'draggable_widget.dart';
class DraggableDemo extends StatefulWidget {
@override
_DraggableDemoState createState() => _DraggableDemoState();
}
class _DraggableDemoState extends State<DraggableDemo> {
Color _draggableColor = Colors.pink[50];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
DraggableWidget(
offset: Offset(80.0, 80.0),
widgetColor: Colors.tealAccent,
),
DraggableWidget(
offset: Offset(180.0, 80.0),
widgetColor: Colors.redAccent,
),
DraggableWidget(
offset: Offset(280.0, 80.0),
widgetColor: Colors.red[100],
),
Center(
child: DragTarget(onAccept: (Color color) {
_draggableColor = color;
}, builder: (context, candidateData, rejectedData) {
return Container(
width: 200.0,
height: 200.0,
color: _draggableColor,
);
}),
)
],
));
}
}
draggable_widget.dart 文件
import 'package:flutter/material.dart';
class DraggableWidget extends StatefulWidget {
final Offset offset;
final Color widgetColor;
const DraggableWidget({Key key, this.offset, this.widgetColor})
: super(key: key);
_DraggableWidgetState createState() => _DraggableWidgetState();
}
class _DraggableWidgetState extends State<DraggableWidget> {
Offset offset = Offset(0.0, 0.0);
@override
void initState() {
super.initState();
offset = widget.offset;
}
@override
Widget build(BuildContext context) {
return Positioned(
left: this.offset.dx,
top: this.offset.dy,
child: Draggable(
data: widget.widgetColor,
child: Container(
width: 100,
height: 100,
color: widget.widgetColor,
),
feedback: Container(
width: 100.0,
height: 100.0,
color: widget.widgetColor.withOpacity(0.5),
),
onDraggableCanceled: (Velocity velocity, Offset offset) {
setState(() {
//这里可以做拖拽到拖拽区块时候的判断
if (true) {
this.offset = offset;
}
});
},
),
);
}
}
JavaScript中的拖拽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<style>
div {
width: 100px;
height: 100px;
border: 1px solid red;
float: left;
border-left: 0;
border-top: 0
}
img {
width: inherit;
height: inherit;
}
</style>
<body>
<div id="div1" class="q" ondragover="allowDrop(event)" ondrop="drop(event)"><img id="drag1"
src="http://n.sinaimg.cn/sinakd10112/175/w1080h1495/20200326/f2ac-irkazzv3170145.jpg" draggable="true"
ondragstart="drag(event)" width="200" height="200" /></div>
<div id="div2" ondragover="allowDrop(event)" ondrop="drop(event)"><img id="drag2"
src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1585323091847&di=552aae10f464e9ca90e91920c450060e&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20171120%2F5bbe5a3c8b26408095e60d8f8af0d239.jpeg"
draggable="true" ondragstart="drag(event)" width="200" height="200" /></div>
</body>
</html>
<script>
for (let i = 0; i < 10; i++) {
// $("body").append("<div ondragover='allowDrop(event)' ondrop='drop(event)'></div>")
var eDiv = document.createElement("div")
eDiv.setAttribute('ondragover', 'allowDrop(event)')
eDiv.setAttribute('ondrop', 'drop(event)')
document.querySelector("body").append(eDiv)
console.log(eDiv.attributes);
}
/*
拖事件 图片
1 设置图片允许拖动
draggable="true"
2 拖的时候保存数据(图片id)
ev.dataTrasfer.setData('credential凭据',ev.target.id);
放置事件 DIV
1允许图片放置这里
ondragover="allowDrop()"
allowDrop里面是一个阻止浏览器默认操作
function allowDrop(ev){
ev.preventDefault();
}
2 放置图片时
ondrop="drop(ev)"
function drop(ev{
ev.preventDefalut(); //阻止浏览器默认操作
var data=ev.dataTransfer.getData('credential凭据');//获取前面保存的数据
ev.target.appendChild(document.getElementById(data));// DIV追加子元素
}
*/
var img, div;
function drag(ev) {
ev.dataTransfer.setData("credential凭据", ev.target.id);
img = ev.target;
}
function allowDrop(ev) { ev.preventDefault(); }
function drop(ev) {
if (ev.target.nodeName == "DIV") {
ev.preventDefault();
iSrc = ev.target.src;
var data = ev.dataTransfer.getData("credential凭据");
ev.target.appendChild(document.getElementById(data));
}
else if (ev.target.nodeName == "IMG") {
iSrc = img.src;
img.src = ev.target.src;
ev.target.src = iSrc;
}
// console.log(ev.tatrget);
}
</script>