如何使用 Draggable 和 DragTarget 在 Flutter 中创建拖放 UI 元素?
Flutter 是一个移动应用程序 SDK,允许开发人员为 Android 和 iOS 构建和发布跨平台应用程序。Flutter 最有价值的功能之一是它能够创建可拖动的 U.I. 元素。使用此功能,您可以创建按钮,列表甚至整个屏幕,这些屏幕可以在您的应用程序中拖动。
可拖动微件允许您向任何微件添加拖放行为。DragTarget 是一个小组件,可用于指定当用户放置拖动的对象时,哪个小组件应接受放置事件。
在本文中,我们将讨论拖放、可拖动和拖动目标小部件,它们是 Flutter Toolkit 库的一部分。
关于拖放 UI 元素
拖放 UI 元素是一个新的 Flutter 小部件,允许您创建强大的自定义交互。您可以使用拖放 UI 元素来构建应用的核心交互,例如将对象从应用中的一个位置拖动到另一个位置。
Flutter 的 DragTarget 小部件允许您在允许拖动事件的页面上定义一些目标区域。例如,如果用户将图像拖到按钮上,则该按钮可能被设置为拖动事件的目标(例如,它可以接收掉落)。当拖动的物品击中目标时,它们会从目标上反弹并根据它们进入目标区域的角度在重力作用下落回原位。
可拖动的 UI 元素
可拖动微件可以在您的应用程序中创建可拖动元素。拖放功能是一项流行的功能,可让您将对象从屏幕的一部分拖放到另一部分。这对于重新排列项目、移动文件以及许多其他事情非常有用。
可拖动界面最突出的用途是在网页设计中。许多网站允许用户通过此功能重新排列其页面上的元素。除了在网站上使用外,可拖动还可用于许多其他领域,例如移动应用程序、桌面软件,甚至视频游戏!
拖动目标元素
拖动目标是一个小组件,允许您指定可以启动拖动操作的应用程序区域。DragTarget 是 GestureDetector 的一个子类,你可以使用它来检测应用中的拖动操作或手势。
DragTarget 有三种方法:
onStart – 在用户开始拖动时调用
onDrag – 当用户将手指拖过目标区域时调用
onEnd – 当用户停止拖动时调用。
使用这些小部件,您可以允许拖动整个小部件或仅拖动其中的一部分!
有两个小部件可以在 Flutter 中拖放 U.I. 元素:Draggable 和 DragTarget。可拖动允许您拖动整个小部件或其中的一部分(例如,其背景)。当多个元素响应同一事件(例如,使用不同的动画响应)时使用 DragTarget。
“可拖动”和“拖动目标”微件是允许用户与您的应用程序交互的第一步。这些小部件使您能够创建拖放体验,以便在屏幕上移动项目,包括移动 U.I. 元素或整个页面并调整其大小。
在 Flutter 应用程序开发中创建拖放体验时,可以使用可拖动小部件。可拖动小部件允许您在屏幕上拖动对象。
若要实现拖放体验,需要使用一个或多个可拖动小组件和至少一个 DragTarget 小组件。“拖动目标”构件可以是任何形状或大小,只要它具有“可拖动”构件的有效放置目标即可。
这些小部件可以处理本机元素拖动,并使用自定义图像而不是默认背景颜色自定义可拖动微件。
您可以将这些组合在一起以实现强大的自定义交互。例如,如果您希望用户能够在按钮上拖动图像,或将整个小组件从应用程序中的一个位置拖动到另一个位置,则 Draggable 和 DragTarget 是允许他们这样做的第一步。
例
拖放是许多应用中使用的常见交互。这是执行不同任务的简单方法,可用于各种目的。例如,您可以将文件拖到电子邮件中或在手机上移动它们。
在此示例中,我们将讨论创建简单的拖放式 UI 元素所需的初始步骤。可以将元素拖动到所需位置,也可以将它们拖放到其他元素上。
第一步是创建一个可拖动的小部件。这个小部件将定义我们元素的位置及其边界。要使您的小部件可拖动,您需要为其提供两个子项:文本小部件和带框文本的小部件。拖动文本时将显示在框中。该框将包含有关将元素放在哪里的所有必要信息。
第二步是创建一个 DragTarget 小部件,允许您指定哪些其他小部件有资格将元素拖放到它们上。如果您希望在将元素拖放到另一个元素上时具有任何特殊功能(例如更改颜色或隐藏/显示某些内容),则可以在 DragTarget 实例上设置自定义属性。
例
main.dart
import 'package:flutter/material.dart';
import 'package:dotted_border/dotted_border.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false, home: DemoExample());
}
}
class DemoExample extends StatefulWidget {
const DemoExample({Key? key}) : super(key: key);
@override
State<demoexample> createState() => _DemoExampleState();
}
class _DemoExampleState extends State<demoexample> {
@override
Widget build(BuildContext context) {
bool isDropped = false;
String _color = "red";
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
LongPressDraggable<string>(
// Data is the value this Draggable stores.
data: _color,
feedback: Material(
child: Container(
height: 170.0,
width: 170.0,
decoration: const BoxDecoration(
color: Colors.redAccent,
),
child: const Center(
child: Text(
'Dragging',
textScaleFactor: 2,
),
),
),
),
childWhenDragging: Container(
height: 150.0,
width: 150.0,
color: Colors.grey,
child: const Center(
child: Text(
'I was here',
textScaleFactor: 2,
),
),
),
child: Container(
height: 150.0,
width: 150.0,
color: Colors.redAccent,
child: const Center(
child: Text(
'Drag me',
textScaleFactor: 2,
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.15,
),
DragTarget<string>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return DottedBorder(
borderType: BorderType.RRect,
radius: const Radius.circular(12),
padding: const EdgeInsets.all(6),
color: Colors.black,
strokeWidth: 2,
dashPattern: const [8],
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(12)),
child: Container(
height: 200,
width: 200,
color: isDropped ? Colors.redAccent : null,
child: Center(
child: Text(
!isDropped ? 'Drop here' : 'Dropped',
textScaleFactor: 2,
)),
),
),
);
},
onAccept: (data) {
debugPrint('hi $data');
setState(() {
isDropped = true;
});
debugPrint('hi $isDropped');
},
onWillAccept: (data) {
return data == _color;
},
),
],
),
));
}
}
</dynamic></dynamic></string></string></demoexample></demoexample>
输出
结论
本文着眼于两个新的小部件,用于在 Flutter 应用程序开发中构建拖放交互。这些小部件使只需几行代码即可在 Flutter 中轻松构建成熟的拖放界面!我希望你们喜欢阅读这篇文章。
常见问题 (FAQ)
1. 颤振有拖放式用户界面吗?
Flutter 为您提供了一个小部件 LongPressDraggable,它提供了从拖放交互开始所需的确切行为。长按可拖动小部件将识别长按何时触发,并将查看用户手指附近的新小部件。当用户拖动时,小部件将跟随用户的手指。
2. 如何在 Flutter 应用程序中构建自定义下拉列表?
下拉按钮将使用叠加层进行全屏堆栈。在下拉列表后面添加全屏手势检测器,以便在用户点击屏幕上的任意位置时将其关闭。因此,叠加层使用LayerLink和CompositedTransformerFollower小部件链接到按钮。
3. 如何在 Flutter 中使用 DragTarget?
DragText < T 扩展了对象>类 Null 安全性。删除可拖动小部件时,小部件将获取数据。将可拖动对象拖动到拖动目标的顶部时,系统会询问拖动目标是否接受可拖动对象携带的任何数据。
4. 什么是可拖动小部件和拖动目标小部件?
可拖动小组件识别拖动手势的开头,并显示跟踪用户手指在屏幕上的反馈小组件。但是,如果用户将手指移动到 DragTraget 的顶部,则该目标可以接受可拖动对象携带的数据。
Flutter 中的 DragTarget 小部件将接收用户拖放的数据。它允许您将项目从一个小部件拖动到另一个小部件。因此,它是一个用于创建游戏和其他交互式用户界面的小部件。