2017-01-24 75 views
0

我有一個按鈕創建編程創建編程浮拖能按鈕沒有故事板(Xamarin)

InfoBtn = _utilProvider.FloatingBtn("My Button"); //Returns Floating UIButton 
InfoBtn.Frame = new CGRect((ScreenWidth/2) - 22.5, ScreenHeight - 65, 55, 55); 
View.Add(InfoBtn); 

enter image description here

我想補充的阻力和編程能力的下降給它。問題是,由Xamarin迷上了事件不會讓我使用自定義事件處理程序,如UIEvent以這種方式(從https://www.cocoanetics.com/2010/11/draggable-buttons-labels/的iOS例如直接轉換):

InfoBtn.TouchDragInside += (btn, uievent) => 
{ 
    var button = (UIButton)btn; 
    var e = (UIEvent)uievent; //ERROR: Can not convert type 'System.EventArgs' to 'UIKit.UIEvent' 
    // get the touch 
    UITouch touch = (UITouch)e.TouchesForView(button).AnyObject; 

    // get delta 
    CGPoint previousLocation = touch.PreviousLocationInView(button); 
    CGPoint location = touch.LocationInView(button); 
    nfloat delta_x = location.X - previousLocation.X; 
    nfloat delta_y = location.Y - previousLocation.Y; 

    // move button 
    button.Center = new CGPoint(button.Center.X + delta_x, button.Center.Y + delta_y); 
}; 

根據Xamarin的例子,因爲他們使用Using Touch in iOShttps://developer.xamarin.com/guides/ios/application_fundamentals/touch/ios_touch_walkthrough/故事板。

定製UIViewController通過設置自定義類

創建

partial class TouchViewController : UIViewController 

,並分配到ViewController怎麼可能customClass進行編程設定?

我也嘗試添加UIGestureRecognizer

InfoBtn.AddGestureRecognizer(new MyGestureRecognizer()); 

partial class MyGestureRecognizer : UIGestureRecognizer 
{ 
    public override void TouchesBegan(NSSet touches, UIEvent evt) 
    { 
     base.TouchesBegan(touches, evt); 

     UITouch touch = touches.AnyObject as UITouch; 
     if (touch != null) 
     { 
      // Touch started 
     } 
    } 

    public override void TouchesCancelled(NSSet touches, UIEvent evt) 
    { 
     base.TouchesCancelled(touches, evt); 
    } 

    public override void TouchesEnded(NSSet touches, UIEvent evt) 
    { 
     base.TouchesEnded(touches, evt); 
    } 

    public override void TouchesMoved(NSSet touches, UIEvent evt) 
    { 
     base.TouchesMoved(touches, evt); 
     UITouch touch = touches.AnyObject as UITouch; 
     if (touch != null) 
     { 
      // move the shape 
     } 
    } 
} 

但它永遠只能進入TouchesBegan方法。

基本上在網上找到每個教程後,我感到沮喪。

任何幫助,將不勝感激

回答

0

好,我知道它使用https://github.com/TwoRedCells/UIDragDropGestureRecognizer-Xamarin.iOS

我已經修改了類了一下,這裏是工作代碼工作:

ViewDidLoad()

InfoBtn = _utilProvider.FloatingBtn("My Button"); //Returns Floating UIButton 
var dd = new DragDropGestureRecognizer(); 
dd.Dragging += (object sender, DragDropEventArgs e) => 
{ 
    var view = ((DragDropGestureRecognizer)sender).View; 

    // Reposition box. 
    var x = e.ViewWasAt.X + e.Delta.X; 
    var y = e.ViewWasAt.Y + e.Delta.Y; 
    view.Center = new CGPoint(x, y); 
}; 
InfoBtn.AddGestureRecognizer(dd); 
InfoBtn.TouchUpInside += async (object sender, EventArgs e) => 
{ 
    //Button On Click 
}; 
InfoBtn.Frame = new CGRect((ScreenWidth/2) - 22.5, ScreenHeight - 65, 55, 55); 
View.Add(InfoBtn); 

添加了與我的應用程序具有相同命名空間的類DragDropGestureRecognizer.cs

using System; 
using CGPoint = System.Drawing.PointF; 
using Foundation; 
using UIKit; 

namespace myNS 
{ 
    public class DragDropGestureRecognizer : UIGestureRecognizer 
    { 
     public DragDropGestureRecognizer() 
     { 
     } 

     public event EventHandler<DragDropEventArgs> Held; 
     protected void OnHeld(object sender, DragDropEventArgs e) 
     { 
      if (Held != null) 
       Held(sender, e); 
     } 

     public event EventHandler<DragDropEventArgs> Dragging; 
     protected void OnDragging(object sender, DragDropEventArgs e) 
     { 
      if (Dragging != null) 
       Dragging(sender, e); 
     } 


     public event EventHandler<DragDropEventArgs> Dropped; 
     protected void OnDropped(object sender, DragDropEventArgs e) 
     { 
      if (Dropped != null) 
       Dropped(sender, e); 
     } 

     public bool DidDrag { get; private set; } 
     public CGPoint DownAt { get; private set; } 
     public CGPoint DragAt { get; private set; } 
     public CGPoint ViewWasAt { get; private set; } 
     public CGPoint Delta 
     { 
      get { return new CGPoint(DragAt.X - DownAt.X, DragAt.Y - DownAt.Y); } 
     } 
     public bool Active { get { return DidDrag; } } 
     public override UIGestureRecognizerState State 
     { 
      get { return base.State; } 
      set { base.State = value; } 
     } 
     private CGPoint TouchPoint { get { return (CGPoint)LocationInView(View.Superview); } } 

     public override bool CanBePreventedByGestureRecognizer(UIGestureRecognizer preventingGestureRecognizer) 
     { 
      return false; 
     } 

     public override void TouchesBegan(NSSet touches, UIEvent evt) 
     { 
      base.TouchesBegan(touches, evt); 

      if (NumberOfTouches > 1) 
      { 
       State = UIGestureRecognizerState.Failed; 
       return; 
      } 

      OnHeld(this, new DragDropEventArgs(default(UIGestureRecognizerState), DragAt, Delta, ViewWasAt)); 

      DownAt = TouchPoint; 
      ViewWasAt = (CGPoint)View.Center; 
      State = UIGestureRecognizerState.Possible; 
     } 

     public override void TouchesEnded(NSSet touches, UIEvent evt) 
     { 
      base.TouchesEnded(touches, evt); 

      if (DidDrag) 
      { 
       State = UIGestureRecognizerState.Recognized; 
       OnDropped(this, new DragDropEventArgs(State, DragAt, Delta, ViewWasAt)); 
      } 
      else 
       State = UIGestureRecognizerState.Failed; 
     } 

     public override void TouchesCancelled(NSSet touches, UIEvent evt) 
     { 
      base.TouchesCancelled(touches, evt); 
      State = UIGestureRecognizerState.Failed; 
     } 

     public override void TouchesMoved(NSSet touches, UIEvent evt) 
     { 
      base.TouchesMoved(touches, evt); 
      if (State == UIGestureRecognizerState.Failed) 
       return; 

      DragAt = TouchPoint; 
      if (Distance(DownAt, DragAt) > 30 || DidDrag) //Won't move until dragged further than 30px 
      { 
       DidDrag = true; 
       OnDragging(this, new DragDropEventArgs(State, DragAt, Delta, ViewWasAt)); 
       State = UIGestureRecognizerState.Changed; 
      } 
     } 

     public override void Reset() 
     { 
      base.Reset(); 

      State = UIGestureRecognizerState.Possible; 
      DownAt = CGPoint.Empty; 
      DragAt = CGPoint.Empty; 
      DidDrag = false; 
     } 

     private float Distance(CGPoint point1, CGPoint point2) 
     { 
      var dx = point1.X - point2.X; 
      var dy = point1.Y - point2.Y; 
      return (float)Math.Sqrt(dx * dx + dy * dy); 
     } 
    } 

    public class DragDropEventArgs : EventArgs 
    { 
     public DragDropEventArgs(UIGestureRecognizerState state, CGPoint point, CGPoint delta, CGPoint viewWasAt) 
     { 
      State = state; 
      Point = point; 
      Delta = delta; 
      ViewWasAt = viewWasAt; 
     } 

     public UIGestureRecognizerState State { get; private set; } 
     public CGPoint Point { get; private set; } 
     public CGPoint Delta { get; private set; } 
     public CGPoint ViewWasAt { get; private set; } 
    } 
} 

感謝伊凡·羅德里格斯 - TwoRedCells


的Android等效:

private int _xPad, _yPad, _xDelta, _yDelta; 
prviate bool _moved; 

InfoBtn.Touch += (v, me) => //InfoBtn is a button within a frameLayout 
{ 
    int X = (int)me.Event.RawX; 
    int Y = (int)me.Event.RawY; 
    switch (me.Event.Action & MotionEventActions.Mask) 
    { 
     case MotionEventActions.Down: 
      _xPad = frameLayout.PaddingLeft; 
      _yPad = frameLayout.PaddingTop; 
      _xDelta = X; 
      _yDelta = Y; 
      _moved = false; 
      break; 
     case MotionEventActions.Up: 
      if (!_moved) 
      { 
       //On Button Click 
      } 
      break; 
     case MotionEventActions.PointerDown: 
      break; 
     case MotionEventActions.PointerUp: 
      break; 
     case MotionEventActions.Move: 
      var _x = X - _xDelta; 
      var _y = Y - _yDelta; 
      _moved = _moved || Math.Abs(_x) > 100 || Math.Abs(_y) > 100; //100px 
      if (_moved) 
      { 
       var padleft = _x - _xPad; 
       padleft = padleft + InfoBtn.Width > Resources.DisplayMetrics.WidthPixels ? Resources.DisplayMetrics.WidthPixels - InfoBtn.Width : padleft; 
       var padtop = _y - _yPad; 
       padtop = padtop + InfoBtn.Height > Resources.DisplayMetrics.HeightPixels ? Resources.DisplayMetrics.HeightPixels - InfoBtn.Height : padtop; 
       frameLayout.SetPadding(0, 0, padleft, padtop); 
      } 
      break; 
    } 
    frameLayout.Invalidate(); 
};