2017-08-07 37 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安卓照片瀏覽器包括所有這些功能。 –