Xamarin ZoomIn 在 Android 上滞后 [英] Xamarin ZoomIn lags on Android

查看:22
本文介绍了Xamarin ZoomIn 在 Android 上滞后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了一些代码来放大和缩小 Xamarin Forms.在 iOS 上它运行顺利,但在 Android 上它有一些滞后,这里是它是如何工作的视频 http://fs2.fex.net/get/688885800398/30602583/5998218f/2017_08_07_19_45_28.mp4我不知道如何让它顺利进行,你能帮忙吗?

I have found some code to zoom In and zoom Out for Xamarin Forms. On iOS it's working smoothly but on Android it has some lags, here is video how it working http://fs2.fex.net/get/688885800398/30602583/5998218f/2017_08_07_19_45_28.mp4 I do not have any idea how to make it smoothly, could you help with this ?

 public class ZoomImage : Image
    {
        private const double MIN_SCALE = 1;
        private const double MAX_SCALE = 1.5;
        private const double OVERSHOOT = 0.9;
        private double StartScale;
        private double LastX, LastY;

        public ZoomImage()
        {
            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  - 50, 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:
                    LastX = (1 - AnchorX) * Width;
                    LastY = (1 - AnchorY) * Height;
                    break;
                case GestureStatus.Running:
                    AnchorX = Clamp(1 - (LastX + e.TotalX) / Width, 0, 1);
                    AnchorY = Clamp(1 - (LastY + e.TotalY) / Height, 0, 1);
                    break;
            }
        }

        private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
        {
            switch (e.Status)
            {
                case GestureStatus.Started:
                    StartScale = Scale;
                    AnchorX = e.ScaleOrigin.X;
                    AnchorY = e.ScaleOrigin.Y;
                    break;
                case GestureStatus.Running:
                    double 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, 50, Easing.SpringOut);
                    else if (Scale < MIN_SCALE)
                        this.ScaleTo(MIN_SCALE, 50, 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;
        }
    }

推荐答案

我不知道如何使它顺利,你能帮忙吗

I do not have any idea how to make it smoothly, could you help with this

为了放大/缩小视图,捏合手势就足够了.不要在 Pan 和 Tapped 手势事件中编写缩放逻辑.而且,我不明白 OVERSHOOT 是什么.但是Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT)) 也会导致放大/缩小的意外行为.

In order to zoom in/out a view, a pinch gesture is enough. Don't write scale logic in your Pan and Tapped gesture events. And also, I don't understand what is the OVERSHOOT for. but Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT)) also leads to the unexpected behavior of the zoom in/out.

所以固定的 ZoomImage 应该看起来像这样(我注释掉了不必要的代码):

So the fixed ZoomImage should looks like this(I commented out the unnecessary codes):

public class ZoomImage : Image
{
    private const double MIN_SCALE = 1;
    private const double MAX_SCALE = 1.5;
    private const double OVERSHOOT = 0.9;
    private double StartScale;
    private double LastX, LastY;

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

        //don't register the Pan gesture and Tap gesture for zoom in/out

        //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 - 50, heightConstraint);
    }


    private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        switch (e.Status)
        {
            case GestureStatus.Started:
                StartScale = Scale;
                AnchorX = e.ScaleOrigin.X;
                AnchorY = e.ScaleOrigin.Y;
                break;
            case GestureStatus.Running:

                double current = Scale + (e.Scale - 1) * StartScale;
                //Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT));
                var parent = (StackLayout)this.Parent;
                var child = parent.Children[1];
                if (child is Label)
                {
                    (child as Label).Text = Clamp(current, MIN_SCALE, MAX_SCALE).ToString();
                }
                Scale = Clamp(current, MIN_SCALE, MAX_SCALE);
                break;
            case GestureStatus.Completed:
                //Scale is already limited to Min_SCALE and MAX_SCALE, the following codes is not necessary

                //if (Scale > MAX_SCALE)
                //this.ScaleTo(MAX_SCALE, 50, Easing.SpringOut);
                //else if (Scale < MIN_SCALE)
                //this.ScaleTo(MIN_SCALE, 50, 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;
    }
}

这篇关于Xamarin ZoomIn 在 Android 上滞后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆