0
votes

I took the source I found here: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs

And created a custom renderer in a Xamarin Forms Android project. I got the project to build and the menu to open / close as expected as well as display the starting detail page.

The detail page is a "NavigaionPage" in Xamarin.Forms which is actually just a ViewGroup with a bunch of code to make it work with Push / Pop functions.

When I push a new Page, one that has a custom renderer and native RelativeLayout as a subview, the Page appears blank white until I rotate orientation.

After some research in the code, I realized both OnMeasure and OnLayout was not being called in the Page which was being pushed to the NavigationPage / detail page (with the pushed page's size stuck at 0x0 until orientation change).

I created another custom renderer but this time for the NavigationPage which looks like this:

public class MasterDetailContentNavigationPageRenderer : NavigationPageRenderer 
{

  protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
  {
    base.OnElementChanged(e);

    if(e.OldElement != null)
    {
      e.OldElement.Pushed -= handleOnPushed;
    }

    if(e.NewElement != null)
    {
      e.NewElement.Pushed += handleOnPushed;
    }
  }

  private void handleOnPushed(object sender, EventArgs e)
  {
    var w = MeasureSpec.MakeMeasureSpec(MeasuredWidth, MeasureSpecMode.Exactly);
    var h = MeasureSpec.MakeMeasureSpec(MeasuredHeight, MeasureSpecMode.Exactly);
    Measure(w, h);
    Layout(Left, Top, Right, Bottom);
  }
}

This custom renderer for the detail page / NavigaionPage worked for 2 out of 3 of my pushed Pages.

The main / most important page did not fully add all of the UI elements.

The Page that was pushed and missing UI has SOME of the UI. The following is a list of how the page is displayed:

--- SongViewerLayout : RelativeLayout

------ RelativeLayout

--------- ViewerTopBar (draws all buttons except one)

--------- DocumentView (blank white spot between top bar and pagination)

--------- ViewerPagination (draws background color but not page buttons)

If I change orientations the missing button appears in the top bar, the page numbers show up and the document view sort of draws but it's off.

If I go back to using Xamarin.Forms provided MasterDetailPage the UI just loads as expected.

I have studied the code in the Xamarin.Forms repo but none of it really applies to the inner workings of the elements that are added. In other words, the detail page (which in my case is a NavigationPage) gets added on SetElement(...) and some handlers are assigned ... but nothing I could tell that looks for Pages being pushed and then responding. I would assume / expect the NavigationPage just to work as expected now that it's a subview of the MasterDetailPage / DrawerLayout.

Note: the views that seems to have the most issues are added programmatically and given "LayoutParamaters". The views found in the AXML seem to just show up.

  • Is there something I am missing to "initialize" a layout in Android? I have made native apps in Android and not had to do anything special.

  • Why would the UI above the NavigationPage cause the NavigationPage not to do standard initialization?

  • What am I missing???

Edit:

I created a working example of this issue on my GitHub account which you can clone here: https://github.com/XamarinMonkey/CustomMasterDetail

  1. Build and run CustomMasterDetail.Droid (Notice the UI is a MasterDetailPage)

  2. Tap any item

  3. The bottom blue bar has no page numbers.

  4. Rotate orientation the page numbers display.

  5. Stop the build

  6. Comment out the entire class "MainMasterDetailPageRenderer.cs"

  7. Rebuild / run the app

  8. Tap any item

  9. Page numbers are shown right away as expected just because it is now using the default MasterDetailPage!

  10. Give suggestions please!

Edit #2:

Thanks to some feedback, it does not seem to be an issue in 6.0 devices. My testing device is a "Samsung Galaxy Tab Pro" with v5.1.1. And unfortunately I need this app to go back to 4!

Edit #3:

The issue has to be adding a view programmatically in Android 5.1.1 to a native RelativeLayout (which is pushed to a NavigationPage detail page ) after it is inflated in Xamarin.Forms. Calling Measure / Layout manually seems to solve the issue. But I need a more automated solution.

1
The link is the source code of xamarin forms. Can you show the MasterDetialPage render in your code?Mike Ma
See my edits, I have a working example on GitHubPaul Hart
I have test your code in my android 6.0 device. It works and can show the page number without comment out the MainMasterDetailPageRenderer .Mike Ma
I am using the "Samsung Galaxy Tab Pro" with v5.1.1Paul Hart
Have you tested it in another device?Mike Ma

1 Answers

0
votes

I came up with a solution that works. It might be expensive but it seems to layout fast on devices I have tested.

Basicly, I read up on Android and found a way to listen for layout changes using the ViewTreeObserver.GlobalLayout event combined with calling Measure / Layout on the detail and master ViewGroups.

public void MeasureAndLayoutNative()
{
    if(_childView != null)
    {
        IVisualElementRenderer renderer = Platform.GetRenderer(_childView);
        if(renderer.ViewGroup != null)
        {
            var nativeView = renderer.ViewGroup;

            var w = MeasureSpec.MakeMeasureSpec(nativeView.MeasuredWidth, MeasureSpecMode.Exactly);
            var h = MeasureSpec.MakeMeasureSpec(nativeView.MeasuredHeight, MeasureSpecMode.Exactly);
            nativeView.Measure(w, h);
            nativeView.Layout(nativeView.Left, nativeView.Top, nativeView.Right, nativeView.Bottom);
        }
    }
}

I updated my code example above with the working changes!