NET Multi-platform App UI (.NET MAUI) 捏合手势识别器用于执行交互式缩放。 捏合手势的一个常见场景是在捏合位置对图像进行交互式缩放。 这是通过缩放视区的内容来实现的。
在 .NET MAUI 中,捏合手势识别由 PinchGestureRecognizer 类提供,该类定义在检测到的捏合手势更改时触发的 PinchUpdated 事件。 PinchUpdated 事件随附的 PinchGestureUpdatedEventArgs 对象定义了以下属性:
- Scale,类型为
double
,指示自上次收到更新后捏合手势的相对大小。 - ScaleOrigin,类型
Point
,指示捏合手势的更新原点。 - Status,类型为 GestureStatus,指示是否已针对新启动的手势、正在运行的手势、已完成的手势或已取消的手势引发事件。
创建 PinchGestureRecognizer
若要使 View 识别捏合手势,请创建一个 PinchGestureRecognizer 对象,处理 PinchUpdated 事件,并将新的手势识别器添加到视图上的 GestureRecognizers
集合。 下面的代码示例展示了附加到 Image 的 PinchGestureRecognizer:
<Image Source="waterfront.jpg">
<Image.GestureRecognizers>
<PinchGestureRecognizer PinchUpdated="OnPinchUpdated" />
</Image.GestureRecognizers>
</Image>
OnPinchUpdated
事件处理程序的代码应添加到代码隐藏文件中:
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
// Handle the pinch
}
等效 C# 代码如下:
PinchGestureRecognizer pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += (s, e) =>
{
// Handle the pinch
};
image.GestureRecognizers.Add(pinchGesture);
创建捏合容器
以下示例所示的 PinchToZoomContainer
类是一个通用帮助程序类,可用于以交互方式缩放 View:
public class PinchToZoomContainer : ContentView
{
double currentScale = 1;
double startScale = 1;
double xOffset = 0;
double yOffset = 0;
public PinchToZoomContainer()
{
PinchGestureRecognizer pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
}
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = Math.Clamp(targetX, -Content.Width * (currentScale - 1), 0);
Content.TranslationY = Math.Clamp(targetY, -Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
}
在本示例中,OnPinchUpdated
方法根据用户的捏合手势更新包装视图的缩放级别。 这是通过使用 PinchGestureUpdatedEventArgs 对象的 Scale、ScaleOrigin 和 Status 属性的值计算要应用于捏合手势原点的比例系数来实现的。 然后,通过将包装视图的 TranslationX
、TranslationY
和 Scale
属性设置为计算值,在捏合手势的原点对其进行缩放。
PinchToZoomContainer
类可以围绕 View 进行包装,以便已识别的捏合手势可以缩放包装的视图。 以下 XAML 示例展示了包装 Image 的 PinchToZoomContainer
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PinchGesture;assembly=PinchGesture"
x:Class="PinchGesture.HomePage">
<Grid>
<local:PinchToZoomContainer>
<Image Source="waterfront.jpg" />
</local:PinchToZoomContainer>
</Grid>
</ContentPage>
在本示例中,当 Image 接收到捏合手势时,显示的图像将被放大或缩小。