【问题标题】:Create floating drag-able button programatically without storyboard (Xamarin)在没有情节提要的情况下以编程方式创建浮动可拖动按钮(Xamarin)
【发布时间】:2017-01-24 17:10:24
【问题描述】:

我有一个以编程方式创建的按钮

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

我想以编程方式为其添加拖放功能。问题是,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);
};

根据 Using Touch in iOS https://developer.xamarin.com/guides/ios/application_fundamentals/touch/ios_touch_walkthrough/ 的 Xamarin 示例,他们使用情节提要。

创建了一个自定义UIViewController

partial class TouchViewController : UIViewController

并通过设置自定义类分配给 ViewController

<viewController id="18" sceneMemberID="viewController" customClass="TouchViewController">

如何以编程方式设置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 方法。

在尝试了网上找到的所有教程之后,我现在很沮丧。

任何帮助将不胜感激

【问题讨论】:

    标签: c# visual-studio drag-and-drop xamarin.ios uibutton


    【解决方案1】:

    好的,我用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; }
        }
    }
    

    感谢 Yvan Rodrigues - 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();
    };
    

    【讨论】:

      猜你喜欢
      • 2017-10-19
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 1970-01-01
      • 2015-10-26
      • 1970-01-01
      • 2017-07-16
      相关资源
      最近更新 更多