- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想将一个列表项拖到另一个可能为空的列表中。如果 dragitem 放置在另一个列表的特定项目上,那么被拖动的项目将被添加到它被拖动到的列表的索引中,同样的事情也将适用于同一个列表。我试过了,但我无法在选择 dragitem 时使其像滚动 ListView 一样,并且只有 3 个可见项目。
我想这样开发:/image/bdn1I.gif
感谢任何帮助。
最佳答案
您尝试开发的内容可以使用 Draggable 和 DragTarget 来完成,但您必须意识到 Draggable 和 DragTarget 都应该具有相同的数据类型
我将简要解释这两个小部件,然后在本段之后我将发布完整代码,然后我将分别解释每个部分。
Draggable 是用于使用户能够将一个小部件从一个位置拖动到另一个位置的小部件,但它只能在相同类型的 DragTarget 小部件上放置和处理
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) =>
MaterialApp(
home: Drag(),
);
}
class Drag extends StatefulWidget {
@override
_DragState createState() => _DragState();
}
class _DragState extends State<Drag> {
List listA = ["A", "B", "C"];
List listB = ["D", "E", "F"];
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.greenAccent[200],
body: SafeArea(
child: Column(
children: [
// list view separated will build a widget between 2 list items to act as a separator
Expanded(
child: ListView.separated(
itemBuilder: _buildListAItems,
separatorBuilder: _buildDragTargetsA,
itemCount: listA.length,
)),
Expanded(
child: ListView.separated(
itemBuilder: _buildListBItems,
separatorBuilder: _buildDragTargetsB,
itemCount: listB.length,
)),
],
),
),
);
}
// builds the widgets for List B items
Widget _buildListBItems(BuildContext context, int index) {
return Draggable<String>(
// the value of this draggable is set using data
data: listB[index],
// the widget to show under the users finger being dragged
feedback: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listB[index],
style: TextStyle(fontSize: 20),
),
),
),
// what to display in the child's position when being dragged
childWhenDragging: Container(
color: Colors.grey,
width: 40,
height: 40,
),
// widget in idle state
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listB[index],
style: TextStyle(fontSize: 20),
),
),
),
);
}
// builds the widgets for List A items
Widget _buildListAItems(BuildContext context, int index) {
return Draggable<String>(
data: listA[index],
feedback: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listA[index],
style: TextStyle(fontSize: 20),
),
),
),
childWhenDragging: Container(
color: Colors.grey,
width: 40,
height: 40,
),
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listA[index],
style: TextStyle(fontSize: 20),
),
),
),
);
}
// will return a widget used as an indicator for the drop position
Widget _buildDropPreview(BuildContext context, String value) {
return Card(
color: Colors.lightBlue[200],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
value,
style: TextStyle(fontSize: 20),
),
),
);
}
// builds DragTargets used as separators between list items/widgets for list A
Widget _buildDragTargetsA(BuildContext context, int index) {
return DragTarget<String>(
// builder responsible to build a widget based on whether there is an item being dropped or not
builder: (context, candidates, rejects) {
return candidates.length > 0 ? _buildDropPreview(context, candidates[0]):
Container(
width: 5,
height: 5,
);
},
// condition on to accept the item or not
onWillAccept: (value)=>!listA.contains(value),
// what to do when an item is accepted
onAccept: (value) {
setState(() {
listA.insert(index + 1, value);
listB.remove(value);
});
},
);
}
// builds drag targets for list B
Widget _buildDragTargetsB(BuildContext context, int index) {
return DragTarget<String>(
builder: (context, candidates, rejects) {
return candidates.length > 0 ? _buildDropPreview(context, candidates[0]):
Container(
width: 5,
height: 5,
);
},
onWillAccept: (value)=>!listB.contains(value),
onAccept: (value) {
setState(() {
listB.insert(index + 1, value);
listA.remove(value);
});
},
);
}
}
下面的部分负责为ListB构建Draggable widgets,这个Draggable Widget会根据index显示list的值,list item的值会被设置为draggable的数据,这样dragTarget就可以处理可拖动。
// builds the widgets for List B items
Widget _buildListBItems(BuildContext context, int index) {
return Draggable<String>(
// the value of this draggable is set using data
data: listB[index],
// the widget to show under the users finger being dragged
feedback: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listB[index],
style: TextStyle(fontSize: 20),
),
),
),
// what to display in the child's position when being dragged
childWhenDragging: Container(
color: Colors.grey,
width: 40,
height: 40,
),
// widget in idle state
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
listB[index],
style: TextStyle(fontSize: 20),
),
),
),
);
}
这部分代码将处理来自 listB 的 draggables(如果你修改代码也可以是 listA),它会根据它们的值接受/拒绝 draggables,如果 draggable 可以,它会显示一个小部件被接受,它将使用修改后的列表设置状态,以便创建新状态并更改用户界面。
// builds DragTargets used as separators between list items/widgets for list A
Widget _buildDragTargetsA(BuildContext context, int index) {
return DragTarget<String>(
// builder responsible to build a widget based on whether there is an item being dropped or not
builder: (context, candidates, rejects) {
return candidates.length > 0 ? _buildDropPreview(context, candidates[0]):
Container(
width: 5,
height: 5,
);
},
// condition on to accept the item or not
onWillAccept: (value)=>!listA.contains(value),
// what to do when an item is accepted
onAccept: (value) {
setState(() {
listA.insert(index + 1, value);
listB.remove(value);
});
},
);
}
最后在这段代码中,正如我上面提到的,它只接受从列表 A 到列表 B 的可拖动对象,反之亦然,但它不会接受从同一个列表到同一个列表的可拖动对象。除此之外,还有一些我没有考虑但你可以考虑的情况,这些情况是:
希望我的回答对你有帮助!
关于Flutter 在多个列表之间拖放列表项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64008722/
我在这里有一个我想要做的事情的例子:http://jsbin.com/OwoYAlEQ/1/edit 这是我的 HTML: person one person two person three per
我想知道是否有人知道是否有一个预先制定的解决方案:我在 ASP.net 网站上有一个列表,我希望用户能够通过拖放对列表进行重新排序。此外,我希望有第二个列表,用户可以将第一个列表中的项目拖到其中。 到
我想知道是否有人知道是否有一个预先制定的解决方案:我在 ASP.net 网站上有一个列表,我希望用户能够通过拖放对列表进行重新排序。此外,我希望有第二个列表,用户可以将第一个列表中的项目拖到其中。 到
我在我的 Web 应用程序中使用 Ajax ControlToolkit 中的 ModalPopupExtender。我将其 Drag 属性设置为 true,但是当我拖动弹出面板并将其放到新位置时,它
所以,基于this answer ,我有一组可以拖放并卡入到位的 div。唯一的问题是,可拖动的 div 具有不同的高度,我需要它们始终捕捉到目标的底部,而不是顶部。 您可以在this JsFiddl
我一直在使用 Bea 的解决方案 here一段时间后发现它非常有帮助。现在我遇到的问题是,当我将项目拖放到另一个 ListView 控件中或拖放到另一个 ListView 控件中,并且我想在拖动“期间
我试图在使用 QTreeWidget.setItemWidget() 重新父级(拖放)后将小部件放入 QTreeWidgetItem 但是,如果编译以下代码,结果是 QTreeWidgetItem 内
这是场景,我使用的是prototype和scriptaculous,但我相信jquery也会有同样的问题。我在相对定位的 div 中有一个可拖动图像的列表。问题是我无法将图像拖出父 div...好吧.
我正在使用一个普通(Bootstrap)表,我想在其中包含可排序的行。我正在使用 Angular CDK (DragDropModule) 来实现排序/排序。但是,当拖动行时,它会扭曲宽度,因为 cd
我正在尝试在我的 UICollectionView 中实现拖放机制,这与在快捷方式应用程序中重新排序快捷方式的组件非常相似。 截至目前,行为是当您开始拖动时,会留下一个透明的单元格 View ,而另一
我有以下 Jquery UI 拖放 jsfiddle https://jsfiddle.net/zoojsfiddle/ud96jdcp/ 具有
我希望创建一个基于网络的“公告板”,可以这么说,用户可以在其中创建/删除/拖放“图钉”,而不允许重叠“图钉”。 这是一个图表,应该有助于说明我正在尝试创建的内容: 'pins' 可能已创建双击;他们会
我是一名优秀的程序员,十分优秀!