Reputation: 6276
In a Page I have a ScrollView
and inside some labels and a Google Maps
in the middle. In Android, when I try to move the map up or down, all page is moved but the map. To display the map I'm using Xamarin.Forms.GoogleMaps. I created my own custommap
to draw a route. The component is working well, I can see the map in iOS
and Android
and I can move the map.
I read some posts on Stackoverflow and this post but always the guys are an Activity and the project is native.
I created:
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.
}
}
}
There are a couple of errors:
In my case, I have a PCL solution with iOS and Android projects. In iOS everything is fine. The only problem is for Android. How can I fix this problem?
Any advice? Thanks.
Upvotes: 0
Views: 937
Reputation: 16652
My question is related to the code I found. I can't understand how I can use it in Xamarin.Forms
In XF framework, we only have one Activity
, means the default MainAcitivty
, all views are displayed based on this MainAcitivty
, it you want to show a custom view from client Android project in PCL, usually we use Custom Renderer
to create a view Renderer, for your case your view.axml
is the layout resource in client Android project, then you should implement the logic code for this view inside the renderer.
First create a subclass of View
in PCL so it can be used like normal XF control:
public class ScrollViewWithMap:View
{
}
Then in Android client project place your view.axml under the Resources/layout
folder and together create it's renderer:
[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);
}
}
}
}
Then you can move the logic code from your MyActivity
to this ScrollViewWithMapRenderer
for example:
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.
}
}
}
I couldn't find a property Map
in your TouchableMapFragment
, I think you code in incomplete and you should be able to solve this issue. By the way, the code TouchableMapFragment
should also be placed in android client project.
Finally we can use this ScrollViewWithMap
in PCL for example like this:
<local:ScrollViewWithMap />
Upvotes: 1
Reputation: 1016
Any component inside layout.xml can have an "id" attribute for example if we have a
<Button id="@+id/something"></Button>
then the id of the button is "something" and we can get this view from code behind by calling
Button btn = (Button) v.findViewById(Resource.id.something);
Best possible solution based on your code, maybe change the view.axml to rtc.axml
Upvotes: 0