Giter Club home page Giter Club logo

sharpnado.tabs's Introduction

Sharpnado.Tabs for MAUI and Xamarin.Forms

Get it from NuGet:

Nuget

Nuget

Supported MAUI platforms Supported XF platforms
✔️ Android ✔️ Android
✔️ iOS ✔️ iOS
❓ Windows ✔️ UWP
❓ Mac
  • MAUI version
  • Fully customizable
  • Underlined tabs, bottom tabs, Segmented control, scrollable tabs
  • Vertical tabs
  • Lazy and Delayed views
  • Material tabs specs full implementation
  • SVG support thanks to GeometryIcon
  • Badge on tabs
  • Component oriented architecture
  • Layout your tabs and ViewSwitcher as you want
  • Shadows included in TabHost
  • Bindable
MAUI sample
Bottom bar tabs Fixed tabs
BottomTabItem UnderlinedTabItem
Segmented tabs Neumorphic tabs
TabType.Scrollable inherit from TabItem
Material top icon Material leading icon
IconOptions="TopIcon" IconOptions="LeadingIcon"
Scrollable tabs Custom tabs
TabType.Scrollable inherit from TabItem
BadgeView BadgeView (Chips)
Numbers, Indicator Chips with text
Vertical Tabs
Orientation="Vertical"

Sample app

For dotnet MAUI, you can just have a look at the MauiSample solution.

For Xamarin.Forms the tabs components are presented in the Silly! app in the following repository:

https://github.com/roubachof/Xamarin-Forms-Practices

Installation

MAUI

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseSharpnadoTabs(loggerEnable: false);

        return builder.Build();
    }
}

Xamarin.Forms

Because Tabs uses platform-specific effects like tinted images and tap feedback color, you must install the nuget package in all your targeted platforms projects (netstandard, ios, android, uwp).

  • In Core project in App.xaml.cs:

For the namespace xaml schema to work (remove duplicates xml namespace: see this xamarin doc), you need to call tabs and shadows initializers from the App.xaml.cs file like this:

public App()
{
    InitializeComponent();

    Sharpnado.Tabs.Initializer.Initialize(false, false);
    Sharpnado.Shades.Initializer.Initialize(loggerEnable: false);
    ...
}
  • Mandatory initializations on iOS:
    Xamarin.Forms.Forms.Init();
    Sharpnado.Tabs.iOS.Preserver.Preserve();
  • Mandatory initializations on UWP:
    var rendererAssemblies = new[] 
    { 
        typeof(UWPShadowsRenderer).GetTypeInfo().Assembly,
        typeof(UwpTintableImageEffect).GetTypeInfo().Assembly,
    };
    Xamarin.Forms.Forms.Init(e, rendererAssemblies);

Version 3.0 (MAUI only)

Attached Properties

You can use Commands.Tap to add a tap gesture to any view.

The TouchEffect.Color property will set a native touch feedback with the desired color.

DelayedView

You probably know the LazyView by now, the DelayedView is an evolution of it enabling full control of your UI building times.

Using a DelayedView will reduce application startup time by deferring the UI building of your components by some milliseconds (the value can be configured).

delayedView.mp4

All you have is wrap your view in a DelayedView inside your ViewSwitcher, or even anywhere in your app.

<tabs:ViewSwitcher x:Name="Switcher"
                           Grid.RowSpan="3"
                           Margin="0"
                           Animate="True"
                           SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
    <tabs:DelayedView x:TypeArguments="views:TabM"
                        AccentColor="{StaticResource Primary}"
                        Animate="True"
                        BindingContext="{Binding HomePageViewModel}"
                        UseActivityIndicator="True" />
    <tabs:DelayedView x:TypeArguments="views:TabA"
                        AccentColor="{StaticResource Primary}"
                        Animate="True"
                        UseActivityIndicator="True" />
    <tabs:DelayedView x:TypeArguments="views:TabU"
                        AccentColor="{StaticResource Primary}"
                        Animate="True"
                        UseActivityIndicator="True" />
    <tabs:LazyView x:TypeArguments="views:TabI" Animate="True" />
</tabs:ViewSwitcher>

It can totally work outside of the Tabs context.

Shadows (Xamarin.Forms only)

The TabHostView inherits directly from Shadows. It means you can add as many shades as you like to your tab bar. It behaves exactly the same as the Shadows component.

Since shadows are now handled by Shades, the old shadow renderers have been removed. The ShadowType property is gone.

For more information about custom shades, visit the Sharpnado.Shadows repo.

UnderlinedTabItem with ViewSwitcher

Let's consider this view:

And let's have a look at its code:

<Grid Padding="{StaticResource StandardThickness}"
      ColumnSpacing="0"
      RowSpacing="0">
    <Grid.RowDefinitions>
        <RowDefinition Height="200" />
        <RowDefinition Height="40" />
        <RowDefinition Height="30" />
        <RowDefinition Height="30" />
        <RowDefinition Height="50" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <!-- first 4 rows then... -->

    <tabs:TabHostView x:Name="TabHost"
                      Grid.Row="4"
                      Margin="-16,0"
                      BackgroundColor="#272727"
                      SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
        <tabs:TabHostView.Tabs>
            <tabs:UnderlinedTabItem Style="{StaticResource TabStyle}" Label="{loc:Translate Tabs_Quote}" />
            <tabs:UnderlinedTabItem Style="{StaticResource TabStyle}" Label="{loc:Translate Tabs_Filmography}" />
            <tabs:UnderlinedTabItem Style="{StaticResource TabStyle}" Label="{loc:Translate Tabs_Meme}" />
        </tabs:TabHostView.Tabs>
    </tabs:TabHostView>

    <ScrollView Grid.Row="5">
        <tabs:ViewSwitcher x:Name="Switcher"
                           Animate="True"
                           SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
            <details:Quote Animate="True" BindingContext="{Binding Quote}" />
            <details:Filmo Animate="True" BindingContext="{Binding Filmo}" />
            <details:Meme Animate="True" BindingContext="{Binding Meme}" />
        </tabs:ViewSwitcher>
    </ScrollView>
</Grid>

The TabHostView and the ViewSwitcher are really two independent components, and you can place them anywhere. They don't need to be next to each other (even if it would be weird I must admit).

Since they don't know each other, you just need to link them through their SelectedIndex property. You will bind the ViewSwitcher to your view model, and the TabHostView to the ViewSwitcher's SelectedIndex property.

You can also see a mysterious Animate property. It just adds a nice appearing effect. It's really just a little bonus.

UnderlineAllTab

UnderlinedTabItem.UnderlineAllTab=(true|false)

You can decide whether or not you want the underline to take the whole tab width, or just the text width.

View model

    public TaskLoaderNotifier<SillyDudeVmo> SillyDudeLoader { get; }

    public QuoteVmo Quote { get; private set; }

    public FilmoVmo Filmo { get; private set; }

    public MemeVmo Meme { get; private set; }

    public int SelectedViewModelIndex
    {
        get => _selectedViewModelIndex;
        set => SetAndRaise(ref _selectedViewModelIndex, value);
    }

    public override void Load(object parameter)
    {
        SillyDudeLoader.Load(() => LoadSillyDude((int)parameter));
    }

    private async Task<SillyDudeVmo> LoadSillyDude(int id)
    {
        var dude = await _dudeService.GetSilly(id);

        Quote = new QuoteVmo(
            dude.SourceUrl,
            dude.Description,
            new TapCommand(url => Device.OpenUri(new Uri((string)url))));
        Filmo = new FilmoVmo(dude.FilmoMarkdown);
        Meme = new MemeVmo(dude.MemeUrl);
        RaisePropertyChanged(nameof(Quote));
        RaisePropertyChanged(nameof(Filmo));
        RaisePropertyChanged(nameof(Meme));

        return new SillyDudeVmo(dude, null);
    }

Well I won't go into details it's pretty obvious. If you want to know more about the mystery TaskLoaderNotifier, please read this post (https://www.sharpnado.com/taskloaderview-2-0-lets-burn-isbusy-true/).

Styling

The tab style is defined in the content page resources, but we could put it the App.xaml since most of the time we will have one type of top tabs (well it's up to your crazy designer really :)

<ContentPage.Resources>
    <ResourceDictionary>
        <Style x:Key="TabStyle" TargetType="tabs:UnderlinedTabItem">
            <Setter Property="SelectedTabColor" Value="{StaticResource AccentColor}" />
            <Setter Property="FontFamily" Value="{StaticResource FontSemiBold}" />
            <Setter Property="LabelSize" Value="14" />
            <Setter Property="UnselectedLabelColor" Value="White" />
        </Style>
    </ResourceDictionary>
</ContentPage.Resources>

BottomTabItem with Neumorphism and corner radius

And let's have a look at its xaml:

<Grid ColumnSpacing="0" RowSpacing="0"
      BackgroundColor="#F0F0F3">
    <Grid.RowDefinitions>
        <RowDefinition Height="{StaticResource ToolbarHeight}" />
        <RowDefinition Height="*" />
        <RowDefinition Height="95" />
    </Grid.RowDefinitions>

    <tb:Toolbar Title="Silly App!"
                BackgroundColor="{StaticResource Accent}"
                ForegroundColor="White"/>

    <tabs:ViewSwitcher x:Name="Switcher"
                       Grid.Row="1"
                       Animate="False"
                       SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
        <customViews:LazyView x:TypeArguments="tabsLayout:HomeView" BindingContext="{Binding HomePageViewModel}" />
        <customViews:LazyView x:TypeArguments="tabsLayout:ListView" BindingContext="{Binding ListPageViewModel}" />
        <customViews:LazyView x:TypeArguments="tabsLayout:GridView" BindingContext="{Binding GridPageViewModel}" />
    </tabs:ViewSwitcher>

    <tabs:TabHostView Grid.Row="2"
                      HorizontalOptions="Center"
                      VerticalOptions="Start"
                      HeightRequest="60"
                      WidthRequest="280"
                      TabType="Fixed"
                      IsSegmented="True"
                      CornerRadius="30"
                      Margin="15"
                      BackgroundColor="#F0F0F3"  
                      Shades="{sh:NeumorphismShades}"
                      SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
        <tabs:TabHostView.Tabs>
            <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                                IconImageSource="house_96"
                                Label="{localization:Translate Tabs_Home}" />
            <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                                IconImageSource="list_96"
                                Label="{localization:Translate Tabs_List}" />
            <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                                IconImageSource="grid_view_96"
                                Label="{localization:Translate Tabs_Grid}" />
        </tabs:TabHostView.Tabs>
    </tabs:TabHostView>

</Grid>

Warning: the CornerRadius property will only be effective if the IsSegmented property is true.

IsTextVisible

BottomTabItem.IsTextVisible=(true|false)

If you like your bottom bar items without text:

SelectedTabColor and SelectedTabTextColor

You can set a color for the selected tab via SelectedTabColor. If you want to have a different color for the text, you can specify SelectedTabTextColor.

Styling

<ContentPage.Resources>
    <ResourceDictionary>
        <Style x:Key="BottomTabStyle" TargetType="tabs:BottomTabItem">
            <Setter Property="SelectedTabColor" Value="{StaticResource Accent}" />
            <Setter Property="UnselectedLabelColor" Value="Gray" />
            <Setter Property="UnselectedIconColor" Value="LightGray" />
            <Setter Property="FontFamily" Value="{StaticResource FontLight}" />
            <Setter Property="LabelSize" Value="14" />
            <Setter Property="IconSize" Value="28" />
            <Setter Property="IsTextVisible" Value="False" />
        </Style>
    </ResourceDictionary>
</ContentPage.Resources>

Scrollable tabs

A new Property TabType was added to the TabHostView:

public TabType TabType

public enum TabType
{
    Fixed = 0,
    Scrollable,
}

Version 2.2: Material tabs

Contributor: @mkanyo (Miklos Kanyo)

Since version 2.2, a new type of tab has been introduced: the MaterialUnderlinedTabItem. It's a full implementation of the material tabs specifications:

https://material.io/components/tabs

material tabs

IconOptions values:

  1. TopIcon
  2. IconOnly
  3. LeadingIcon
  4. TextOnly

You can also set precisely the gap between the icon and the text thanks to the IconTextSpacing.

Instead of using a classic Image you can also set a svg Geometry (SVG image) icon thanks to the GeometryIcon property.

Cool Hack: you can use MaterialUnderlinedTabItem (and then use a SVG image) as a bottom bar item, just specify UnderlineHeight = 0.

If you chose to go down this road you can also set the following properties:

  • public bool Fill
  • public double StrokeThickness
  • public double IconTextSpacing
<tabs:TabHostView x:Name="TabHost"
                  Grid.Row="4"
                  Style="{DynamicResource DynamicBottomShadow}"
                  Margin="-16,0"
                  BackgroundColor="{DynamicResource Elevation4dpColor}"
                  ShowScrollbar="False"
                  TabType="Scrollable"
                  SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
    <tabs:TabHostView.Tabs>
        <tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
                                        IconImageSource="list_96.png"
                                        IconOptions="TopIcon"
                                        IconSize="24"
                                        IconTextSpacing="0"
                                        Label="{localization:Translate Tabs_Quote}"
                                        UnderlineHeight="2" />
        <tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
                                        IconImageSource="theme_96.png"
                                        IconOptions="IconOnly"
                                        IconSize="24"
                                        IconTextSpacing="0"
                                        Label="FILMO" />
        <tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
                                        IconImageSource="grid_view_96.png"
                                        IconOptions="LeadingIcon"
                                        IconSize="24"
                                        IconTextSpacing="0"
                                        Label="{localization:Translate Tabs_Meme}" />
        <tabs:MaterialUnderlinedTabItem Style="{StaticResource ScrollableTabStyle}"
                                        Padding="10,0"
                                        IconImageSource="house_96.png"
                                        IconOptions="TextOnly"
                                        IconSize="24"
                                        IconTextSpacing="0"
                                        Label="NONSENSE" />
      </tabs:TabHostView.Tabs>
</tabs:TabHostView> 

Version 2.1: Vertical tabs

Contributor: @nor0x (Joachim Leonfellner)

Since version 2.1, you can change the orientation of the tabs to achieve vertical tabs. It could be pretty convenient for landscape or tablet layout.

<sho:TabHostView x:Name="TabHostLogo"
    Grid.Row="3"
    WidthRequest="200"
    HeightRequest="60"
    Margin="15"
    Padding="20,0"
    HorizontalOptions="Center"
    VerticalOptions="Start"
    BackgroundColor="{DynamicResource DynamicBottomBarBackground}"
    CornerRadius="30"
    IsSegmented="True"
    Orientation="Horizontal"
    Shades="{DynamicResource DynamicBottomTabsShadow}"
    TabType="Fixed">

You can find in the silly app (https://github.com/roubachof/Xamarin-Forms-Practices/blob/master/SillyCompany.Mobile.Practices/Presentation/Views/TabsLayout/SillyBottomTabsPage.xaml.cs) an example of dynamically adapting tabs orientation while switching from portrait to landscape:

vertical tabs gif

Segmented control

Since version 1.7 we can mimic iOS segmented control style.

A new tab item has been created: the SegmentedTabItem. Use it with IsSegmented, SegmentedOutlineColor, and SegmentedHasSeparator, and you will have the classic iOS style.

<tabs:TabHostView x:Name="TabHost"
                    Grid.Row="4"
                    HeightRequest="40"
                    Margin="20,15,20,0"
                    VerticalOptions="Center"
                    BackgroundColor="#F0F0F3"
                    Shades="{sh:SingleShade Offset='0,8',
                                            BlurRadius=10,
                                            Color={StaticResource Accent}
                                            Opacity=0.2}"
                    CornerRadius="20"
                    IsSegmented="True"
                    SegmentedHasSeparator="True"
                    SegmentedOutlineColor="{StaticResource Accent}"
                    TabType="Fixed"
                    SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
    <tabs:TabHostView.Tabs>
        <tabs:SegmentedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Quote" />
        <tabs:SegmentedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Movies" />
        <tabs:SegmentedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Meme" />
    </tabs:TabHostView.Tabs>
</tabs:TabHostView>
<Style x:Key="SegmentedTabStyle" TargetType="tabs:SegmentedTabItem">
    <Setter Property="SelectedTabColor" Value="{StaticResource Accent}" />
    <Setter Property="FontFamily" Value="{StaticResource FontSemiBold}" />
    <Setter Property="LabelSize" Value="14" />
    <Setter Property="SelectedLabelColor" Value="#F0F0F3" />
    <Setter Property="UnselectedLabelColor" Value="Gray" />
</Style>

Properties

IsSegmented Enables segmentation thus clipping for the TabHostView.
CornerRadius Sets the corner radius for the view.
Only works if IsSegmented is set to true.
SegmentedOutlineColor Sets the corner radius for the view.
Only works if IsSegmented is set to true.
SegmentedHasSeparator Sets a separator between each tab item, the color is given by the SegmentedOutlineColor property.

TabButton

Sometimes your designer wants to spice-up a bit the bottom bar tabs by adding a button like a take a picture button. The issue is that the semantic differs from the others tabs since you will make an action instead of swaping views.

So I created the TabButton for scenarios like this.

It has a load of properties to fulfill your designer wildest dreams:

public string IconImageSource

public ICommand TapCommand

public int CornerRadius

public Color ButtonBackgroundColor

public Thickness ButtonPadding

public double ButtonWidthRequest

public double ButtonHeightRequest

public double ButtonCircleSize

For the circle button the issue is that most of the time, you want it to be bigger and to come out a bit of the bar. It needs a little trick to make it works. For example this is the source of the above circle button:

<tabs:TabHostView x:Name="TabHost"
                    Grid.Row="2"
                    BackgroundColor="#272727"
                    SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}"
                    TabType="Fixed">
    <tabs:TabHostView.Tabs>
        <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                            IconImageSource="house_96.png"
                            Label="{localization:Translate Tabs_Home}" />
        <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                            IconImageSource="list_96.png"
                            Label="{localization:Translate Tabs_List}" />

        <!--  Circle button  -->
        <tabs:TabButton ButtonBackgroundColor="Accent"
                        ButtonCircleSize="60"
                        ButtonPadding="15"
                        IconImageSource="theme.png"
                        Scale="1.3"
                        TranslationY="-10" />

        <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                            IconImageSource="grid_view_96.png"
                            Label="{localization:Translate Tabs_Grid}" />
        <tabs:BottomTabItem Style="{StaticResource BottomTabStyle}"
                            IconImageSource="house_96.png"
                            Label="{localization:Translate Tabs_Home}" />
    </tabs:TabHostView.Tabs>
</tabs:TabHostView>

So just a bit of translation and scale here.

You can also decide to have a more boring button, why not?

<tabs:TabButton Padding="5"
                ButtonBackgroundColor="Accent"
                ButtonPadding="10"
                CornerRadius="5"
                IconImageSource="camera_96.png" />

BadgeView (Chips)

You can add a badge on any UnderlinedTabItem and BottomTabItem.

By default the BadgeView is placed in the top right corner of the TabItem by setting HorizontalOptions=End and VerticalOptions=Start.

Badges on BottomTabItem

SillyBottomTabsPage.xml from the Silly! app

<!--  Example of segmented tab bar (rounded floating tabs)  -->
<tabs:TabHostView Grid.Row="2"
                    WidthRequest="280"
                    HeightRequest="60"
                    Margin="15"
                    HorizontalOptions="Center"
                    VerticalOptions="Start"
                    CornerRadius="30"
                    IsSegmented="True"
                    Shades="{sh:NeumorphismShades}"
                    TabType="Fixed"
                    SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
    <tabs:TabHostView.Tabs>
        <tabs:BottomTabItem IconImageSource="house_96.png" Label="{localization:Translate Tabs_Home}">
            <tabs:BottomTabItem.Badge>
                <tabs:BadgeView BackgroundColor="White"
                                BorderColor="{StaticResource Accent}"
                                TextColor="{StaticResource Accent}"
                                Text="999+" />
            </tabs:BottomTabItem.Badge>
        </tabs:BottomTabItem>
        <tabs:BottomTabItem IconImageSource="list_96.png" Label="{localization:Translate Tabs_List}">
            <tabs:BottomTabItem.Badge>
                <tabs:BadgeView BackgroundColor="DodgerBlue"
                                BadgePadding="4,2"
                                TextSize="13"
                                Text="{Binding ListPageViewModel.SillyCount}" />
            </tabs:BottomTabItem.Badge>
        </tabs:BottomTabItem>
        <tabs:BottomTabItem IconImageSource="grid_view_96.png" Label="{localization:Translate Tabs_Grid}">
            <tabs:BottomTabItem.Badge>
                <tabs:BadgeView Margin="20,5"
                                BackgroundColor="Red"
                                ShowIndicator="True"
                                TextSize="14"
                                Text="3" />
            </tabs:BottomTabItem.Badge>
        </tabs:BottomTabItem>
    </tabs:TabHostView.Tabs>
</tabs:TabHostView>

Badges on UnderlinedTabItem

SillyDudePage.xml from the Silly! app

<tabs:TabHostView x:Name="TabHost"
                    Grid.Row="4"
                    Margin="-16,0,-16,30"
                    BackgroundColor="{DynamicResource DynamicBottomBarBackground}"
                    CornerRadius="20"
                    Shades="{DynamicResource DynamicTabsShadow}"
                    TabType="Fixed"
                    SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
    <tabs:TabHostView.Tabs>
        <tabs:UnderlinedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Quote">
            <tabs:UnderlinedTabItem.Badge>
                <tabs:BadgeView BackgroundColor="{StaticResource Accent}"
                                BadgePadding="6,2"
                                FontFamily="{StaticResource FontExtraBold}"
                                TextSize="12"
                                Text="9" />
            </tabs:UnderlinedTabItem.Badge>
        </tabs:UnderlinedTabItem>
        <tabs:UnderlinedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Movies">
            <tabs:UnderlinedTabItem.Badge>
                <tabs:BadgeView BackgroundColor="DodgerBlue"
                                BadgePadding="6,1,6,2"
                                Text="new" />
            </tabs:UnderlinedTabItem.Badge>
        </tabs:UnderlinedTabItem>
        <tabs:UnderlinedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Meme">
            <tabs:UnderlinedTabItem.Badge>
                <tabs:BadgeView Margin="20,0"
                                HorizontalOptions="Start"
                                VerticalOptions="Center"
                                BackgroundColor="White"
                                BorderColor="{StaticResource Accent}"
                                TextColor="{StaticResource Accent}"
                                Text="14" />
            </tabs:UnderlinedTabItem.Badge>
        </tabs:UnderlinedTabItem>
    </tabs:TabHostView.Tabs>
    </tabs:TabHostView>

Properties

Property Description Default
Text Sets the text for the badge text.
If it's an integer, the badge will be hidden if the value is 0.
string.Empty
TextSize Sets the text size used for the badge text. 10
TextColor Sets the text color used for the badge text. Color.White
FontFamily Sets the font family used for the badge text. null
BadgePadding Precisely adjust inner text margin. new Thickness(4, 2)
ShowIndicator Shows a small dot instead of the babdge. false
BackgroundColor Sets the background for the badge. Color.Red
BorderColor Sets a border color for the badge. Transparent
Margin Sets a precise margin for the badge. 10
HorizontalOptions Sets the horizontal location of the badge. LayoutOptions.End
VerticalOptions Sets the vertical location of the badge. LayoutOptions.Start

Custom SPAM tabs !

As I said, your designer can go cuckoo and you won't even sweat it.
Just extend the abstract TabItem and fulfill the wildest dreams of your colleagues.

<tabs:TabItem x:Class="SillyCompany.Mobile.Practices.Presentation.CustomViews.SpamTab"
              xmlns="http://xamarin.com/schemas/2014/forms"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              xmlns:tabs="clr-namespace:Sharpnado.Presentation.Forms.CustomViews.Tabs;assembly=Sharpnado.Presentation.Forms"
              x:Name="RootLayout">
    <ContentView.Content>
        <Grid ColumnSpacing="0" RowSpacing="0">
            <Image x:Name="Spam"
                   VerticalOptions="End"
                   Aspect="Fill"
                   Source="{Binding Source={x:Reference RootLayout}, Path=SpamImage}" />
            <Image x:Name="Foot"
                   Aspect="Fill"
                   Source="monty_python_foot" />
        </Grid>
    </ContentView.Content>
</tabs:TabItem>

...

<tabs:TabHostView x:Name="TabHost"
                  Grid.Row="2"
                  BackgroundColor="White"
                  SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
    <tabs:TabHostView.Tabs>
        <tb:SpamTab SpamImage="spam_classic_home" />
        <tb:SpamTab SpamImage="spam_classic_list" />
        <tb:SpamTab SpamImage="spam_classic_grid" />
    </tabs:TabHostView.Tabs>
...

Please don't be shy with Xamarin.Forms animations, it's so easy to use and so powerful thanks to the amazing C# Task api.
USE.
THEM.

private void Animate(bool isSelected)
{
    double targetFootOpacity = isSelected ? 1 : 0;
    double targetFootTranslationY = isSelected ? 0 : -_height;
    double targetHeightSpam = isSelected ? 0 : _height;

    NotifyTask.Create(
        async () =>
        {
            Task fadeFootTask = Foot.FadeTo(targetFootOpacity, 500);
            Task translateFootTask = Foot.TranslateTo(0, targetFootTranslationY, 250, Easing.CubicOut);
            Task heightSpamTask = Spam.HeightRequestTo(targetHeightSpam, 250, Easing.CubicOut);

            await Task.WhenAll(fadeFootTask, translateFootTask, heightSpamTask);

            Spam.HeightRequest = targetHeightSpam;
            Foot.TranslationY = targetFootTranslationY;
            Foot.Opacity = targetFootOpacity;
        });
}

sharpnado.tabs's People

Contributors

mkanyo avatar mphill avatar nebula2 avatar nor0x avatar notanaverageman avatar roubachof avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sharpnado.tabs's Issues

UnderlinedTabItem with text and icon

First of all, Sharpnado Tabs rocks 🤘😆🤘

There are so many places I found them useful.

Currently we can set only text in UnderlinedTabItem. To show image we can use Icon Font but it's not possible to show them both at the same time.

It would be nice to have additional property, maybe IconImageSource (to be consistent with BottomTabItem) which will allow to set any ImageSource next to Label.

As an additional option, we could have something like ContentLayout in Button to control how icon should be displayed relative to text:
https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.button.contentlayout?view=xamarin-forms

Alternatively, it could be made Templated :) So we can set any Content instead of just text. When Content is text, it could be converted to label as we have now.

[Xamarin.Forms] Is there a way to cancel a tab switch after clicking a selectable tab?

Given this UI:

<tabs:ViewSwitcher x:Name="Switcher"
                              SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">

               ...some views

</tabs:ViewSwitcher>

and

   <tabs:TabHostView x:Name="TabHost"
                             TabType="Fixed"
                             SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
                <tabs:TabHostView.Tabs>

                 ... some tabs

                </tabs:TabHostView.Tabs>
     </tabs:TabHostView>

and this view model implementation:

    public int SelectedViewModelIndex
    {
        get => selectedViewModelIndex;
        set
        {

               if (ShouldChangePage(from: selectedViewModelIndex, to: value)){
                      SelectedViewModelIndex = value;
              }{
              // Don't want to change tab if I get here
              }

        }
    }

Even if the pseudo "ShouldChangePage" method returns false, and we never actually set the SelectedViewModelIndex property - the UI switches tabs anyway even though the selectedViewModelIndex doesn't change.

I could utilise IsEnabled and pre-disable the tabs based on my logic - but I would like to perform an action based on a tab click like show some UI with "why can't you switch" type explanation.

Is there any way to do this?

Enable FontAwesome for IconImageSource in TabItems

Currently you can only enter a string in IconImageSource that is related to an actual resource that has been added to either the forms project or the individual platform projects. It would be nice if you could use something like FontAwesome for Icons in the TabItems

Proposal (allow for backward capability)
Add an additional property that is something like "FontIconImageSource" and a corresponding IValueConvertor to get the icon from the fontawesome library. It would look like the following
<tabs:BottomTabItem FontIconImageSource="{x:Static fontawesome:FontAwesomeIcons.Users}" FontFamily="{StaticResource FontAwesomeSolid}" />

Here is a great article on using fontawesome fonts in a xamarin.forms library. User would have to the the same for this.
https://medium.com/@tsjdevapps/use-fontawesome-in-a-xamarin-forms-app-2edf25311db4

Describe alternatives you've considered
Tried to the following the above article and tried this
<tabs:BottomTabItem IconImageSource="{x:Static fontawesome:FontAwesomeIcons.Users}" FontFamily="{StaticResource FontAwesomeSolid}" />

Theme not correctly applied on Scrollable UnderlinedTabItem

Platform:

  • OS: Android
  • Device: all (AndroidEmulator/OnePlus8Pro)
  • Sdk vervion: [Android SDK 28]
  • Xamarin.Forms: [4.8.0.1821]

Describe the bug
I'm currently trying to use 2 Sharpnado tabs in the same screen (1 bottom bar in a page and 1 horizontal scrollable in a view). My issue is on the rendering of Scrollable UnderlinedTabItem when changing the theme dynamically. Only some tabs are having the correct theme applied. The issue does not occur if no tab is selected.

Screenshots
image

Vertical Tabs

Describe the solution you'd like

First of all - thank you for yet another great component for Xamarin.Forms. I'm already using some of your other packages and have to say that it's a joy using them 👏

i was wondering if these tabs can also be displayed vertically - the TabHostView contains a Grid and a ScrollView which could both handle vertical layouting i guess. I know that there is more to it obviously but i was curious if Vertical Tabs are interesting for you?

More and more apps, especially on landscape orientation (Desktop, Tablets,...) are using vertical tabs as their main navigation mechanism. i.e. Discord, MS Teams, MS Edge, Mac App Store...

Describe alternatives you've considered
Could probably be done with a Main-Detail layout, but this seems to more suited for showing very similar views and just chaning the underlying data for the detatil view

Additional context
Here are some examples:
IMG_12389123
©redit https://dribbble.com/shots/13818645-Project-Kanban-Style
©redit https://dribbble.com/shots/14158637-Deals
©redit https://dribbble.com/shots/9834917-Careers-Hiring-Job-Admin-UI-Design/attachments/1867783?mode=media
©redit https://dribbble.com/shots/13616742-User-Profile

Using TabType="Scrollable" missing scroll/focus

I'm very fond of this component which i find very flexible and performant. Thank you !

However i miss the functionality to automatically (or by calling a build-in method inside OnSelectedIndexChanged) to "automatically" scroll the TabHostView to the currently selected TabItem

Whether I set the SelectedIndex via code to an index currently not visible (not scrolled into view) OR the user "taps" on a partly visible TabItem - the TabHostView is not automatically scrolling the TabItem to be fully visible.

I may very well be missing setting a Property on TabHostView to some "magic" value - but I did consult the sources on github - and i couldn't find either a method nor something that seem to ask the private _scrollView to scroll items to be visible.

What am I missing ?

Regards René

Ability to bind Tabs property of a TabHostView

Is your feature request related to a problem? Please describe.
I was trying to create tabs on the go using the Tabs observable collection. I ended up using a workaround but it will be easy to bind the whole object.

Describe the solution you'd like
Bindable Tabs of a TabHostView

Describe alternatives you've considered
Initialize the Tabs on Xaml and send the TabHostView as a parameter to the ViewModel so I can create the dynamic tabs later on.

Additional context
We have a feature in which you can have multiple tabs based on how many tables a restaurant has.

[MAUI] warning MSB3270: There was a mismatch between the processor architecture of the project being built...

Platform

  • OS: iOS
  • MAUI: latest

Describe the bug
When adding the Sharpnado.Tabs.Maui nuget to a simple class library targeting net6.0-ios, I get the following warning when building the library:

warning MSB3270: There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "C:\Nuget\sharpnado.tabs.maui\3.0.0\lib\net6.0-ios15.4\Maui.Tabs.dll", "AMD64". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.

Could you please help me understand it and fix it ?

To Reproduce
Steps to reproduce the behavior:

  1. Create a class library for net6.0
  2. Target net6.0-ios (see csproj below)
  3. Add a package reference to Sharpnado.Tabs.Maui (3.0.0)
  4. Build library
  5. See warning

csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net6.0-android;net6.0-ios</TargetFrameworks>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Sharpnado.Tabs.Maui" Version="3.0.0" />
  </ItemGroup>
</Project>

Tab Icon Dynamic Resource Colors Not Changing after tapping on them

Platform (please complete the following information):

  • OS: [Both]
  • Device: [Pixel/AndroidEmulator/iPhone 7]
  • Sdk vervion: [iOS 14.1/Android SDK 28]
  • Xamarin.Forms: [4.6.0]

Describe the bug
I have a Dynamic Resource color which is being swapped out if the user changes from Light to Dark mode and vice versa. If the user doesn't tap any of the tab icons, the colors change fine. However, after they have tapped on the tab icon, and you try to change the color, the color is not updated anymore.

To Reproduce
Steps to reproduce the behavior:

  1. Load up the attached sample
  2. On the screen that loads, click the 'Change Color' button. You will see that all the home icons change color, which is correct
  3. Tap on one or two of the home icons and then click the 'Change Color' button again.
  4. You will see that only the icons that you haven't clicked on before will be updated. If you tap on all the home icons, then no colors will ever be updated

Exceptions (if applicable)
N/A

Screenshots (if applicable)
See attached sample

App2.zip

Enable Wiki

Describe the solution you'd like
Could we have the wiki enabled for this plugin so we can add to it, this would help as right now the readme is quite long and the sample project is sort of seperate to Sharpnado.Tabs specfically.

Describe alternatives you've considered
A longer readme or a couple more sample projects, but the existence of the sample project and the long readme would be better of just as a short wiki maintained here on the page

How to swipe between tabs

Is your feature request related to a problem? Please describe.
I want the TabHostView and ViewSwitcher to have the carousel effect? In other words make it work just like a tabstrip works on Android.[...]

Thank you very much for this amazing library.

[MAUI] Configurable TouchEffect duration (Android RippleEffect)

Is your feature request related to a problem? Please describe.
Configurable TouchEffect: TapAnimation duration

Describe the solution you'd like
XAML property i.e. similar to <syncEffectsView:SfEffectsView RippleAnimationDuration="800">

        public static readonly BindableProperty DurationProperty =
            BindableProperty.CreateAttached(
            propertyName: "Duration",
            typeof(double),
            typeof(TouchEffect),
            250, /* Android 250 / iOS 225 */
            propertyChanged: PropertyChanged
        );

Describe alternatives you've considered
None

Additional context
TouchEffectPlatform.cs
Android: TapAnimation(duration: 250, _alpha, 0); (?)
iOS: UIView.Animate(0.225, ...) (?)

[QUESTION] SelectedTabColor

Is there a way for SelectedTabColor to only affect the icon and not output the tapping effect with the same color?

[UWP] Underline does not disappear when switching Tabs

Platform (please complete the following information):

  • UWP
  • Windows
  • Sdk vervion: Windows 10
  • Xamarin.Forms: [5.0.x]

Describe the bug
The underline does not disappears when changing the tabs

To Reproduce
Steps to reproduce the behavior:

  1. Add TabView with multiple Tab
  2. Switch betweens Tabs

Screenshots (if applicable)
image

SelectedIndex's defaultBindingMode should be TwoWay or OneWayToSource by default

SelectedIndex is used to get or set the selected tab.

It's default binding mode is OneWay, which means SelectedIndex can only be used to set the selected tab.

The use case of the tabs is to switch something, especially in segmented mode.

To switch something, the selected item change notification is mandatory.

So SelectedIndex should be TwoWay by default.

Setting GeometryIcon on MaterialUnderlinedTabItem throws System.MissingMethodException

Platform (please complete the following information):

  • OS: Both
  • Device: iPhoneSimulator/AndroidEmulator
  • Sdk vervion: iOS 14/Android SDK 30
  • Xamarin.Forms: 5.0.0.2083

Describe the bug
Using the new MaterialUnderlinedTabItem and setting a GeometryIcon throws System.MissingMethodException.

To Reproduce
Steps to reproduce the behavior:

  1. Add a TabHostView
  2. Add a MaterialUnderlinedTabItem to the TabHostView
  3. Set a GeometryIcon to the MaterialUnderlinedTabItem
  4. Run the application

Exceptions (if applicable)

System.MissingMethodException: Method not found: void Xamarin.Forms.Shapes.Shape.set_Fill(Xamarin.Forms.Color)
  at Sharpnado.Tabs.MaterialUnderlinedTabItem.ToggleIconVisibility (System.Boolean visible) [0x00036] in D:\Dev\Sharpnado\src\Xamarin-Forms-Practices\Sharpnado.Tabs\Tabs\Tabs\MaterialUnderlinedTabItem.xaml.cs:169 
  at Sharpnado.Tabs.MaterialUnderlinedTabItem.UpdateIconAndTextLayout () [0x0005f] in D:\Dev\Sharpnado\src\Xamarin-Forms-Practices\Sharpnado.Tabs\Tabs\Tabs\MaterialUnderlinedTabItem.xaml.cs:150 
  at Sharpnado.Tabs.MaterialUnderlinedTabItem.OnPropertyChanged (System.String propertyName) [0x000f2] in D:\Dev\Sharpnado\src\Xamarin-Forms-Practices\Sharpnado.Tabs\Tabs\Tabs\MaterialUnderlinedTabItem.xaml.cs:128 
  at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x00114] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:510 
  at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:446 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value, System.Boolean fromStyle, System.Boolean checkAccess) [0x0004d] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:374 
  at Xamarin.Forms.BindableObject.SetValue (Xamarin.Forms.BindableProperty property, System.Object value) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\BindableObject.cs:349 
  at Sharpnado.Tabs.MaterialUnderlinedTabItem.set_GeometryIcon (Xamarin.Forms.Shapes.Geometry value) [0x00000] in D:\Dev\Sharpnado\src\Xamarin-Forms-Practices\Sharpnado.Tabs\Tabs\Tabs\MaterialUnderlinedTabItem.xaml.cs:72 
  at myapp.Views.UserProfilePage.InitializeComponent () [0x00023] in D:\Projects\myapp\myapp-platform-app\src\myapp\myapp\obj\Debug\netstandard2.0\Views\UserProfilePage.xaml.g.cs:26 
  at myapp.Views.UserProfilePage..ctor () [0x00008] in D:\Projects\myapp\myapp-platform-app\src\myapp\myapp\Views\UserProfilePage.xaml.cs:17 
  at (wrapper managed-to-native) System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00005] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:936 
  at DryIoc.Interpreter.TryInterpretAndUnwrapContainerException (DryIoc.IResolverContext r, FastExpressionCompiler.LightExpression.Expression expr, System.Boolean useFec, System.Object& result) [0x0002f] in /_/src/DryIoc/Container.cs:2868 
  at DryIoc.Container.ResolveAndCacheKeyed (System.Int32 serviceTypeHash, System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Object scopeName, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x001e1] in /_/src/DryIoc/Container.cs:521 
  at DryIoc.Container.DryIoc.IResolver.Resolve (System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x00042] in /_/src/DryIoc/Container.cs:430 
  at DryIoc.Resolver.Resolve (DryIoc.IResolver resolver, System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, System.Object[] args) [0x00000] in /_/src/DryIoc/Container.cs:8070 
  at Prism.DryIoc.DryIocContainerExtension.Resolve (System.Type type, System.String name, System.ValueTuple`2[System.Type,System.Object][] parameters) [0x0001c] in /_/src/Containers/Prism.DryIoc.Shared/DryIocContainerExtension.cs:314 ```

Invalid Generic Instantiation

  • OS: [iOS]
  • Device: [iPhone 11 simulator]
  • Sdk vervion: [iOS 14.3]
  • VS for Mac 8.8.5 (build 18)
  • Xamarin.Forms: [5.0.0.1874]

Bug: Invalid Instantiation of the LazyView for the tabs in the TabHostView object.

Steps to reproduce the behavior:
2. Clone the repo
3. Launch the iOS project
4. See error

See exception/error screenshot below:

See the app.cs file & XAML files here:

If there is anything else you need to know, please let me know.

Expose FontAttributes Field on TabTextItem

First, thanks so much for your components they are super helpful!

Is your feature request related to a problem? Please describe.
I want to be able to bold the text on the UnderlinedTabItem, as per the TabStyle in the SillyApp! sample application FontSize and FontFamily are exposed but FontAttributes is not. I would like to keep using the default platform fonts but bold the tab item label for legibility/readability

Describe the solution you'd like
Expose FontAttributes field on TabTextItem

Describe alternatives you've considered
I tried researching the Xamarin font documentation https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/text/fonts and looked at the sample font app: https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithFonts but couldn't see how to create a font family without specifying a font file. I just want to use the standard platform fonts but with the bold attribute applied.

Additional context
See Image below, the thin lighter color font is hard to read for people with poor eyesight or in poor lighting conditions:
image

Screen Shot 2020-10-30 at 4 50 22 pm

I would be so grateful if you could slot this in or suggest a workaround :)

[Xamarin] Tab resizing on click

Platform

  • OS: [iOS] (Not tested android)
  • Device: Iphone XS
  • Sdk vervion: 15.2.0.17
  • Xamarin.Forms: 5.0.0.2196

Describe the bug
When having multiple tabs, if one of the tabs has content in a list view / collection view that goes off the screen, once the page is loaded if you click on another tab and go back to the original the tab will reduce in size every time. This doesn't happen on the first load.

Screenshots (if applicable)
ezgif-3-2c3ec5c3dc

Is there an example on how to dynamically create tabs?

This component seems just what I need to implement scrollable tabbed pages.
Based on your example I understand how to create a scrollable set of tabs, how to link them to tab contents, and I can manipulate them from xaml.
However, I need to craeate tabs and tab content dynamically.
Is there an eample on how to do it either fully from C# code, instantiating say UnderlinedTabItems and adding them to the TabHostView and the ViewScroller, or via some templating mechanism and using observable collections.

NavigationPage for each Tab - is this possible?

First: I'm very sorry but it feels like an absolute rookie question and I'm kind of ashamed to ask... Please be kind

We developed our very first Xamarin.Forms App a while ago and our main concept is a TabbedPage with five individual tabs. Three of five tabs are sophisticated pages that can have some deeper navigational structure. So every of those tree tabs is a NavigationPage that wraps the actual page. From within each tab the user can navigate deeper but she can always change the main tabs to check something else.

This works very nice but then I fell kind of in love with your tabs and the possibilities to style them and have them beautifully arranged. So I tried to figure out how to implement our current use case but I'm not seeing how to do this properly. Yes, the ViewSwitcher needs views - got it. But is there something to implement our functionality within a ViewSwitcher and best case with lazy loading?

Thanks for helping out!

Swipe Feature for ViewSwitcher

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Problem with SegmentedTabItem

Platform (please complete the following information):

  • OS: Android
  • Device: AndroidEmulator
  • Sdk vervion: Android SDK 29
  • Xamarin.Forms: 4.7.0.1351

Describe the bug
Downloaded the sample, uncommented the element underneath in the SillyDudePage.xaml and commented the previous one.

The Tabs seems to draw 4 tabs instead of 3. The last one seems to be a dummy one.

Screenshots (if applicable)
If applicable, add screenshots to help explain your problem.
Screenshot_1604185994

Support for .NET MAUI

As a developer, this plugin is very useful for customizing tab to meet the requirement.

So, If this is going to support MAUI, it will be very useful.

Thanks.

Binding Context of View is Changed

Platform

  • OS: Both
  • Device: all
  • MAUI: [6.0.540]

Describe the bug
Inserting the view in the tab removes the view's BindingContext

To Reproduce
I have a content view with the binding context set in view, such as the code below where it is set in xaml:

<ContentView.BindingContext>
        <model:MyViewModel/>
</ContentView.BindingContext>

When I put this view in the DelayedView (or the LazyView) it changes the binding of the view to the parent's page BindingContext
Here is the code for the page:

<tabs:ViewSwitcher x:Name="Switcher" Grid.RowSpan="4" Margin="0" Animate="True"
                                           SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">

          <tabs:DelayedView Animate="True">
                   <views:MyViewWithItsOwnBindingContext/>
          </tabs:DelayedView>

           <tabs:DelayedView x:TypeArguments="views:MySecondView" Animate="True" />
</tabs:ViewSwitcher>

[MAUI/Xamarin.Forms/Both] Sharpnado BottomTab TouchEffect Color Not Working

<tabs:BottomTabItem Label="Home" tabs:TouchEffect.Color="Green"/>

When this is written, it works in Hot Reload mode after the build, but it did not work when it was re-debugged and reopened. I put Touch Effect.Color in TabHostView in the same way, but the color doesn't change and it comes out in sky blue.

Am I doing something wrong?
And it doesn't reflect when you put the color in transparent.

Thank you always.

Add SelectedItem property

For few items TabHostView can be used as an alternative to Picker with it's ItemsSource property. Unlike Picker it doesn't have SelectedItem property so we must bind SelectedIndex, take that index and look into the list to retrieve actual Item. For many properties in VM it can produce a lot of boilerplate code.

To make it consistent with other controls containing ItemsSource, it would be nice to have SelectedItem which may be usefull when we bind tabs to list.

SegmentedTabItem and BadgeView No text

If I use this combination, I'm unable to see the text, otherwise, it works well.

image

<tabs:TabHostView x:Name="TabHost" Grid.Row="1" HeightRequest="40" Margin="20,15,20,0" VerticalOptions="Center" BackgroundColor="#F0F0F3" Shades="{shades:SingleShade Offset='0,8', BlurRadius=10, Color={StaticResource PrimaryColor}, Opacity=0.2}" CornerRadius="20" IsSegmented="True" SegmentedHasSeparator="True" SegmentedOutlineColor="{StaticResource PrimaryColor}" TabType="Fixed" SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}"> <tabs:TabHostView.Tabs> <tabs:SegmentedTabItem Label="Mis números" BackgroundColor="Red" SelectedLabelColor="AliceBlue" SelectedTabColor="Azure"> <tabs:BadgeView Margin="20,0" HorizontalOptions="Start" VerticalOptions="Center" BackgroundColor="Red" BorderColor="{StaticResource TitleColor}" TextColor="{StaticResource TitleColor}" Text="14" /> </tabs:SegmentedTabItem> <tabs:SegmentedTabItem Style="{StaticResource SegmentedTabStyle}" Label="Agregar" /> </tabs:TabHostView.Tabs> </tabs:TabHostView>

I'm using the last version.

Swipe gestures

Would be nice to have to have swipe gestures to switch between tabs.

[MAUI] Package Sharpnado.Tabs.Maui 3.0.0 is not compatible with net6.0

I'm currently migrating my Xamarin.Forms app to Maui.

The architecture of my app looks like this: ios/android app -> UI library -> Core library

ios/android app projects hold the platform specific code required to start the app
UI library holds the UI code (pages, view)
Core libreary holds the business logic code (view models, services, models...)
In the Xamarin app, both UI and Core libraries are netstandard projects.
The UI library references the Sharpnado.Tabs package (since it suports the netstandard TFM).

In my Maui app, both UI and Core libraries are net6.0 projects.
However I find it impossible to reference the Sharpnado.Tabs.Maui package in the UI library.
It expects a net6.0-android / net6.0-ios TFM.
But there is no reason for that, since this is a cross-platform library, with no specific code to compile.

Error	NU1202	
Package Sharpnado.Tabs.Maui 3.0.0 is not compatible with net6.0 (.NETCoreApp,Version=v6.0). 
Package Sharpnado.Tabs.Maui 3.0.0 supports:
  - net6.0-android31.0 (.NETCoreApp,Version=v6.0)
  - net6.0-ios15.4 (.NETCoreApp,Version=v6.0)

Could you please make sure this package can be installed in a net6.0 project?

Thanks

Load page on demand.

Is it possible to load the pages asynchronously while appearing? I cannot find the way to implement this in Sharpnado Tabs? All the pages in view switcher loads during the startup.

TabItemTappedCommand on Hostview is set to private and not available

On The class TabHostView your Command: TabItemTappedCommand is set to private and therefore not available fo command excecution.

line 229: private ICommand TabItemTappedCommand { get; }

Though it is possible to use the xamarin Community toolkit to convert the SelectedIndexChanged event to a command it would be much better if the command would become publicly available and thus make a command excecution possible when an item is selected.

Can't insert a Tab

Platform

  • OS: iOS
  • Device: iPhoneSimulator

Describe the bug
Trying to adapt the SillyBottomTabsPage in the SillyCompany demo, I ran into this problem, which seems to be a problem with the base Sharpnado Tabs functionality, not the SillyCompany code. I could be wrong about that of course.
I created an AddTab(...) method in the view holding the tabs and the views and the switcher, whose body is basically:

     TabHost.Tabs.Add(tabItem);
     Switcher.Children.Add(view);

And this seems to work well.

However I tried an InsertTab(...) variation, which basically did the same, only like this:

     TabHost.Tabs.Insert(index, tabItem);
     Switcher.Children.Insert(index, view);

But when I did this, it inserted the icons properly but had the labels in the wrong place.

It just added the label on the end instead of inserting it where it should have gone.

To Reproduce
Steps to reproduce the behavior:

  1. use the SillyBottomTabsPage in the SillyCompany demo
  2. create a new BottomTabItem and a new View
  3. Use Insert(...) to insert the BottomTabItem to TabHost and the View to the Switcher, each using the same index, making sure the index is somewhere before the last items already in both those arrays.

Support for screen readers

My app utilizes the Sharpnado tabs. But the VoiceOver feature of iOS, that read aloud the items being tapped, does not seem to behave properly with Sharpnado Tabs.

First of all, if I change to another page using the Sharpnado tabs, and taps around the screen, it reads aloud elements of the previous now hidden page.
Second: Don't know if this is just when having a listbox as content in a page, but when tapping in the Sharpnado bottom tabbar, it reads aloud items from the listbox behind the tabbar.

Support for WPF

Is your feature request related to a problem? Please describe.
I need to backport our Xamarin Forms Application to WPF because of numerous machines being stuck on Windows 10 1607.

Describe the solution you'd like
Please add support for WPF.

Describe alternatives you've considered
Cloning the source and "hotfixing" it for my application.

Additional context
I've cloned the source code, plugged it directly into my application. Found out that extending the UWP-Part to check also for WPF, it works already. Of course no "special effects" (tinting) are applied.

Method SetTapUWP (Line 81 at the time of writing):

if ((Device.RuntimePlatform != Device.UWP && Device.RuntimePlatform!= Device.WPF) || !(bindableObject is View view))...

Method PropertyChanged (Line 155 at the time of writing):

if ((Device.RuntimePlatform == Device.UWP || Device.RuntimePlatform == Device.WPF)...

Segmented Control Command

Hey, so im trying to run a Command each time someone clicks a new BottomTabItem instead of loading a new ContentView.

My current code opens a new ContentView which seems quite slow to me.
So how would a run a command if a tab gets clicked?

Repository with the code
Current code:

<ContentPage.Content>
        <Grid> 
                <StackLayout>
                    <tabs:ViewSwitcher x:Name="Switcher"
                                       Padding="0,0,0,0"
                                       Animate="True"
                                       SelectedIndex="{Binding SelectedViewModelIndex, Mode=TwoWay}">
                    <views:YoutubeSmallPage/>
                    <views:InstagramSmallPage/>
                    <views:TiktokSmallPage/>
                    <views:TwitterSmallPage/>
                    <views:TwitchSmallPage/>
                </tabs:ViewSwitcher>
                </StackLayout>

            <tabs:TabHostView x:Name="TabHost"
                              HeightRequest="40"
                              WidthRequest="300"
                              Margin="0,0,0,20"
                              VerticalOptions="End"
                              HorizontalOptions="Center"
                              BackgroundColor="#F0F0F3"
                              Shades="{sh:SingleShade Offset='0,8',
                                            Color={StaticResource Primary},
                                            BlurRadius=10,
                                            Opacity=0.2}"
                              CornerRadius="50"
                              IsSegmented="True"
                              SegmentedHasSeparator="True"
                              SegmentedOutlineColor="{StaticResource Primary}"
                              TabType="Fixed"
                              SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}">
                <tabs:TabHostView.Tabs>
                    <tabs:BottomTabItem Style="{StaticResource SegmentedTabStyle}" IconImageSource="youtube.png" IconSize="20" Padding="0,10,0,0" UnselectedIconColor="#d44141"/>
                    <tabs:BottomTabItem Style="{StaticResource SegmentedTabStyle}" IconImageSource="instagram.png" IconSize="20" Padding="0,10,0,0" UnselectedIconColor="#aa7a50"/>
                    <tabs:BottomTabItem Style="{StaticResource SegmentedTabStyle}" IconImageSource="tiktok.png" IconSize="20" Padding="0,10,0,0"/>
                    <tabs:BottomTabItem Style="{StaticResource SegmentedTabStyle}" IconImageSource="twitter.png" IconSize="20" Padding="0,10,0,0" UnselectedIconColor="#08a0e9"/>
                    <tabs:BottomTabItem Style="{StaticResource SegmentedTabStyle}" IconImageSource="twitch.png" IconSize="20" Padding="0,10,0,0" UnselectedIconColor="#816ea4"/>
                </tabs:TabHostView.Tabs>
            </tabs:TabHostView>
        </Grid>
    </ContentPage.Content>```

If i open the page which contains the tabs it at least takes around one second to load the page.

Update [ContentProperty("TabHostContent")] to [ContentProperty("Tabs")]

Update [ContentProperty("TabHostContent")] to [ContentProperty("Tabs")]

    [ContentProperty("TabHostContent")]
    public class TabHostView : Shadows

...
        public View TabHostContent
        {
            set =>
                throw new NotSupportedException(
                    "Starting from version 1.3, you can only add TabItem to the TabHostView through the Tabs property");
        }

On Android Bottom TAB Item click is not working

Platform (please complete the following information):

  • OS: [Android]
  • Device: [AndroidEmulator/...]
  • Sdk vervion: [/Android SDK 30]
  • Xamarin.Forms: [5.0]

Describe the bug
On Android Bottom, the TAB Item click is not working.it's very hard to change the tabs

To Reproduce
Steps to reproduce the behavior:
On Android Bottom, the TAB Item click is not working.it's very hard to change the tabs

Underline color property

Hello. I'm using you lib in case of awsome tabs. But for me not enought property to change color of undeline.
It will be very nice if you add such changes in a close time.

SelectedTabIndexChanged called multiple times

Platform (please complete the following information):

  • OS: Android
  • Device: AndroidEmulator/
  • Sdk version: Android SDK 21
  • Xamarin.Forms: [4.8.0.1451]

Describe the bug
I have added an event handler for SelectedTabIndexChanged. Every time I tap on a tab item, this handler is called 3 times. It should be called only once.

To Reproduce
Add a SelectedTabIndexChanged handler. Check how many times is called with a tap on a tab item.

[MAUI] .Net7 Support

Thanks in advance for this AMAZING library!

Platform (please complete the following information):

  • OS: Android
  • Device: Android devices and emulators
  • SDK version: Android SDK 31
  • MAUI: 7.0.100

Describe the bug
Deploying an app that was built in release mode targeting Android will fail after the app launch.

To Reproduce
Steps to reproduce the behavior:

  1. Install Sharpnado.Tabs.Maui in a Blank project using .Net7
  2. Build and Deploy in Release mode to Android Device.
  3. See the error

Exceptions (if applicable)

Error Message from VS: The selected execution mode is not supported for .Net projects

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.