1

I work on a Xamarin.Forms.Shell app containing 4 tabs.

On the main tab, I have:

  • a NavigationBar through a TitleView containing a logo
  • a ScrollView containing an Image as background's header
  • a ScrollView containing the main content, that can cover the Header to be fully visible

The XAML looks like this:

<?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="AvilaShellAppSample.Views.HomePage"
            Shell.NavBarHasShadow="False"
            Shell.NavBarIsVisible="True"
            x:Name="homePage">
    <!-- TitleView -->
    <Shell.TitleView >
        <Grid>
            <ffimageloadingsvg:SvgCachedImage Source="resource://ShellAppSample.Resources.blackLogoTitle.svg"
                                            DownsampleHeight="6"
                                            HeightRequest="45"/>
        </Grid>
    </Shell.TitleView>
    <ContentPage.BindingContext>
        <vm:HomeViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <Grid RowSpacing="0"
            BackgroundColor="{StaticResource Gray-050}"
            Margin="0,0,0,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Grid Grid.Row="1">
                <!--  Header ScrollView : Image  -->
                <ScrollView>
                    <ContentView x:Name="headerView"
                                HorizontalOptions="FillAndExpand"
                                VerticalOptions="FillAndExpand">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <!--  Header Image  -->
                            <ffimageloading:CachedImage x:Name="headerImage"
                                            Grid.Row="0"
                                            Aspect="AspectFill"
                                            BackgroundColor="{DynamicResource Gray-200}"
                                            DownsampleToViewSize="true"
                                            HeightRequest="280"
                                            HorizontalOptions="FillAndExpand"
                                            VerticalOptions="Start"
                                            Source="resource://ShellAppSample.Resources.indoor.jpg">
                            </ffimageloading:CachedImage>
                        </Grid>
                    </ContentView>
                </ScrollView>

                <!--  Content ScrollView  -->
                <ScrollView>
                <ctrl:ParallaxScrollView HorizontalOptions="FillAndExpand"
                                        VerticalOptions="FillAndExpand"
                                        ParallaxHeaderView="{x:Reference headerView}"
                                        LogoHeaderView="{x:Reference logoHeaderView}"
                                        HiddenView="{x:Reference hiddenView}"
                                        MainPage="{Binding homePage}">
                    <Grid ColumnSpacing="0"
                        RowSpacing="0"
                        VerticalOptions="FillAndExpand">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="220" /> 
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <!-- Content -->
                    </Grid>
                </ctrl:ParallaxScrollView>
                </ScrollView>
            </Grid>
        </Grid>
    </ContentPage.Content>
</ContentPage>

Like this, it's working fine.

But I would like:

  • to hide the NavigationBar by default, and to display it only after the user has started to scroll the main content
  • that the Image of the background's header fills all the space from the top screen: so the StatusBar should be be displayed in transparency over this Image

I've changed the XAML to hide the NavigationBar and to display the Header at the top of the screen through a negative Margin:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
            ...
            Shell.NavBarIsVisible="True"
            x:Name="homePage">
    <!-- TitleView -->
    <Shell.TitleView >
        ...
    </Shell.TitleView>
    <ContentPage.BindingContext>
        <vm:HomeViewModel />
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <Grid RowSpacing="0"
            BackgroundColor="{StaticResource Gray-050}"
            Margin="0,-20,0,0">

=> This works well on iOS, but not quite on Android as the StatusBar is not transparent.

Finally, to display the NavigationBar after a scroll, I use a ParallaxScrollView control that get some references of this View.

I do something like this:

if (y <= -60)
{
    Shell.SetNavBarIsVisible(MainPage, true);
    Shell.SetNavBarHasShadow(MainPage, true);
    Shell.SetPresentationMode(MainPage, PresentationMode.Animated);
    }
}
else
{
    Shell.SetNavBarIsVisible(MainPage, false);
    Shell.SetNavBarHasShadow(MainPage, false);
    Shell.SetPresentationMode(MainPage, PresentationMode.Animated);
}

=> on iOS, the display of the NavigationBar is well done, but there is remaning gap before the header when the NavigationBar is hidden again. On Android, the rendering is satisfactory.

Here is the rendering on iOS.

It seems it's not possible de create a Custom NavigationPage for the main page of a Xamarin.Forms.Shell app. So is there a way to achieve the expected behavior?

Gold.strike
  • 1,269
  • 13
  • 47

0 Answers0