2017-08-07 60 views
0

我发现了一些代码来放大和缩小Xamarin窗体。在iOS上,它工作顺利,但在Android上它有一些滞后,这里是视频如何工作http://fs2.fex.net/get/688885800398/30602583/5998218f/2017_08_07_19_45_28.mp4 我不知道如何使它流畅,你能帮助吗?Xamarin在Android上的ZoomIn延迟

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

设置一个断点,并确保OnMeasure,当你捏不被调用。 –

+0

可能你是对的,但我已经评论过它们,它在缩放过程中仍然存在滞后现象......我认为这可能是缓慢的处理器或内存问题,但我已经在真实设备上进行了测试,因此它不是一个选项 –

回答

0

我没有任何想法如何让它顺利,你可以用这个

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

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

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

感谢您的回复!这是我在xamarin论坛上发现的真实情况,这已经足够了。如果我将删除平移和点击手势,它将不会提供移动到某个点的选项,这些点在缩放后不在屏幕上。 如何使用捏,平移和轻击手势识别器进行缩放功能?对于例如defualt安卓照片浏览器包括所有这些功能。 –