Search code examples
xamarin.formsmaster-detailtabbedpage

Xamarin MVVM Show master page sliding from the left, when pressing tabbed page tab item


I am trying to achieve the effect, cross-platform(ios, android and uwp), as shown in the image below:

enter image description here

Clicking "More" normally would open a page, as normal behaviour for a tab bar item. Not sure how to override that behaviour and reveal the sliding master page instead. To the left of the "More" tab bar item, theres another tab bar item, when clicked it refreshes the data on (or reloads) the MainPage.

SettingsPage.xaml (master page, the sliding settings page)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyProject.Classes"
             xmlns:views="clr-namespace:MyProject.Views"
             x:Class="MyProject.Views.SettingsMasterPage"
             IconImageSource="menu.png"
             Padding="0,40,0,0"
             Title="Menu">


    <StackLayout>
        <ListView x:Name="listView" x:FieldModifier="public">
            <ListView.ItemsSource>
                <x:Array Type="{x:Type local:MasterPageItem}">
                               
                    <local:MasterPageItem Title="Settings Link 1" />
                    <local:MasterPageItem Title="Settings Link 2"  />
                    <local:MasterPageItem Title="Settings Link 3"  />   
                 
                </x:Array>
            </ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="5,10">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="30"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Image Source="{Binding IconSource}" />
                            <Label Grid.Column="1" Text="{Binding Title}" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>

</ContentPage>

MyTabbedPage.xaml

 <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
                 xmlns:views="clr-namespace:MyProject.Views;assembly=MyProject"
                 x:Class="Xamarin.Sigma01.Views.LoggerDetectionTabbedPage"
                 android:TabbedPage.ToolbarPlacement="Bottom"
                 BarBackgroundColor="White"
                 SelectedTabColor="Black"
                 BarTextColor="Black">
        <TabbedPage.Children>
            <views:MainPage IconImageSource="tab_icon_mainpage.png" />
            <!-- second link should be the sandwhich button that brings up the settings page -->
        </TabbedPage.Children>   
    </TabbedPage>

MainPage.xaml (the main page, navigated to by the left TabBar link icon, to the left of the sandwhich icon with title "More")

<ContentPage.Content>
        <StackLayout>
            <Label Text="Welcome to the Main page!"
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="CenterAndExpand" />      

        </StackLayout>
    </ContentPage.Content>

Solution

  • An alternative, following the idea from @Shaw, but without Shell is to use the good old MasterDetail Page (which supports UWP) and add two buttons at the bottom to provide the "More" and "Refresh" functionality.

    If this sounds like a good option for you, keep reading:

    Add a Master-Detail Page to your Solution

    On Visual Studio 2019 adding a Master-Detail to your solution is pretty straight forward. You only need to right click the Xamarin.Forms Project in the Solution Explorer and go to Add -> New Item (or simply use the shortcut Ctrl+Shift+A):

    enter image description here

    in the window that appears, select Master-Detail Page, give it a cool name (MasterDetailPage1 in this example!) and click Add:

    enter image description here

    By doing this you successfully have added a Master Detail to your solution. Now just go to App and set MainPage to it as follows:

    MainPage = new MasterDetailPage1();
    

    Add the bottom buttons

    Now we want two buttons at the bottom of our Detail page. This is simply done by adding a stack of two buttons that locate at the end. Our newly added MasterDetailPage1Detail.xaml will then look like:

    <?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="MasterTabRefresh.MasterDetailPage1Detail"
                 Title="Detail">
      <StackLayout>
        <Label Text="This is a detail page. To get the 'triple' line icon on each platform add a icon to each platform and update the 'Master' page with an Icon that references it."
               Padding="10"/>
            <StackLayout Orientation="Horizontal"
                         VerticalOptions="EndAndExpand"
                         Spacing="0">
                <Button BackgroundColor="CornflowerBlue"
                        Text="Refresh"
                        TextColor="White"
                        CornerRadius="0"
                        HorizontalOptions="FillAndExpand"/>
                <Button BackgroundColor="CornflowerBlue"
                        Text="More"
                        TextColor="White"
                        CornerRadius="0"
                        HorizontalOptions="FillAndExpand"
                        Clicked="MoreClicked"/>
            </StackLayout>
      </StackLayout>
    </ContentPage>
    

    which should look like:

    enter image description here

    And in the code behind (MasterDetailPage1Detail.xaml.cs ) we add the "More" functionality:

    private void MoreClicked(object sender, EventArgs e)
    {
        ((MasterDetailPage)Application.Current.MainPage).IsPresented = !((MasterDetailPage)Application.Current.MainPage).IsPresented;
    }
    

    Add a nice X (close) button to your menu/master

    This could be achieved by adding a label with an "X" at the top right of the menu. Simply modify your MasterDetailPage1Master.xaml to look like (note Label at Column 2 Row 0!)

    <?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="MasterTabRefresh.MasterDetailPage1Master"
                 Title="Master">
      <StackLayout>
        <ListView x:Name="MenuItemsListView"
                  SeparatorVisibility="None"
                  HasUnevenRows="true"
                  ItemsSource="{Binding MenuItems}">
          <ListView.Header>
            <Grid BackgroundColor="#03A9F4">
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="30"/>
              </Grid.ColumnDefinitions>
              <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="80"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="10"/>
              </Grid.RowDefinitions>
                        <Label Grid.Column="2"
                       Grid.Row="0"
                       Text="X"
                       FontAttributes="Bold"
                       HorizontalTextAlignment="Center"
                       VerticalTextAlignment="Center">
                            <Label.GestureRecognizers>
                                <TapGestureRecognizer Tapped="X_Tapped"/>
                            </Label.GestureRecognizers>
                        </Label>
                <Label
                  Grid.Column="1"
                  Grid.Row="2"
                  Text="My wonderful App"
                  Style="{DynamicResource SubtitleStyle}"/>
            </Grid>
          </ListView.Header>
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
                  <Label VerticalOptions="FillAndExpand" 
                        VerticalTextAlignment="Center" 
                        Text="{Binding Title}" 
                        FontSize="24"/>
                </StackLayout>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>
      </StackLayout>
    </ContentPage>
    

    Which should look like this:

    enter image description here

    And then add the "Close" functionality to that "X" Label in the code behind (MasterDetailPage1Master.xaml):

    private void X_Tapped(object sender, EventArgs e)
    {
        ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
    }
    

    And that is it! This should get you going. Happy coding!