Augustin Bocken
Augustin Bocken

Reputation: 379

A white bar appear between StatusBar and MasterDetailPage Xamarin.Forms Android

I'm trying to build a simple geolocalization app, who should point to the location of the user on a map after login. This part works fine, but there is a white space that I'd like to see removed from the status bar and the view, but I don't know how.

Here are two links to screens of the bug:

enter image description here

enter image description here

I already tried the solutions presented here: https://forums.xamarin.com/discussion/86568/unwanted-blank-space-above-navigation-bar-navigation-page but it didn't work well: the XAML solutions didn't do anything, and the last solution (with the check on the build version) made the blue bar disappear as well, which is not the researched effect.

Here is some of my code, tell me if you need anything more :

The page where i show my map :

<?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="MyApp.View.Detail"
             xmlns:i18n="clr-namespace:MyApp"
             Title=""
             BackgroundColor="{StaticResource MainBackgroundColor}"
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
  <StackLayout>
    <ActivityIndicator IsRunning="{Binding IsBusy, Mode=TwoWay}" IsVisible="{Binding IsBusy, Mode=TwoWay}" Color="Blue"/>
    <maps:Map VerticalOptions ="FillAndExpand" HorizontalOptions ="FillAndExpand"
            x:Name="MyMap"
            IsShowingUser="true"
            MapType="Street"
        />
  </StackLayout>
</ContentPage>

And here is the MasterViewDetail

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.View.HomePage">

</MasterDetailPage>

Thank you for your help!

EDIT :

Here is the structure of my project :

App(NavigationPage)
    MainPage (ContentPage)
        LoginPage (ContentPage)
            HomePage (MasterDetailPage)
                HomeDetail(ContentPage)
        RegisterPage (ContentPage)

The problem is i'm not totally free with it, i'm an intern and must follow the client's command...

Upvotes: 2

Views: 1601

Answers (1)

JimBobBennett
JimBobBennett

Reputation: 2159

It's built that way inside Xamarin forms - it always adds top padding. A bug has been raised for this, but no idea when it will be fixed.

I've managed to work around it with a custom renderer that does some hacky reflection:

[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(NoSpaceMasterDetailPageRenderer))]

namespace Droid.Renderers
{
    public class NoSpaceMasterDetailPageRenderer : MasterDetailPageRenderer
    {
        /// <summary>
        /// When adding a view, tweak the top padding if necessary.
        /// According to:
        /// https://github.com/xamarin/Xamarin.Forms/blob/589adbd3ef145ec85f9fe64eda008251c1cdb745/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
        /// The TopPadding is always set for the detail. This works fine when the master detail is shown normally, but
        /// if it is inside a navigation page (such as the inspection view) then you get extra unwanted padding.
        /// The 'fix' is to set the top padding to 0 for the detail, only of course the types and fields are hidden from us...
        /// </summary>
        /// <param name="child">Child.</param>
        public override void AddView(Android.Views.View child)
        {
            try
            {
                var isMasterField = child.GetType().GetField("_isMaster", BindingFlags.NonPublic | BindingFlags.Instance);
                if (isMasterField == null) return;

                var isMaster = isMasterField.GetValue(child);
                if ((bool)isMaster) return;

                var parentField = child.GetType().GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance);
                if (parentField == null) return;

                var parent = parentField.GetValue(child) as MasterDetailPage;
                if (parent == null || !(parent.Parent is NavigationPage)) return;

                var topPaddingProperty = child.GetType().GetProperty("TopPadding", BindingFlags.Public | BindingFlags.Instance);
                if (topPaddingProperty != null)
                    topPaddingProperty.SetValue(child, 0);
            }
            finally
            {
                base.AddView(child);
            }
        }
    }
}

Upvotes: 2

Related Questions