Xamarin,Android和Google地图:我无法上下移动地图(仅左右)

时间:2017-10-10 07:23:13

标签: android google-maps xamarin xamarin.forms

在一个页面中,我有一个ScrollView,里面有一些标签,中间有一个Google Maps。在Android中,当我尝试向上或向下移动地图时,所有页面都会移动但是地图。要使用Xamarin.Forms.GoogleMaps显示地图,请执行此操作。我创建了自己的custommap来绘制路线。该组件运行良好,我可以在iOSAndroid中查看地图,我可以移动地图。

我在Stackoverflow和this post上阅读了一些帖子,但是这些人总是一个活动,项目是原生的。

我创建了:

TouchableMapFragment

public class TouchableMapFragment : MapFragment
{
  public event EventHandler TouchDown;
  public event EventHandler TouchUp;

  public override View OnCreateView(LayoutInflater inflater, 
                                    ViewGroup container, Bundle savedInstanceState)
  {
    var root = base.OnCreateView(inflater, container, savedInstanceState);
    var wrapper = new TouchableWrapper(Activity);
    wrapper.SetBackgroundColor(Resources.GetColor(Android.Resource.Color.Transparent));
    ((ViewGroup) root).AddView(wrapper,
      new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, 
      ViewGroup.LayoutParams.MatchParent));

    wrapper.TouchUp = () =>
    {
      if (TouchUp != null)
        TouchUp(this, EventArgs.Empty);
    };
    wrapper.TouchDown = () =>
    {
      if (TouchDown != null)
        TouchDown(this, EventArgs.Empty);
    };

    return root;
  }

  class TouchableWrapper : FrameLayout
  {
    public Action TouchDown;
    public Action TouchUp;

    #region ctors
    protected TouchableWrapper(IntPtr javaReference, JniHandleOwnership transfer) 
      : base(javaReference, transfer) {}
    public TouchableWrapper(Context context) 
      : this(context, null) {}
    public TouchableWrapper(Context context, IAttributeSet attrs) 
      : this(context, attrs, 0) {}
    public TouchableWrapper(Context context, IAttributeSet attrs, int defStyle) 
      : base(context, attrs, defStyle) { }
    #endregion

    public override bool DispatchTouchEvent(MotionEvent e)
    {
      switch (e.Action)
      {
        case MotionEventActions.Down:
          if (TouchDown != null)
            TouchDown();
          break;
        case MotionEventActions.Cancel:
        case MotionEventActions.Up:
          if (TouchUp != null)
            TouchUp();
          break;
      }

      return base.DispatchTouchEvent(e);
    }
  }
}

view.xaml

<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/scroll">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="match_parent">
        <fragment
            android:id="@+id/map"
            android:layout_width="600dp"
            android:layout_height="match_parent"
            android:name="my.awesome.namespace.TouchableMapFragment" />
    </LinearLayout>
</HorizontalScrollView>

Activity.cs

public class MyActivity : Activity
{
  private GoogleMap _map;
  private HorizontalScrollView _hsv;

  protected override void OnCreate(Bundle bundle)
  {
    base.OnCreate(bundle);
    SetContentView(Resource.Layout.rtc);

    _hsv = FindViewById<HorizontalScrollView>(Resource.Id.scroll);
    SetupMapIfNeeded();
  }

  private void SetupMapIfNeeded()
  {
    if (null != _map) return;

    var frag = FragmentManager.FindFragmentById<TouchableMapFragment>(Resource.Id.map);
    if (frag != null)
    {
      frag.TouchUp += (sender, args) => _hsv.RequestDisallowInterceptTouchEvent(false);
      frag.TouchDown += (sender, args) => _hsv.RequestDisallowInterceptTouchEvent(true);

      _map = frag.Map;
      if (_map == null) return; // will probably not happen

      // do stuff to _map here, such as adding overlays etc.
    }
  }
}

有几个错误:

  • 如何解决Android问题以正确移动地图?
  • 的setContentView(Resource.Layout.rtc);什么是rtc?
  • Resource.Id.map不存在

就我而言,我有一个包含iOS和Android项目的PCL解决方案。在iOS中一切都很好。唯一的问题是Android。我该如何解决这个问题?

有什么建议吗?感谢。

2 个答案:

答案 0 :(得分:1)

  

我的问题与我找到的代码有关。我无法理解如何在Xamarin.Forms中使用它

在XF框架中,我们只有一个Activity,表示默认MainAcitivty,所有视图都是根据此MainAcitivty显示的,您希望从客户端Android显示自定义视图在PCL中的项目,通常我们使用Custom Renderer来创建视图渲染器,对于您的情况,您的view.axml是客户端Android项目中的布局资源,那么您应该在渲染器内实现此视图的逻辑代码。

首先在PCL中创建View的子类,以便像普通的XF控件一样使用它:

public class ScrollViewWithMap:View
{
}

然后在Android客户端项目中将view.axml放在Resources/layout文件夹下,并一起创建它的渲染器:

[assembly: ExportRenderer(typeof(ScrollViewWithMap), typeof(ScrollViewWithMapRenderer))]

namespace YOURNAMESPACE.Droid
{
    public class ScrollViewWithMapRenderer : ViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);
            if (Control == null)
            {
                var context = Xamarin.Forms.Forms.Context;
                LayoutInflater minflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
                var view = minflater.Inflate(Resource.Layout.view, this, false);
                SetNativeControl(view);
            }
        }
    }
}

然后您可以将逻辑代码从MyActivity移到此ScrollViewWithMapRenderer,例如:

public class ScrollViewWithMapRenderer : ViewRenderer
{
    private GoogleMap _map;
    private HorizontalScrollView _hsv;
    private Context context = Xamarin.Forms.Forms.Context;

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);
        if (Control == null)
        {
            LayoutInflater minflater = context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
            var view = minflater.Inflate(Resource.Layout.view, this, false);
            _hsv = view.FindViewById<HorizontalScrollView>(Resource.Id.scroll);
            SetNativeControl(view);

            SetupMapIfNeeded();
        }
    }

    private void SetupMapIfNeeded()
    {
        if (null != _map) return;
        var frag = ((Activity)context).FragmentManager.FindFragmentById<TouchableMapFragment>(Resource.Id.map);
        if (frag != null)
        {
            frag.TouchUp += (sender, args) => _hsv.RequestDisallowInterceptTouchEvent(false);
            frag.TouchDown += (sender, args) => _hsv.RequestDisallowInterceptTouchEvent(true);

            _map = frag.Map;
            if (_map == null) return; // will probably not happen

            // do stuff to _map here, such as adding overlays etc.
        }
    }
}

我在Map中找不到属性TouchableMapFragment,我认为您的代码不完整,您应该能够解决此问题。顺便说一下,代码TouchableMapFragment也应放在android客户端项目中。

最后,我们可以在PCL中使用此ScrollViewWithMap,例如:

<local:ScrollViewWithMap />

答案 1 :(得分:0)

  1. 基本上是Resource.Layout.xxxx xxxx&#34;是布局文件的名称,即xxxx.xml
  2. layout.xml中的任何组件都可以有一个&#34; id&#34;属性 例如,如果我们有一个

    <Button id="@+id/something"></Button>
    

    然后按钮的ID是&#34;&#34;我们可以从后面的代码中获取此视图 通过调用

    Button btn = (Button) v.findViewById(Resource.id.something);
    
  3. 基于您的代码的最佳解决方案,可能会将 view.axml 更改为 rtc.axml