如何与 Android 中的 xamarin 表单图像进行交互?

How can I interact with a xamarin forms image in Android?

我在 Xamarin Forms 中有一个图像。我想使用本机 android 功能与此图像进行交互。例如,当图像被点击时,我想知道图像被点击位置的 x,y 坐标。我可以使用 Android ImageView,但我不确定如何将 Xamarin Forms 图像转换为 Android ImageView

[assembly: ExportRenderer(typeof(Image), typeof(FloorplanImageRenderer))]
namespace EmployeeApp.Droid.Platform
{

  public class FloorplanImageRenderer : ImageRenderer
  {
        protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
        {
            if (Control == null)
            {

                var imageView = (ImageView)e.NewElement; // This is not right

            }

            base.OnElementChanged(e);
        }
   }
}

But the Control is null....

不,它不应该为空。回到你的问题,我认为首先,你需要将触摸事件附加到 PCL 中的图像控件,并创建一个 属性 来在图像被触摸时保持坐标。我认为在您的代码中:

[assembly: ExportRenderer(typeof(Image), typeof(FloorplanImageRenderer))]

我觉得这里的Image应该是你自定义的图片控件,继承自PCL中的Image。

为触摸事件创建接口:

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