【问题标题】:How can I interact with a xamarin forms image in Android?如何与 Android 中的 xamarin 表单图像进行交互?
【发布时间】:2018-07-05 03:07:03
【问题描述】:

我在 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);
        }
   }
}

【问题讨论】:

  • 检查渲染器本身的Element属性
  • 我该怎么做?
  • 对不起,我弄错了,您正在检查 null 的 Control 属性包含本机变体。我总是把这两者混在一起:)
  • 但控件为空......
  • 所以创建一个检查它什么时候不是。你可能想了解自定义渲染器

标签: xamarin xamarin.android imageview xamarin.forms custom-renderer


【解决方案1】:

但是控制是空的......

不,它不应该为空。回到您的问题,我认为首先,您需要将触摸事件附加到 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;
}

【讨论】:

  • 谢谢,这正是我想要的。有没有机会给我指出一些 ios 的示例代码?
  • @stepheaw,对不起,我对 iOS 不熟悉。
猜你喜欢
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
  • 2011-03-20
  • 2015-11-19
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多