3 votes

lorsque j'ajoute un geste de tapotement, le pincement et le panoramique ne fonctionnent pas dans les formulaires xamarin.

Je veux créer une fonctionnalité permettant de toucher et d'ajouter une image d'épingle sur une autre image d'arrière-plan et l'image d'arrière-plan doit être capable de zoomer et de faire un panoramique. Voici le code XAML pour cela, ici le zoom par pincement ne fonctionne pas mais l'événement de toucher fonctionne bien.

<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>

dans le fichier cs, cette commande de robinet ajoute une image d'épingle à l'intérieur de la disposition absolue en utilisant les coordonnées dans Point.

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

Maintenant si on enlève juste ui:Gesture.TapCommand2="{Binding TapCommand2}" cette propriété du code ci-dessus pinch et pan fonctionne bien.

Pour l'événement Tap, j'ai utilisé le paquet NuGet Vapolia.XamarinFormsGesture et pour le pinch et le pan, j'ai utilisé le Gesture Recognizer de xamarin forms. Quelqu'un peut-il m'aider ?

1voto

G.hakim Points 5733

Récemment, j'ai réalisé une fonctionnalité similaire et j'ai fini par créer un CustomControl comme ci-dessous :

Note : J'ai utilisé l'image FFImageLoadings CachedImage dans ma classe. Si vous n'utilisez pas FFImage, remplacez-la par l'image défectueuse de votre formulaire xamarin.

Et celui-ci dispose des fonctionnalités suivantes : PanSwipe, Zoom et DoubleTap pour zoomer.

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;
    }
}

Bonne chance, En cas de questions, veuillez nous contacter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X