首页 > 解决方案 > Xamarin 将缩放/旋转添加到 ContentView

问题描述

我有个问题。我创建了一个 CustomView,我可以在其中拖放视图,但现在我还想为其添加缩放/旋转功能。现在这里是为移动视图而创建的 OnTouchEvent:

public override bool OnTouchEvent(MotionEvent e)
{
    float x = e.RawX;
    float y = e.RawY;
    var dragView = Element as DraggableView.DraggableView;

    switch (e.Action)
    {
        case MotionEventActions.Down:
            if (dragView.DragMode == DragMode.Touch)
            {
                if (!touchedDown)
                {
                    if (firstTime)
                    {
                        originalX = GetX();
                        originalY = GetY();
                        firstTime = false;
                    }
                    dragView.DragStarted();
                }
                TextMoved = false;
                touchedDown = true;
                stopwatch.Start();
            }
            dX = x - this.GetX();
            dY = y - this.GetY();
            break;
        case MotionEventActions.Move:
            if (touchedDown)
            {
                if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
                {
                    SetX(x - dX);
                }

                if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
                {
                    SetY(y - dY);
                }

                TextMoved = true;
            }
            break;
        case MotionEventActions.Up:
            touchedDown = false;

            if(TextMoved == true)
            {
                dragView.DragEnded();
            }
            else
            {
                MessagingCenter.Send<object, DraggableView.DraggableView>(this, "EditSelectedText", dragView);
            }

            break;
        case MotionEventActions.Cancel:
            touchedDown = false;
            break;
    }
    return base.OnTouchEvent(e);
}

但现在我还需要缩放/旋转功能。问题是我已经为我的skiasharp 位图创建了它,但这不是skiasharp,所以我不能使用它。

如何在没有skiasharp的情况下在 OnTouchEvent 中实现此功能?

标签: c#xamarinxamarin.formsxamarin.androidxamarin.ios

解决方案


有一个关于ScaleAndRotate的 xamarin-forms-samples ,但是它与TouchEvent.I 无关。我找到了一种方法,使用PanGestureRecognizerPinchGestureRecognizer来实现它。

创建一个ScaleAndRotateContainer ContentView,其中包含PanGestureRecognizerPinchGestureRecognizer

public class ScaleAndRotateContainer : ContentView
{
    double currentScale = 1;
    double startScale = 1;
    double xOffset = 0;
    double yOffset = 0;
    double rotateNum = 1;
    public ScaleAndRotateContainer()
    {
        var pinchGesture = new PinchGestureRecognizer ();
        pinchGesture.PinchUpdated += OnPinchUpdated;
        var panGesture = new PanGestureRecognizer();
        panGesture.PanUpdated += PanGesture_PanUpdated;
        GestureRecognizers.Add (pinchGesture);
        GestureRecognizers.Add(panGesture);
    }

    private void PanGesture_PanUpdated(object sender, PanUpdatedEventArgs e)
    {
        rotateNum++;
        this.RotateTo(rotateNum);
        this.AnchorX = 0.5;
        this.AnchorY = 0.5;
    }

    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 = targetX.Clamp (-Content.Width * (currentScale - 1), 0);
            Content.TranslationY = targetY.Clamp (-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;
        }
    }
}

然后在Xaml中为 ContentPage 使用它:

xmlns:local="clr-namespace:PinchGesture;assembly=YourNameSpace"

<local:ScaleAndRotateContainer>
    <local:ScaleAndRotateContainer.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center" >
            <Label Text="Hello Xamarin.Forms!" />
            <Image Source="waterfront.jpg" />
        </StackLayout>
    </local:ScaleAndRotateContainer.Content>
</local:ScaleAndRotateContainer>

效果:

在此处输入图像描述


推荐阅读