识别拖放手势
.NET Multi-platform App UI (.NET MAUI) 拖放手势识别器利用连续手势将项及其相关的数据包从屏幕上的一个位置拖放到另一个位置。 拖放手势可以在单个应用程序中进行,也可以在一个应用程序中开始,然后在另一个应用程序中结束。
拖动源(即启动拖动手势的元素)可以通过填充数据包对象来提供要传输的数据。 当拖放源被释放时,就会发生放置。 然后,放置目标(即拖动源下的元素)会处理数据包。
在应用中启用拖放的过程如下所示:
- 启用对元素的拖动,具体方法为将 DragGestureRecognizer 对象添加到它的 GestureRecognizers 集合中。 有关详细信息,请参阅启用拖动。
- [可选] 生成数据包。 .NET MAUI 自动为图像和文本控件填充数据包,但对于其他内容,则需要构造自己的数据包。 有关详细信息,请参阅生成数据包。
- 通过将 DropGestureRecognizer 对象添加至元素的 GestureRecognizers 集合中启用对元素的放置。 有关详细信息,请参阅启用放置。
- [可选] 处理
DropGestureRecognizer.DragOver
事件,以指明放置目标允许执行的操作类型。 有关详细信息,请参阅处理 DragOver 事件。 - [可选] 处理数据包,以接收放置的内容。 .NET MAUI 将自动从数据包中检索图像和文本数据,但对于其他内容,则需要处理数据包。 有关详细信息,请参阅处理数据包。
启用拖动
在 .NET MAUI 中,拖动手势识别是由 DragGestureRecognizer 类提供的。 此类定义了以下属性:
- CanDrag 属于
bool
类型,指明手势识别器附加到的元素能否为拖动源。 此属性的默认值为true
。 - DragStartingCommand 属于 ICommand 类型,在第一次识别拖动手势时执行。
- DragStartingCommandParameter 属于
object
类型,是传递给 DragStartingCommand 的参数。 - DropCompletedCommand 属于 ICommand 类型,在放置拖动源时执行。
- DropCompletedCommandParameter 属于
object
类型,是传递给 DropCompletedCommand 的参数。
这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。
DragGestureRecognizer 类还定义了 DragStarting 和 DropCompleted 事件,这些事件会在 CanDrag 属性为 true
时触发。 当检测到拖动手势时,DragGestureRecognizer 对象就会执行 DragStartingCommand,并调用 DragStarting 事件。 然后,当检测到放置手势完成时,DragGestureRecognizer 对象就会执行 DropCompletedCommand,并调用 DropCompleted 事件。
DragStarting 事件随附的 DragStartingEventArgs 对象定义了以下属性:
- Cancel 属于
bool
类型,指明是否应取消事件。 - Data 属于 DataPackage 类型,指明拖动源随附的数据包。 这是只读属性。
- 类型为
PlatformDragStartingEventArgs?
的 PlatformArgs 表示与事件关联的平台特定参数。
在 Android 上,PlatformDragStartingEventArgs 类定义以下属性:
- 类型为 View 的
Sender
表示附加到事件的本机视图。 - 类型为 MotionEvent 的
MotionEvent
表示包含拖放状态信息的事件。
此外,在 Android 上,PlatformDragStartingEventArgs 类定义了以下方法:
SetDragShadowBuilder
,用于设置拖动开始时要使用的 View.DragShadowBuilder。SetClipData
,用于设置拖动开始时要使用的 ClipData。SetLocalData
,用于设置拖动开始时要使用的本地数据。SetDragFlags
,用于设置拖动开始时要使用的 DragFlags。
例如,使用 SetClipData
方法将 ClipData 与拖动的项关联:
void OnDragStarting(object sender, DragStartingEventArgs e)
{
#if ANDROID
string content = "insert your content here";
e.PlatformArgs.SetClipData(Android.Content.ClipData.NewPlainText("Drag data", content));
#endif
}
DropCompleted 事件附带的 DropCompletedEventArgs 对象定义一个类型为 PlatformDropCompletedEventArgs?
的 PlatformArgs 属性,该属性表示与事件关联的平台特定参数。
在 Android 上,PlatformDropCompletedEventArgs 类定义以下属性:
下面的 XAML 示例展示了附加到 Image 的 DragGestureRecognizer:
<Image Source="monkeyface.png">
<Image.GestureRecognizers>
<DragGestureRecognizer />
</Image.GestureRecognizers>
</Image>
在此示例中,可以对 Image 启动拖动手势。
提示
拖动手势可通过先长按再拖动来启动。
生成数据包
对于以下控件,当拖动开始时,.NET MAUI 将为你自动生成数据包:
- 文本控件。 可以从 CheckBox、DatePicker、Editor、Entry、Label、RadioButton、Switch 和 TimePicker 对象中拖动文本值。
- 图像控件。 可以从 Button、Image 和 ImageButton 控件中拖动图像。
下表显示了当对文本控件启动拖动手势时读取的属性和尝试执行的任何转换:
控件 | 属性 | 转换 |
---|---|---|
CheckBox | IsChecked |
bool 已转换为 string 。 |
DatePicker | Date |
DateTime 已转换为 string 。 |
Editor | Text |
|
Entry | Text |
|
Label | Text |
|
RadioButton | IsChecked |
bool 已转换为 string 。 |
Switch | IsToggled |
bool 已转换为 string 。 |
TimePicker | Time |
TimeSpan 已转换为 string 。 |
对于除文本和图像以外的内容,你需要自行生成数据包。
数据包由 DataPackage 类表示,此类定义了以下属性:
- Properties 属于 DataPackagePropertySet 类型,它是组成 DataPackage 中所包含数据的属性的集合。 此为只读属性。
- Image 属于 ImageSource 类型,它是 DataPackage 中包含的图像。
- Text 属于
string
类型,它是 DataPackage 中包含的文本。 - View 属于 DataPackageView 类型,它是 DataPackage 的只读版本。
DataPackagePropertySet 类表示存储为 Dictionary<string,object>
的属性包。 若要了解 DataPackageView 类,请参阅处理数据包。
存储图像或文本数据
通过在 DataPackage.Image
或 DataPackage.Text
属性中存储图像或文本数据,可以将这些数据与拖动源关联。 可以在 DragStarting 事件的处理程序中添加数据。
下面的 XAML 示例展示了为 DragStarting 事件注册处理程序的 DragGestureRecognizer:
<Path Stroke="Black"
StrokeThickness="4">
<Path.GestureRecognizers>
<DragGestureRecognizer DragStarting="OnDragStarting" />
</Path.GestureRecognizers>
<Path.Data>
<!-- PathGeometry goes here -->
</Path.Data>
</Path>
在此示例中,DragGestureRecognizer 附加到 Path 对象。 在 Path 上检测到拖动手势时,将引发 DragStarting 事件,该事件将执行 OnDragStarting
事件处理程序:
void OnDragStarting(object sender, DragStartingEventArgs e)
{
e.Data.Text = "My text data goes here";
}
DragStarting 事件随附的 DragStartingEventArgs 对象有类型为 DataPackage 的 Data
属性。 在此示例中,DataPackage 对象的 Text
属性设置为 string
。 然后,可以在放置时访问 DataPackage 来检索 string
。
将数据存储在属性包中
任何数据(包括图像和文本)都可以通过将数据存储在 DataPackage.Properties
集合中来与拖动源关联。 可以在 DragStarting 事件的处理程序中添加数据。
下面的 XAML 示例展示了为 DragStarting 事件注册处理程序的 DragGestureRecognizer:
<Rectangle Stroke="Red"
Fill="DarkBlue"
StrokeThickness="4"
HeightRequest="200"
WidthRequest="200">
<Rectangle.GestureRecognizers>
<DragGestureRecognizer DragStarting="OnDragStarting" />
</Rectangle.GestureRecognizers>
</Rectangle>
在此示例中,DragGestureRecognizer 附加到 Rectangle 对象。 在 Rectangle 上检测到拖动手势时,将引发 DragStarting 事件,该事件将执行 OnDragStarting
事件处理程序:
void OnDragStarting(object sender, DragStartingEventArgs e)
{
Shape shape = (sender as Element).Parent as Shape;
e.Data.Properties.Add("Square", new Square(shape.Width, shape.Height));
}
DragStarting 事件随附的 DragStartingEventArgs 对象有类型为 DataPackage 的 Data
属性。 可以通过修改 DataPackage 对象的 Properties
集合(即 Dictionary<string, object>
集合)来存储所需的任何数据。 在此示例中,对 Properties
字典做了修改,以存储根据“Square”键表示 Rectangle 大小的 Square
对象。
启用放置
在 .NET MAUI 中,放置手势识别由 DropGestureRecognizer 类提供。 此类定义了以下属性:
- AllowDrop 属于
bool
类型,指明手势识别器附加到的元素能否成为放置目标。 此属性的默认值为true
。 - DragOverCommand 属于 ICommand 类型,在拖动源被拖动到放置目标上时执行。
- DragOverCommandParameter 属于
object
类型,是传递给DragOverCommand
的参数。 - DragLeaveCommand 属于 ICommand 类型,在拖动源被拖至放置目标上时执行。
- DragLeaveCommandParameter 属于
object
类型,是传递给DragLeaveCommand
的参数。 - DropCommand 属于 ICommand 类型,在拖动源被放置到放置目标上时执行。
- DropCommandParameter 属于
object
类型,是传递给DropCommand
的参数。
这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。
DropGestureRecognizer 类还定义了 DragOver、DragLeave 和 Drop 事件,这些事件会在 AllowDrop 属性为 true
时触发。 当在放置目标上识别拖动源时,DropGestureRecognizer 就会执行 DragOverCommand,并调用 DragOver 事件。 然后,如果将拖动源拖至放置目标,DropGestureRecognizer 将执行 DragLeaveCommand 并调用 DragLeave 事件。 最后,当在放置目标上识别放置手势时,DropGestureRecognizer 就会执行 DropCommand,并调用 Drop 事件。
随附 DragOver 和 DragLeave 事件的 DragEventArgs 类定义了以下属性:
- Data 属于 DataPackage 类型,它包含与拖动源关联的数据。 此属性为只读。
- AcceptedOperation 属于 DataPackageOperation 类型,指定放置目标允许执行的操作。
- PlatformArgs,类型为
PlatformDragEventArgs?
,表示与事件关联的平台特定参数。
在 Android 上,PlatformDragEventArgs 类定义以下属性:
若要了解 DataPackageOperation 枚举,请参阅处理 DragOver 事件。
Drop 事件随附的 DropEventArgs 类定义了以下属性:
- Data 属于 DataPackageView 类型,它是数据包的只读版本。
- Handled,类型为
bool
,指示事件处理程序是否已经处理事件,或者 .NET MAUI 是否应继续自行处理。 - PlatformArgs,类型为
PlatformDropEventArgs?
,表示与事件关联的平台特定参数。
在 Android 上,PlatformDropEventArgs 类定义以下属性:
下面的 XAML 示例展示了附加到 Image 的 DropGestureRecognizer:
<Image BackgroundColor="Silver"
HeightRequest="300"
WidthRequest="250">
<Image.GestureRecognizers>
<DropGestureRecognizer />
</Image.GestureRecognizers>
</Image>
在此示例中,将拖动源放到 Image 放置目标上时,如果拖动源为 ImageSource,则它将被复制到放置目标。 .NET MAUI 自动将拖动的图像和文本复制到兼容的放置目标。
处理 DragOver 事件
可以视需要选择处理 DropGestureRecognizer.DragOver
事件,以指明放置目标允许执行的操作类型。 可以通过在随附 DragOver 事件的 DragEventArgs 对象上设置类型 DataPackageOperation 的 AcceptedOperation
属性指示允许的操作。
DataPackageOperation 枚举定义以下成员:
None
:指明不执行任何操作。Copy
:指明将拖动源内容复制到放置目标。
重要说明
当 DragEventArgs 对象创建时,AcceptedOperation
属性默认为 DataPackageOperation.Copy
。
下面的 XAML 示例展示了为 DragOver 事件注册处理程序的 DropGestureRecognizer:
<Image BackgroundColor="Silver"
HeightRequest="300"
WidthRequest="250">
<Image.GestureRecognizers>
<DropGestureRecognizer DragOver="OnDragOver" />
</Image.GestureRecognizers>
</Image>
在此示例中,DropGestureRecognizer 附加到 Image 对象。 将拖动源拖动到放置目标上但尚未放置时,将触发 DragOver 事件,此事件将执行 OnDragOver
事件处理程序:
void OnDragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.None;
}
在此示例中,DragEventArgs 对象的 AcceptedOperation
属性设置为 DataPackageOperation.None
。 此值可确保在将拖动源放置到放置目标上时不执行任何操作。
处理数据包
在放置目标上释放拖动源时,将引发 Drop 事件。 将拖动源放置到以下控件上时,.NET MAUI 会自动尝试从数据包中检索数据:
- 文本控件。 可以将文本值放置到 CheckBox、DatePicker、Editor、Entry、Label、RadioButton、Switch 和 TimePicker 对象上。
- 图像控件。 可以将图像放置到 Button、Image和 ImageButton 控件上。
下表显示了将基于文本的拖动源放置到文本控件上时要设置的属性和尝试执行的任何转换:
控件 | 属性 | 转换 |
---|---|---|
CheckBox | IsChecked |
string 转换为 bool 。 |
DatePicker | Date |
string 转换为 DateTime 。 |
Editor | Text |
|
Entry | Text |
|
Label | Text |
|
RadioButton | IsChecked |
string 转换为 bool 。 |
Switch | IsToggled |
string 转换为 bool 。 |
TimePicker | Time |
string 转换为 TimeSpan 。 |
对于除文本和图像以外的内容,你需要自行处理数据包。
Drop 事件随附的 DropEventArgs 类定义了类型为 DataPackageView 的 Data
属性。 此属性表示数据包的只读版本。
检索图像或文本数据
使用 DataPackageView 类中定义的方法,可以在 Drop 事件的处理程序中从数据包中检索图像或文本数据。
DataPackageView 类包含 GetImageAsync
和 GetTextAsync
方法。 GetImageAsync
方法从数据包中检索存储在 DataPackage.Image
属性中的图像,并返回 Task<ImageSource>
。 同样,GetTextAsync
方法从数据包中检索存储在 DataPackage.Text
属性中的文本,并返回 Task<string>
。
下面的示例展示了从 Path 的数据包中检索文本的 Drop
事件处理程序:
async void OnDrop(object sender, DropEventArgs e)
{
string text = await e.Data.GetTextAsync();
// Perform logic to take action based on the text value.
}
在此示例中,文本数据是使用 GetTextAsync
方法从数据包中检索的。 然后,可以执行基于文本值的操作。
从属性包中检索数据
通过访问数据包的 Properties
集合,可以在 Drop 事件的处理程序中从数据包中检索任何数据。
DataPackageView 类定义了类型为 DataPackagePropertySetView
的 Properties
属性。 DataPackagePropertySetView
类表示存储为 Dictionary<string, object>
的只读属性包。
下面的示例展示了从 Rectangle 的数据包的属性包中检索数据的 Drop 事件处理程序:
void OnDrop(object sender, DropEventArgs e)
{
Square square = (Square)e.Data.Properties["Square"];
// Perform logic to take action based on retrieved value.
}
在此示例中,Square
对象是通过指定“Square”字典键从数据包的属性包中检索的。 然后,可以执行基于检索到的值的操作。
在应用程序之间拖放
在 iOS、Mac Catalyst 和 Windows 上,拖动可以在一个应用程序中启动,相应的放置操作以 .NET MAUI 应用程序结尾。 从中拖动项的应用是 源 应用程序,删除项的 .NET MAUI 应用是 目标 应用程序。
无法从 源 应用程序拖动到 Android 上的 .NET MAUI 目标 应用程序。
获取手势位置
可以通过对 DragEventArgs、DragStartingEventArgs 或 DropEventArgs 对象调用 GetPosition 方法获取拖放手势发生的位置。 GetPosition 方法接受 Element?
参数,并将位置作为 Point?
对象返回:
void OnDragStarting(object sender, DragStartingEventArgs e)
{
// Position relative to screen
Point? screenPosition = e.GetPosition(null);
// Position relative to specified element
Point? relativeToImagePosition = e.GetPosition(image);
}
Element?
参数定义获取位置应相对于的元素。 提供一个 null
值作为此参数意味着 GetPosition 方法返回一个 Point?
对象,该对象定义相对于屏幕的拖放手势位置。