когда я добавляю жест касания, пинч и панорамирование не работают в формах xamarin - PullRequest
0 голосов
/ 20 сентября 2018

Я хочу создать функцию для нажатия и добавления изображения булавки поверх другого фонового изображения, и фоновое изображение должно иметь возможность масштабирования и панорамирования. Это XAML-код для этого, здесь увеличение масштаба не работает, но событие нажатияработает нормально

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:POC"
         xmlns:ui="clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture"
         x:Class="POC.MainPage"
         Title="Main Page">
<ScrollView AbsoluteLayout.LayoutFlags="All">
    <local:PinchAndPanContainer>
        <local:PinchAndPanContainer.Content >
            <AbsoluteLayout x:Name="AbsoluteLayoutForImage">
                <Image x:Name="FloorPlanImage" 
                Source="Capture2.png"
                HeightRequest="400"
                IsEnabled="True"
                InputTransparent="True"
                ui:Gesture.TapCommand2="{Binding TapCommand2}"/>//This Property
            </AbsoluteLayout>
        </local:PinchAndPanContainer.Content>
    </local:PinchAndPanContainer>
</ScrollView>

в файле cs, эта команда касания добавляет изображение булавки в абсолютный макет, используя координаты в точке.

public Command<Point> TapCommand2 => new Command<Point>(point =>
    {
        AddPin(point);
    });

Теперьесли мы просто удалим ui:Gesture.TapCommand2="{Binding TapCommand2}" это свойство из приведенного выше кода, пинч и панорамирование будут работать нормально.

Для события Tap я использовал пакет NuGet Vapolia.XamarinFormsGesture, а для пинча и панорамирования использовались формы xamarin. Gesture Recognizer Может кто-нибудь помочь

1 Ответ

0 голосов
/ 20 сентября 2018

Недавно я выполнил аналогичную функциональность и в итоге создал CustomControl, как показано ниже:

Примечание: Я использовал FFImageLoadings CachedImage в моем классе, если вы не используете FFImage, просто заменитеэто с вашим defualt xamarin формирует изображение.

И это имеет следующие функциональные возможности: PanSwipe, Zoom и DoubleTap для увеличения.

using System;
using Xamarin.Forms;
using FFImageLoading.Forms;

public class ZoomableImage : CachedImage //In case not using ff image replace this with the Image control
{
    private const double MIN_SCALE = 1;
    private const double MAX_SCALE = 4;
    private const double OVERSHOOT = 0.15;
    private double StartScale, LastScale;
    private double StartX, StartY;

    public ZoomableImage()
    {
        var pinch = new PinchGestureRecognizer();
        pinch.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinch);

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

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

        Scale = MIN_SCALE;
        TranslationX = TranslationY = 0;
        AnchorX = AnchorY = 0;
    }

    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
    {
        Scale = MIN_SCALE;
        TranslationX = TranslationY = 0;
        AnchorX = AnchorY = 0;
        return base.OnMeasure(widthConstraint, heightConstraint);
    }

    private void OnTapped(object sender, EventArgs e)
    {
        if (Scale > MIN_SCALE)
        {
            this.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
            this.TranslateTo(0, 0, 250, Easing.CubicInOut);
        }
        else
        {
            AnchorX = AnchorY = 0.5; //TODO tapped position
            this.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);
        }
    }

    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        switch (e.StatusType)
        {
            case GestureStatus.Started:
                StartX = (1 - AnchorX) * Width;
                StartY = (1 - AnchorY) * Height;
                break;
            case GestureStatus.Running:
                AnchorX = Clamp(1 - (StartX + e.TotalX) / Width, 0, 1);
                AnchorY = Clamp(1 - (StartY + e.TotalY) / Height, 0, 1);
                break;
        }
    }

    private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        switch (e.Status)
        {
            case GestureStatus.Started:
                LastScale = e.Scale;
                StartScale = Scale;
                AnchorX = e.ScaleOrigin.X;
                AnchorY = e.ScaleOrigin.Y;
                break;
            case GestureStatus.Running:
                if (e.Scale < 0 || Math.Abs(LastScale - e.Scale) > (LastScale * 1.3) - LastScale)
                { return; }
                LastScale = e.Scale;
                var current = Scale + (e.Scale - 1) * StartScale;
                Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT));
                break;
            case GestureStatus.Completed:
                if (Scale > MAX_SCALE)
                    this.ScaleTo(MAX_SCALE, 250, Easing.SpringOut);
                else if (Scale < MIN_SCALE)
                    this.ScaleTo(MIN_SCALE, 250, Easing.SpringOut);
                break;
        }
    }

    private T Clamp<T>(T value, T minimum, T maximum) where T: IComparable
    {
        if (value.CompareTo(minimum) < 0)
            return minimum;
        else if (value.CompareTo(maximum) > 0)
            return maximum;
        else
            return value;
    }
}

Удачи, В случае запросов любезно вернуться.

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