1
votes

I am developing an application in Xamarin Forms 4.8 version with both side menu(Flyout) and bottom Tabbar using Shell feature. My sidemenu has 4 items and the bottom Tabbar has 5 items. Both are having different items. The bottom Tabbar with such 5 items are always needs to be present around my application. When I click on any item inside the menu, the bottom Tabbar items are replaced with side menu items. I don't know why.

My AppShell.xaml page is shown below,

<Shell xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:local="clr-namespace:MyApp.Views"
        xmlns:localHome="clr-namespace:MyApp.Views.Home"
        xmlns:localOnlineStore="clr-namespace:MyApp.Views.OnlineStores"
        xmlns:localBooks="clr-namespace:MyApp.Views.BookList"
        xmlns:localUniforms="clr-namespace:MyApp.Views.Uniforms"
        xmlns:localUser="clr-namespace:MyApp.Views.User"
        xmlns:localMyAccount="clr-namespace:MyApp.Views.MyAccount"
        xmlns:localCart="clr-namespace:MyApp.Views.Cart"
        xmlns:flyouthead="clr-namespace:MyApp"
        xmlns:controls="clr-namespace:MyApp.Renderer;assembly=MyApp"
        Title="MyApp"
        x:Class="MyApp.AppShell"   
        FlyoutBehavior="Flyout"
        FlyoutHeaderBehavior="Fixed"
        FlyoutBackgroundColor="#011948">           
    
        <Shell.Resources>
            <ResourceDictionary>
                <Color x:Key="NavigationPrimary">#011948</Color>
                ...
                ...
            </ResourceDictionary>
         </Shell.Resources>    
    
         <Shell.FlyoutHeader> ... </Shell.FlyoutHeader> 
         <Shell.ItemTemplate> ... </Shell.ItemTemplate>
         <Shell.MenuItemTemplate> ... </Shell.MenuItemTemplate>
    
    
        <TabBar>
           <Tab Title="Home"
                Icon="ic_home">
                <ShellContent Route="HomePage" Shell.TabBarBackgroundColor="{StaticResource NavigationPrimary}" ContentTemplate="{DataTemplate localHome:HomePage}" />
           </Tab>
           <Tab Title="Books"
                Icon="ic_book">
                <ShellContent Route="ItemsPage" ContentTemplate="{DataTemplate local:ItemsPage}" />
            </Tab>
            <Tab Title="Cart"
                Icon="ic_cart">
                <ShellContent Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
            </Tab>
            <Tab Title="Uniforms"
                Icon="ic_uniform">
                <ShellContent Route="UniformsPage" ContentTemplate="{DataTemplate localUniforms:UniformsPage}" />
            </Tab>
            <Tab Title="Profile"
                Icon="ic_profile">
                <ShellContent Route="MyProfilePage" ContentTemplate="{DataTemplate localMyAccount:MyProfilePage}" />
             </Tab>
      </TabBar>    
    
    
      <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">         
          <ShellContent Title="Online Store" Icon="ic_online_store" ContentTemplate="{DataTemplate localOnlineStore:OnlineStorePage}" />
          <ShellContent Title="About Us" Icon="ic_about_us" ContentTemplate="{DataTemplate localHome:AboutUsPage}" />
          <ShellContent Title="Contact Us" Icon="ic_contact_us" ContentTemplate="{DataTemplate localHome:ContactUsPage}" />
          <ShellContent Title="Sign In" Icon="ic_login" Route="LoginPage" ContentTemplate="{DataTemplate localUser:LoginPage}" />
       </FlyoutItem>    
    
 </Shell>

When I run in Android Emulator, my bottom tabbar looks like in the image below

Bottom Tabbar

and side menu in Flyout as below

Side Menu in Flyout

When I click on items inside the menu, the page is rendered as follows

Side menu overrides bottom tabbar

Here, the bottom Tabbar items are replaced with side menu items.

2

2 Answers

1
votes

You can define your tabs depending on what you put in your AppShell.xaml, while for the flyout you can overwrite it by setting your custom content/view (flyout items won't follow your AppShell.xaml), either by setting the bindable property Shell.FlyoutContent with a direct content or Shell.FlyoutContentTemplate with a DataTemplate instead. This way you will have different items between your tabs and flyout.

<Shell X:Name="shell" ..>
...
<Shell.FlyoutContent>
    <CollectionView BindingContext="{x:Reference shell}"
                     ItemsSource="{Binding FlyoutItems}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Label Text="{Binding Title}"
                       TextColor="White"
                       FontSize="Large" />
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</Shell.FlyoutContent>

Note

This property is available starting from Xamarin.Forms 5.0.0.2012

Related question

Dynamically create list of FlyoutItem in Shell?

1
votes

If you want to display one or more items in the flyout and bottom, you can use a FlyoutItem.

 <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
    <ShellContent Title="About" Icon="tab_about.png" Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
    <ShellContent Title="Browse" Icon="tab_feed.png" ContentTemplate="{DataTemplate local:ItemsPage}" />
</FlyoutItem>

enter image description here

If you just want to display items in the bottom, don't want to display items in the flyout, you just need to use TabBar to do this,

<TabBar>
    <Tab Title="About" Icon="tab_about.png">
        <ShellContent>
            <views:AboutPage />
        </ShellContent>
    </Tab>
    <Tab Title="Browse" Icon="tab_feed.png">
        <ShellContent>
            <views:ItemsPage />
        </ShellContent>
    </Tab>
</TabBar>

enter image description here

Just choose FlayoutItem or TabBar, don't need to use both of them.

For more detailed info about Shell, please take a look:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/create

Update:

 <MenuItem
    Clicked="OnMenuItemClicked"
    StyleClass="MenuItemLayoutStyle"
    Text="Logout" />


 private async void OnMenuItemClicked(object sender, EventArgs e)
    {
        await Shell.Current.GoToAsync("//LoginPage");
    }