Xamarin Shell FlyoutItem's tab click event - xamarin.forms

Im using Xamarin forms, and on my AppShell, i want 2 tabs, i want to have a clicked event on one of the tabs, so that when clicked on it doesnt load another page but actually execute a function (show an Rg.Popup on top of the current page).
So i need a way to capture the tab clicked event or maybe a command or anything.
here is what i have:
<FlyoutItem FlyoutDisplayOptions="AsSingleItem" IsVisible="False">
<Tab Title="001">
<ShellContent ContentTemplate="{DataTemplate local:HomePage}"></ShellContent>
</Tab>
<Tab Title="002">
<ShellContent ContentTemplate="{DataTemplate local:ProfilePage}"></ShellContent>
</Tab>
</FlyoutItem>

1 year too late but hope this helps. you can use menuItem which will display ontop of flyoutitem
<MenuItem Text="item" StyleClass="MenuItemLayoutStyle" Clicked="OnClickMethod">
</MenuItem>

Create a class inherit from TabBar and override the method OnPropertyChanged:
public class MyTab : TabBar
{
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (propertyName == "CurrentItem")
{
int index = this.Items.IndexOf(this.CurrentItem);
if(index == 0)
{
}
if(index == 1)
{
}
}
}
}
Use it in Xaml
<local:MyTab>
<Tab Title="Browse" Icon="tab_feed.png" x:Name="tab1">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="About" Icon="tab_about.png">
<ShellContent ContentTemplate="{DataTemplate local:AboutPage}" />
</Tab>
</local:MyTab>
Another way I thought is that you can execute the function in the page's OnAppearing method.

Related

TabbedPage selectedItem doesn't change when change tab programmatically to tab in "More"

I am working on a Xamarin Forms app with a TabbedPage which has 6 tabs.
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:tabs="clr-namespace:TabbedPageIssue"
xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
android:TabbedPage.IsSwipePagingEnabled="False"
android:TabbedPage.BarSelectedItemColor="#F79320"
android:TabbedPage.BarItemColor="#B1B2B3"
x:Class="TabbedPageIssue.MainPage">
<tabs:Tab1 Title="Tab1"/>
<tabs:Tab2 Title="Tab2"/>
<tabs:Tab3 Title="Tab3"/>
<tabs:Tab4 Title="Tab4"/>
<tabs:Tab5 Title="Tab5"/>
<tabs:Tab6 Title="Tab6"/>
</TabbedPage>
In my app, I want to have a button to direct the app to a tab "inbox" in the "More" part with this code:
private void Button_Clicked(object sender, EventArgs e)
{
var mainPage = this.Parent as TabbedPage;
mainPage.CurrentPage = mainPage.Children[4];
}
When i click the button to change tab, the View changes but the "More" tab is not selected, and if i click on tab1, the view of tab 5 doesn't disappear.
This seems to be a bug of TabbedPage. Everybody has any idea to fix this problem?
I was able to reproduce this issue. For workaround, you could use Shell tabs instead. For the latest version of VS, when you create a Tabbed template, it is using Shell. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/
Xaml:
<?xml version="1.0" encoding="UTF-8"?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App3.Views"
Title="App3"
x:Class="App3.AppShell">
<TabBar>
<ShellContent Title="Tab1" ContentTemplate="{DataTemplate local:Page1}" />
<ShellContent Title="Tab2" ContentTemplate="{DataTemplate local:Page2 }" />
<ShellContent Title="Tab3" ContentTemplate="{DataTemplate local:Page3 }" />
<ShellContent Title="Tab4" ContentTemplate="{DataTemplate local:Page4}" />
<ShellContent Title="Tab5" Route="page5" ContentTemplate="{DataTemplate local:Page5 }" />
<ShellContent Title="Tab6" ContentTemplate="{DataTemplate local:Page6 }" />
</TabBar>
</Shell>
Navigating from Page1 to Page5:
async void Button_Clicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//page5");//page5 is the route i set in xaml
}
OutPut:

Login user and navigation back to home page Shell

I am using Shell in my Xamarin forms application,
I have an issue when My user registers successfully he is redirected to Homepage, however there is no Tab Menu on the bottom while if I redirect him to AppShell the page is blank. Do you have any suggestions?
My redirection
await App.Current.MainPage.Navigation.PushModalAsync(new AppShell());
My AppShell
<TabBar >
<Tab x:Name="HomePage" Icon="home.png" Title="{x:Static resources:AppResources.LabelHome}" >
<ShellContent ContentTemplate="{DataTemplate views:HomePage}"/>
</Tab>
<Tab x:Name="Categories" Icon="collections.png " Title="{x:Static resources:AppResources.LabelCategory}">
<ShellContent ContentTemplate="{DataTemplate views:CategoriesPage}"/>
</Tab>
<Tab x:Name="Add" Icon="add.png" Title="{x:Static resources:AppResources.LabelAddingPage}">
<ShellContent ContentTemplate="{DataTemplate views:AddingPage}"/>
</Tab>
<Tab x:Name="Inbox" Icon="mail.png" Title="{x:Static resources:AppResources.LabelInbox}" >
<ShellContent ContentTemplate="{DataTemplate views:InboxPage}"/>
</Tab>
<Tab x:Name="Profile" Icon="userg.png" Title="{x:Static resources:AppResources.LabelProfil}">
<ShellContent ContentTemplate="{DataTemplate views:UserProfilePage}"/>
</Tab>
</TabBar>
And my app
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
from your redirection await App.Current.MainPage.Navigation.PushModalAsync(new AppShell()); , i think you have another Shell Application just for your login.
try await App.Current.MainPage = new AppShell(); to initialize the Shell as your mainPage.
hope this helps ;)
You will have to make the following changes :-
Your redirection should be :-
await Shell.Current.GoToAsync("//main");
Your App Shell should have this :-
<TabBar Route="main">
...
</TabBar>
Hopefully this helps.

Setting a default page in the Xamarin.Forms shell menu

Using the Xaminals example, I'm trying to set the default startup page. Here's the relevant code from the xaml:
<FlyoutItem Route="animals" x:Name="shellAnimals"
Title="Animals"
FlyoutDisplayOptions="AsMultipleItems">
<Tab Title="Domestic" x:Name="shellDomestic"
Route="domestic"
Icon="paw.png">
<ShellContent Route="cats" x:Name="shellCats"
Style="{StaticResource DomesticShell}"
Title="Cats"
Icon="cat.png"
ContentTemplate="{DataTemplate views:CatsPage}" />
<ShellContent Route="dogs" x:Name="shellDogs"
Style="{StaticResource DomesticShell}"
Title="Dogs"
Icon="dog.png"
ContentTemplate="{DataTemplate views:DogsPage}" />
</Tab>
<ShellContent Route="monkeys" x:Name="shellMonkeys"
Style="{StaticResource MonkeysShell}"
Title="Monkeys"
Icon="monkey.png"
ContentTemplate="{DataTemplate views:MonkeysPage}" />
<ShellContent Route="elephants" x:Name="shellElephants"
Style="{StaticResource ElephantsShell}"
Title="Elephants"
Icon="elephant.png"
ContentTemplate="{DataTemplate views:ElephantsPage}" />
<ShellContent Route="bears" x:Name="shellBears"
Style="{StaticResource BearsShell}"
Title="Bears"
Icon="bear.png"
ContentTemplate="{DataTemplate views:BearsPage}" />
</FlyoutItem>
In the code behind I can successfully set the default startup page.
For example, the dogs page:
shellAnimals.CurrentItem.CurrentItem = shellDogs;
But on the bears page:
// This works, but I don't like the indexing. Will give trouble on dynamic menu's
shellAnimals.CurrentItem = shellAnimals.Items[3];
// This doesn't work, but I don't understand why. It gives a null reference exception in the Xamarin Shell code, on the PushAsync
shellAnimals.CurrentItem = shellBears;
// This shows the bears page at startup, but when I click on an item in the listview, I also get a null reference error
CurrentItem = shellBears;
Why doesn't the second/third snippet work?
How can I set the default page to the bears page without using the indexer?
Can't find anything on this subject except Set default tab on Xamarin Forms Shell but that doesn't answer it.
You can set the current page in XAML, as per the documentation Set-the-current-flyoutitem. This would then mean your Shell tag, you would add `CurrentItem="{x:Reference shellBears}"1.
Additionally, I see in your second code behind snippet you are missing another .CurrentItem step when compared to the dogs example that you say works. Can you try shellAnimals.CurrentItem.CurrentItem = shellBears;
Why doesn't the second/third snippet work?
The second snippet:
shellAnimals.CurrentItem is a variable which type is ShellSection while your shellBears is kind of ShellContent.
The third snippet:
When you use CurrentItem directly in the shell class, that is Shell.CurrentItem and it's a ShellItem.
How can I set the default page to the bears page without using the
indexer?
In your Xaml:
<ShellSection x:Name="shellBears" Title="Bears"
Icon="bear.png">
<ShellContent Route="bears"
Style="{StaticResource BearsShell}"
ContentTemplate="{DataTemplate views:BearsPage}" />
</ShellSection >
And in code behind:
shellAnimals.CurrentItem = shellBears;

How do i navigate to a shell tabbed page from a parent shell tabbed page

i have a parent shell tabbed page. i want to be able to navigate from one of the contentPage of this parent page to another shell tabbed page.
Navigation can be performed by specifying a valid absolute URI as an argument to the GoToAsync method: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/navigation#perform-navigation
On OnItemSelected method, invoke the code below.
await (App.Current.MainPage as Xamarin.Forms.Shell).GoToAsync("//tabbar/tab/about", true);
AppShell.xaml: Set the route.
<TabBar Route="tabbar">
<Tab Title="Browse" Icon="tab_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="About" Icon="tab_about.png" Route="tab">
<ShellContent Route="about" ContentTemplate="{DataTemplate local:AboutPage}" />
</Tab>
</TabBar>

Set default tab on Xamarin Forms Shell

How to set the default selected Tab inside the tab bar on Xamarin forms shell?
<?xml version="1.0" encoding="UTF-8"?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TestApp.NavigationShell"
xmlns:pages="clr-namespace:TestApp.Pages"
xmlns:pageModels="clr-namespace:TestApp.PageModels">
<TabBar Route="testapp">
<Tab Title="Saved" Icon="tabDashboard" Route="dashboard"><ShellContent ContentTemplate="{DataTemplate pages:DashBoardPage}"/></Tab>
<Tab Title="Calendar" Icon="tabCalendar" Route="calendar"><ShellContent ContentTemplate="{DataTemplate pages:CalendarPage}"/></Tab>
<Tab Title="Search" Icon="tabSearch" Route="search"><ShellContent ContentTemplate="{DataTemplate pages:SearchPage}"/></Tab>
<Tab Title="Support" Icon="tabSupport" Route="support"><ShellContent ContentTemplate="{DataTemplate pages:SupportPage}"/></Tab>
<Tab Title="Profile" Icon="tabAccount" Route="account"><ShellContent ContentTemplate="{DataTemplate pages:AccountPage}"/></Tab>
</TabBar>
According to the Xamarin Forms documentation, the first Shell Content will be the default content on the screen. However; I'm trying to set the "Search" page as the default tab rather than "Saved".
I tried to set Tab Index - no luck
I also tried to call routing on onAppearing method of Shell but seems like Shell's on appearing method never gets fired.
I tried to navigate to Search as well:
public partial class NavigationShell : Shell
{
public NavigationShell()
{
InitializeComponent();
//Shell.Current.TabIndex = 2;
}
protected override async void OnAppearing()
{
base.OnAppearing();
//await Shell.Current.GoToAsync("testapp/search");
}
}
What could be the best solution that when app opens need to set the default tab?
Thank you.
Here, how I fix it by using the Name field attribute.
I assigned the name to the TabBar and the tab which I want to assign in the first place.
AppShell.xaml
<TabBar x:Name="main_tab_bar" Route="main">
<Tab Title="History">
<Tab.Icon>
<FontImageSource FontFamily="MaterialIconsRegular" Glyph="{x:Static Emojis:MaterialRegFont.List}"/>
</Tab.Icon>
<ShellContent ContentTemplate="{DataTemplate Views:CallLogPage}" />
</Tab>
<Tab x:Name="main_tab_bar_dial" Title="Dial" >
<Tab.Icon>
<FontImageSource FontFamily="MaterialIconsRegular" Glyph="{x:Static Emojis:MaterialRegFont.Dialpad}"/>
</Tab.Icon>
<ShellContent ContentTemplate="{DataTemplate Views:MainDialerPage}" />
</Tab>
<Tab Title="Settings">
<Tab.Icon>
<FontImageSource FontFamily="MaterialIconsRegular" Glyph="{x:Static Emojis:MaterialRegFont.Settings}"/>
</Tab.Icon>
<ShellContent ContentTemplate="{DataTemplate Views:MainSettingsPage}" />
</Tab>
</TabBar>
AppShell.cs
public AppShell() {
InitializeComponent();
Init();
}
private void Init() {
main_tab_bar.CurrentItem = main_tab_bar_dial;
}
Nevermind, I think I found a solution.
public Page Init(Shell root)
{
CurrentShell = root;
root.CurrentItem.CurrentItem = root.CurrentItem.Items[2];
return CurrentShell;
}
Becase my shell have ONLY one root item which is tabbar itself. I just get the search tab and assigned to the first child's current item and it worked.
Please post your answers if you found another way around.
Thank you.
On the constructor of your Shell class you can set the CurrentItem
in my case I have an <ShellItem> with some <tab>
public PrivateShell()
{
InitializeComponent();
this.CurrentItem.CurrentItem = homeTab; //tab defined by x:Name on XAML
}
As far as I could check it does not pre-render the first shellcontent in case you're using ContentTemplate pattern

Resources