Xamarin.Forms: Displaying a Native Android Page

Intro

Within Xamarn.Forms, we may find ourselves having to show a custom page per device platform (i.e. IOS, Android, etc.) In my case, I needed to display a content page that had a map along with some other controls. In this post I will demonstrate how to load a native android page within a Xamarin.Forms app.

Steps

  1. Add a new class to your Xamarin.Forms project and call it “CustomPage”.

Solution Explorer:

SolutionExplorer_customPage

Class:

using Xamarin.Forms;
 
namespace Pickup
{
    public class CustomPage : ContentPage { }
}

2. In your Xamarin.Forms project, add a XAML file.

SolutionExplorer_xamlFile

Implement the following XAML:

<?xml version="1.0" encoding="utf-8" ?>
<local:CustomPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:Pickup;assembly=Pickup" 
x:Class="Pickup.MapPage" />

3. Add a Layout folder to your Android project as well as an axml file.

SolutionExplorer_axmlFile

4. Implement the axml file as the following:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="200dp" android:layout_height="200dp" class="com.google.android.gms.maps.MapFragment" />

  <TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="top"/>
  
  <View android:layout_height="0dp" android:layout_width="fill_parent" android:layout_weight="1" />
  
  <Button android:id="@+id/button_code" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Locate Me!" />
</LinearLayout>

5. Add a custom renderer to your Android project by adding a new class.
SolutionExplorer_maprenderer

6. Implement the renderer with the following code:

[assembly: ExportRenderer(typeof(CustomPage),
                          typeof(MapPageRenderer))]
namespace Pickup.Droid
{
    public class MapPageRenderer : PageRenderer
    {
        Android.Views.View _view;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);
 
            var activity = this.Context as Activity;
            _view = activity.LayoutInflater.Inflate(Resource.Layout.MapLayout, this, false);
 
            AddView(_view);
        }
 
        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
            _view.Measure(msw, msh);
            _view.Layout(0, 0, r - l, b - t);
        }
    }
}

7. When you run your app, you should see something like this:

defaultMap

Conclusion

In conclusion, we may find ourselves having to show a custom page with Xamarin.Forms per device platform (i.e. IOS, Android, etc.) In my case, I needed to display a content page that had a map along with some other controls. In this post I demonstrated how to load a native android page within a Xamarin.Forms app.

NOTE:

Scott Nimrod is fascinated with Software Craftsmanship.

He loves responding to feedback and encourages people to share his articles.

He can be reached at scott.nimrod @ bizmonger.net

Leave a comment