gpt4 book ai didi

c# - 在没有 Storyboard 的情况下以编程方式创建 float 的可拖动按钮(Xamarin)

转载 作者:太空宇宙 更新时间:2023-11-03 12:33:39 24 4
gpt4 key购买 nike

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

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 的例子在 iOS 中使用 Touch https://developer.xamarin.com/guides/ios/application_fundamentals/touch/ios_touch_walkthrough/他们使用 Storyboard。

创建了一个自定义的 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 方法。

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

任何帮助将不胜感激

最佳答案

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

关于c# - 在没有 Storyboard 的情况下以编程方式创建 float 的可拖动按钮(Xamarin),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41821364/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com