Xamarin - 双指缩放在 IOS 中不起作用。 Android 工作正常

Xamarin - Pinch to zoom not working in IOS. working fine on Android

我已经使用了 SebasianKruse https://forums.xamarin.com/discussion/74168/full-screen-image-viewer-with-pinch-to-zoom-pan-to-move-tap-to-show-captions-for-xamarin-forms/p2 在这里发布的代码来能够缩放和平移我的图像。它在 Android 中运行良好,但在 IOS 中我无法缩放和平移。

我试图在 OnPanUpdated 中设置一个断点,但它从未到达 IOS。

这是我的代码:

xaml:

    <AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
        <StackLayout
             AbsoluteLayout.LayoutFlags="All"
             AbsoluteLayout.LayoutBounds="0,0,1,1">
            <Service:PinchToZoomContainer HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                <ffimageloading:CachedImage RetryCount="5" RetryDelay="1" CacheDuration="1" x:Name="MyImage" HorizontalOptions="Fill" VerticalOptions="CenterAndExpand" DownsampleToViewSize="False">
                </ffimageloading:CachedImage>                   
            </Service:PinchToZoomContainer>                
        </StackLayout>
        <StackLayout BindingContext="{x:Reference MyImage}" IsVisible="{Binding IsLoading}" Padding="12"
             AbsoluteLayout.LayoutFlags="PositionProportional"
             AbsoluteLayout.LayoutBounds="0.5,0.5,-1,-1">
            <ActivityIndicator BindingContext="{x:Reference MyImage}" IsRunning="{Binding IsLoading}" />
            <Label Text="Loading Hi-Res Image..." BindingContext="{x:Reference MyImage}" IsVisible="{Binding IsLoading}" HorizontalOptions="Center" TextColor="Black"/>
         </StackLayout>
    </AbsoluteLayout>     
</ContentPage.Content>

Service/PinchToZoomContainer.cs

using System;
using Xamarin.Forms;
using Xamarin.Forms.Internals;

namespace GalShare.Service
{
public class PinchToZoomContainer : ContentView
{
    private double _startScale, _currentScale;
    private double _startX, _startY;
    private double _xOffset, _yOffset;

    public double MinScale { get; set; } = 1;
    public double MaxScale { get; set; } = 4;

    public PinchToZoomContainer()
    {
        var tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
        tap.Tapped += OnTapped;
        GestureRecognizers.Add(tap);

        var pinchGesture = new PinchGestureRecognizer();
        pinchGesture.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinchGesture);

        var pan = new PanGestureRecognizer();
        pan.PanUpdated += OnPanUpdated;
        GestureRecognizers.Add(pan);
    }

    protected override void OnSizeAllocated(double width, double height)
    {
        RestoreScaleValues();
        Content.AnchorX = 0.5;
        Content.AnchorY = 0.5;

        base.OnSizeAllocated(width, height);
    }

    private void RestoreScaleValues()
    {
        Content.ScaleTo(MinScale, 250, Easing.CubicInOut);
        Content.TranslateTo(0, 0, 250, Easing.CubicInOut);

        _currentScale = MinScale;
        _xOffset = Content.TranslationX = 0;
        _yOffset = Content.TranslationY = 0;
    }

    private void OnTapped(object sender, EventArgs e)
    {
        if (Content.Scale > MinScale)
        {
            RestoreScaleValues();
        }
        else
        {
            //todo: Add tap position somehow
            StartScaling();
            ExecuteScaling(MaxScale, .5, .5);
            EndGesture();
        }
    }

    private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        switch (e.Status)
        {
            case GestureStatus.Started:
                StartScaling();
                break;

            case GestureStatus.Running:
                ExecuteScaling(e.Scale, e.ScaleOrigin.X, e.ScaleOrigin.Y);
                break;

            case GestureStatus.Completed:
                EndGesture();
                break;
        }
    }

    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        switch (e.StatusType)
        {
            case GestureStatus.Started:
                _startX = e.TotalX;
                _startY = e.TotalY;

                Content.AnchorX = 0;
                Content.AnchorY = 0;

                break;

            case GestureStatus.Running:
                var maxTranslationX = Content.Scale * Content.Width - Content.Width;
                Content.TranslationX = Math.Min(0, Math.Max(-maxTranslationX, _xOffset + e.TotalX - _startX));

                var maxTranslationY = Content.Scale * Content.Height - Content.Height;
                Content.TranslationY = Math.Min(0, Math.Max(-maxTranslationY, _yOffset + e.TotalY - _startY));

                break;

            case GestureStatus.Completed:
                EndGesture();
                break;
        }
    }

    private void StartScaling()
    {
        _startScale = Content.Scale;

        Content.AnchorX = 0;
        Content.AnchorY = 0;
    }

    private void ExecuteScaling(double scale, double x, double y)
    {
        _currentScale += (scale - 1) * _startScale;
        _currentScale = Math.Max(MinScale, _currentScale);
        _currentScale = Math.Min(MaxScale, _currentScale);

        var deltaX = (Content.X + _xOffset) / Width;
        var deltaWidth = Width / (Content.Width * _startScale);
        var originX = (x - deltaX) * deltaWidth;

        var deltaY = (Content.Y + _yOffset) / Height;
        var deltaHeight = Height / (Content.Height * _startScale);
        var originY = (y - deltaY) * deltaHeight;

        var targetX = _xOffset - (originX * Content.Width) * (_currentScale - _startScale);
        var targetY = _yOffset - (originY * Content.Height) * (_currentScale - _startScale);

        Content.TranslationX = targetX.Clamp(-Content.Width * (_currentScale - 1), 0);
        Content.TranslationY = targetY.Clamp(-Content.Height * (_currentScale - 1), 0);

        Content.Scale = _currentScale;
    }

    private void EndGesture()
    {
        _xOffset = Content.TranslationX;
        _yOffset = Content.TranslationY;
    }
}
}

为什么此代码在 IOS 上不起作用?根据上面论坛中其他用户的帖子,它应该可以在两个系统上工作..

在真实物理设备上测试不会有任何差异事件。

这是因为Xcode11.4引入了一个新的协议成员 UIGestureRecognizerDelegate 和我们最初建议的默认值 ShouldReceiveEvent 与世界的关系不佳。

我们的产品团队已在 Xamarin.iOS 13.16.0.13 中修复此问题: https://github.com/xamarin/Xamarin.Forms/issues/10162#issuecomment-607585466 您可以在 Mac 上手动下载并安装 pkg。但是 Windows 上的 VS 已经发布了新版本,现在我们只能在安装新的 Xamarin iOS 版本后暂时使用 VS for Mac 进行开发。