Xamarin - щепотка для увеличения не работает в IOS. работает нормально на Android - PullRequest
0 голосов
/ 03 апреля 2020

Я использовал код, опубликованный здесь 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? согласно сообщениям других пользователей на форуме выше, он должен работать на обеих системах.

1 Ответ

1 голос
/ 06 апреля 2020

Никаких различий не будет, хотя тестирование будет проводиться на реальном физическом устройстве.

Это связано с тем, что Xcode 11.4 представил новый элемент протокола для UIGestureRecognizerDelegate и наше начальное предлагаемое значение по умолчанию для ShouldReceiveEvent не воспроизводится должным образом с миром.

Наша команда разработчиков исправила это в Xamarin. iOS 13.16.0.13: https://github.com/xamarin/Xamarin.Forms/issues/10162#issuecomment -607585466 Вы можете вручную загрузить и установить pkg на Ma * 1010. *. Но VS на Windows выпустил новую версию, теперь мы можем только временно разработать ее, используя VS для Ma c после установки новой версии Xamarin iOS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...