iOS上的自定义图像渲染器,用于获取抽头位置的x,y坐标

时间:2017-04-17 13:37:16

标签: c# xamarin xamarin.ios xamarin.forms custom-renderer

我有一个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;
}

1 个答案:

答案 0 :(得分:0)

我在github上发现这个Customer success example就是这样做的。

[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
    }
}