UI is not rendering for the same way on iOS 10.1 and iOS 10.4

Pierre-ChristopheDusPierre-ChristopheDus FRUniversity ✭✭✭

Hello,

I work on a Xamarin.Forms app where I need to implement transparent/translucent navigation bar.

I've studied the the Vision Conference sample, where this is implemented.

This is achieved through a CustomNavigationPage and a CustomRenderer.

The XAML of the CustomNavigationPage is:

<?xml version="1.0" encoding="utf-8" ?>
<NavigationPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="ConferenceVision.Views.CustomNavigationPage"
    xmlns:iOS="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
    iOS:NavigationPage.IsNavigationBarTranslucent="True"
    BarTextColor="{StaticResource NavigationBarTextColor}">
    <NavigationPage.BarBackgroundColor>
        <OnPlatform x:TypeArguments="Color">
            <On Platform="Android, iOS" Value="Transparent" />
            <On Platform="UWP" Value="{StaticResource NavigationBarBackgroundColor}" />
        </OnPlatform>
    </NavigationPage.BarBackgroundColor>
</NavigationPage>

The code-behind of the CustomNavigationPage is:

public partial class CustomNavigationPage : NavigationPage
{
    public bool IgnoreLayoutChange { get; set; } = false;

    protected override void OnSizeAllocated(double width, double height)
    {
        if (!IgnoreLayoutChange)
            base.OnSizeAllocated(width, height);
    }

    public CustomNavigationPage() : base()
    {
        InitializeComponent();
    }

    public CustomNavigationPage(Page root) : base(root)
    {
        InitializeComponent();
    }
}

And the CustomRenderer is:

public class CustomNavigationRenderer : NavigationRenderer
{
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
        UINavigationBar.Appearance.ShadowImage = new UIImage();
        UINavigationBar.Appearance.BackgroundColor = UIColor.Clear;
        UINavigationBar.Appearance.TintColor = UIColor.White;
        UINavigationBar.Appearance.BarTintColor = UIColor.Clear;
        UINavigationBar.Appearance.Translucent = true;
        UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
        {
            Font = UIFont.FromName("HelveticaNeue-Light", (nfloat)20f),
            TextColor = UIColor.White
        });
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
        }

        base.Dispose(disposing);
    }
}

I've tested the app on :

  • simulators : iPhone 6 on iOS 11.3
  • my device : iPhone 6 on iOS 10.1

And we can see that the results are not the same. On the simulator and iOS 11.3, there is a gap between the navigation bar and the content:

screenshot iOS 11.3

But on my device under iOS 10.1, there is no gap and the content is displayed "under" the navigation bar:

screenshot iOS 10.1

The page is built like that, but the rendering is the same on all pages:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:effects="clr-namespace:ConferenceVision.Effects"
             xmlns:local="clr-namespace:ConferenceVision.Views.Renderers"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"              
             ios:Page.UseSafeArea="true"
             Title="About"
             x:Class="ConferenceVision.Views.AboutView">
    <ContentPage.Content>
            <ScrollView>
                <ScrollView.Margin>
                    <OnPlatform x:TypeArguments="Thickness" Default="15,0">
                        <On Platform="Android" Value="15,50,15,0"/>
                    </OnPlatform>
                </ScrollView.Margin>
                ...
            </ScrollView>
    </ContentPage.Content>
</ContentPage>

How explain it? Could this be related to the use of UseSafeArea?
I know that I get an "old" version on my device, but in my app I have to cover the largest number of users.

Posts

  • LandLuLandLu Member, Xamarin Team Xamurai

    When you set the UINavigationBar's Translucent to true, the controller's content will be rendered from the point (0, 0) instead of (0, navigationBar's height). So your content looks covered by navigation bar. But iOS offers us a property called AutomaticallyAdjustsScrollViewInsets , when it is set to true the view controller will automatically adjust its view insets. On iOS 11 because of safe area apple deprecate this api and recommend developers to use 'UIScrollView.ContentInsetAdjustmentBehavior' instead. It seems Forms doesn't support AutomaticallyAdjustsScrollViewInsets very well, but works properly on iOS 11.
    I think we can achieve this effect manually like:

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
    
        UIScrollView scrollView = View.Subviews.FirstOrDefault() as UIScrollView;
        var yOffset = UIApplication.SharedApplication.StatusBarFrame.Size.Height + NavigationController.NavigationBar.Frame.Size.Height;
        if (!UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
        {
            scrollView.ContentInset = new UIEdgeInsets(yOffset, 0, 0, 0);
            scrollView.ContentOffset = new CGPoint(0, -yOffset);
        }
    }
    

    Create a custom renderer for your issue page, put the code above there.

  • skadookkunnanskadookkunnan Member ✭✭
    edited May 15

    @LandLu Thank you for the answer.

    Is there any update to this solution? Can we get this working without implementing a CustomRender?

    Please let us know, we are also facing the same issue right now and we need to support our app from iOS 9 onwards.

Sign In or Register to comment.