Search code examples
androidxamarinxamarin.formscustom-renderer

Android Layout page is not inflated for custom page renderer in Xamarin Forms


I am developing a mobile application for both IOS and Android platforms using Xamarin.Forms. First of all, I just started using Xamarins. What I am trying to do now is I am trying to render the different page for iOS and Android. I am using Custom Page Renderer. I custom page rendered is called, but the problem is when I inflate the layout in Android, it seems like it is not inflating the axml file and not displaying anything.

I started my custom CameraPage like this in App.xaml.cs

MainPage = new NavigationPage(new CameraPage());

This is my CameraPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MementoApp.Views.CameraPage">
    <ContentPage.Content>

    </ContentPage.Content>
</ContentPage>

This is my CameraPage.xaml.cs

namespace MementoApp.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CameraPage : ContentPage
    {
        public CameraPage ()
        {
            InitializeComponent ();
        }
    }
}

In the Android project, I created a new class, called CameraPageRenderer.cs. This is the code for that class.

[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace MementoApp.Droid
{
    public class CameraPageRenderer : PageRenderer
    {

        global::Android.Views.View view;

        Activity activity;

        bool flashOn;

        public CameraPageRenderer() : base(null)
        {
            throw new Exception("This constructor should never be used");
        }

        public CameraPageRenderer(Context context) : base(context)
        {
            this.activity = context as Activity;
            LayoutInflater.From(this.Context).Inflate(Resource.Layout.CameraLayout,null, false);
            Console.WriteLine("Page is rendered");
        }

    }
}

As you can see, in the constructor, I am inflating layout resource called CameraLayout. The constructor is run because in the console, it is printing out "Page is rendered". But on the device screen, it is just displaying the blank page like this.

enter image description here

This is the CameraLayout in Android project

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <TextView android:gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" a:text="This is the camera page" xmlns:a="http://schemas.android.com/tools"/>
</LinearLayout>

Actually, it is supposed to display a TextView with a text, "This is the camera page". But as you can see in the screenshot, nothing is displayed. What is wrong with my code and how can I fix it?


Solution

  • You have forgot to add the View to your page.

    After inflating, the Inflate() method will return a View, you need add this View to your page. I found an article for you, you need do something in OnElementChanged method, like this:

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);
    
            var activity = this.Context as Activity;
            view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.CameraLayout,null, false); this, false);
    
            AddView(view);
        }
    

    Change your TextView to this:

      <TextView
                android:gravity="center" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="This is the camera page" 
                />
    

    Add OnLayout method:

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