自定义图像渲染器在iOS上以获取X级位置的X,Y坐标



我有一个Xamarin表单图像,当用户点击图像上时,我想获得用户点击的位置的x,y坐标。不是视图本身的x,y坐标,而是图像中的坐标。我在下面的Android上工作。iOS自定义渲染器会是什么样?

创建触摸事件的接口:

public interface IFloorplanImageController
{
    void SendTouched();
}

为图像创建自定义控件:

public class FloorplanImage : Image, IFloorplanImageController
{
   public event EventHandler Touched;
 public void SendTouched()
 {
     Touched?.Invoke(this, EventArgs.Empty);
 }
 public Tuple<float, float> TouchedCoordinate
 {
     get { return (Tuple<float, float>)GetValue(TouchedCoordinateProperty); }
     set { SetValue(TouchedCoordinateProperty, value); }
 }
 public static readonly BindableProperty TouchedCoordinateProperty =
     BindableProperty.Create(
         propertyName: "TouchedCoordinate",
         returnType: typeof(Tuple<float, float>),
         declaringType: typeof(FloorplanImage),
         defaultValue: new Tuple<float, float>(0, 0),
         propertyChanged: OnPropertyChanged);
 public static void OnPropertyChanged(BindableObject bindable, object oldValue, object newValue)
   {
   }
}

实现自定义渲染器:

[assembly: ExportRenderer(typeof(FloorplanImage), typeof(FloorplanImageRenderer))]
namespace EmployeeApp.Droid.Platform
{
public class FloorplanImageRenderer : ImageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);
        if (e.NewElement != null)
        {
            if (Control != null)
            {
                Control.Clickable = true;
                Control.SetOnTouchListener(ImageTouchListener.Instance.Value);
                Control.SetTag(Control.Id, new JavaObjectWrapper<FloorplanImage> { Obj = Element as FloorplanImage });
            }
        }
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (Control != null)
            {
                Control.SetOnTouchListener(null);
            }
        }
        base.Dispose(disposing);
    }
    private class ImageTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
    {
        public static readonly Lazy<ImageTouchListener> Instance = new Lazy<ImageTouchListener>(
            () => new ImageTouchListener());
        public bool OnTouch(Android.Views.View v, MotionEvent e)
        {
            var obj = v.GetTag(v.Id) as JavaObjectWrapper<FloorplanImage>;
            var element = obj.Obj;
            var controller = element as IFloorplanImageController;
            if (e.Action == Android.Views.MotionEventActions.Down)
            {
                var x = e.GetX();
                var y = e.GetY();
                element.TouchedCoordinate = new Tuple<float, float>(x, y);
                controller?.SendTouched();
            }
            else if (e.Action == Android.Views.MotionEventActions.Up)
            {
            }
            return false;
        }
    }
}
public class JavaObjectWrapper<T> : Java.Lang.Object
{
    public T Obj { get; set; }
}
}

使用这样的控件:

<local:FloorplanImage HeightRequest="300" x:Name="image" WidthRequest="300"
                  Aspect="AspectFit"  Touched="image_Touched" />

代码背后:

private void image_Touched(object sender, EventArgs e)
{
  var cor = image.TouchedCoordinate;
}

我在github上找到了这个客户成功示例。

[assembly: ExportRenderer(typeof(CustomImage), typeof(CustomImageRenderer))]
namespace FormsImageTapGesture.iOS
{
    public class CustomImageRenderer : ImageRenderer
    {
        #region properties & fields
        // ---------------------------------------------------------------------------
        //
        // PROPERTIES & FIELDS
        //
        // ---------------------------------------------------------------------------
        private UIImageView nativeElement;
        private CustomImage formsElement;
        #endregion
        #region methods
        // ---------------------------------------------------------------------------
        //
        // METHODS
        //
        // ---------------------------------------------------------------------------
        //
        // Set up the custom renderer. In this case, that means set up the gesture
        // recognizer.
        //
        protected override void OnElementChanged(ElementChangedEventArgs<Image> e) {
            base.OnElementChanged (e);
            if (e.NewElement != null) {
                // Grab the Xamarin.Forms control (not native)
                formsElement = e.NewElement as CustomImage;
                // Grab the native representation of the Xamarin.Forms control
                nativeElement = Control as UIImageView;
                // Set up a tap gesture recognizer on the native control
                nativeElement.UserInteractionEnabled = true;
                UITapGestureRecognizer tgr = new UITapGestureRecognizer (TapHandler);
                nativeElement.AddGestureRecognizer (tgr);
            }
        }
        //
        // Respond to taps.
        //
        public void TapHandler(UITapGestureRecognizer tgr) {
            CGPoint touchPoint = tgr.LocationInView (nativeElement);
            formsElement.OnTapEvent ((int)touchPoint.X, (int)touchPoint.Y);
        }
        #endregion
    }
}

最新更新