dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.23k stars 1.76k forks source link

[Spec] TabView #151

Closed jsuarezruiz closed 4 years ago

jsuarezruiz commented 4 years ago

TabView

We can have tabs using Shell. However, what happens if we want to have nested tabs within a specific section (Example: Grid)?, what if we want to fully customize each tab?. In these cases, we would need a Custom Renderer so far...

The TabView is a way to display a set of tabs and their respective content. TabView is useful for displaying several content while giving a user the capability to customize mostly everything.

tabview

NOTE: TabView is a cross-platform view that takes over when native tabs hit their limits, such as positioning with layouts, styling, and non-uniform styling like a raised button.

API

Next, a list with the TabView properties, events and visualstates.

Properties

TabView Properties

Property Type Description
TabItemsSource IEnumerable A collection used to generate the TabView's tab items.
TabViewItemDataTemplate DataTemplate the template the Tab View uses to generate tab items' header.
TabContentDataTemplate DataTemplate The template the Tab View uses to generate tab items' content.
IsCyclical Bool Enable or disable cyclical tabs navigation.
IsLazy Bool Enable or disable lazy tabs loading.
SelectedIndex Int Gets or sets the currently selected tab. Default is 0.
TabStripPlacement TabStripPlacement The TabStrip placement (top or bottom).
TabStripBackground Brush The TabStrip background.
TabIndicatorBrush Brush The TabIndicator background.
TabIndicatorHeight double The TabIndicator height.
TabIndicatorWidth double The TabIndicator width.
TabIndicatorPlacement TabIndicatorPlacement
TabIndicatorView View The TabIndicator content.
TabContentBackground Brush The tab content background.
TabContentHeight Double The tab content height.
TabStripHeight Double The TabStrip height.
TabContentHeight Double The tab content height.
HasTabStripShadow Bool Show or hide the TabStrip shadow effect.
IsTabTransitionEnabled Bool Enable or disable the transition between tabs.
IsSwipeEnabled Bool Enable or disable the swipe gesture.

TabViewItem Properties

Property Type Description
Text String The text of the tab.
TextColor Color The text color of the tab.
TextColorSelected Color The text color of the selected tab.
FontSize FontSize The font size used in the tab text.
FontSizeSelected FontSize The font size used in the selected tab.
FontFamily String The font family used in the tab.
FontFamilySelected String The font family used in the selected tab.
FontAttributes FontAttributes The font attributes used in the tab.
FontAttributesSelected FontAttributes The font attributes used in the selected tab.
Icon ImageSource The icon of the tab.
IconSelected ImageSource The ImageSource used as icon in the selected tab.
Content View The content of the tab. Is View, can use anything as content.
BadgeText Bool The badge text used in the tab.
BadgeTextColor Color The badge text color used in the tab.
BadgeTextColorSelected Color The badge text color used in the selected tab.
BadgeBackgroundColor Color The badge color used in the tab.
BadgeBackgroundColorSelected Color The badge color used in the selected tab.
IsSelected Bool a bool that indicate if the tab is selected or not.
TapCommand ICommand Command that is executed when the user tap a tab.
TapCommandParameter object The tap command parameter.

Events

TabView Events

Event Description
SelectionChanged Event that is raised when the selected tab changed.
Scrolled Event that is raised when is swiping between tabs.

TabViewItem Events

Event Description
TabTapped Event that is raised when the user tap a tab.

VisualStates

The Visual State Manager (VSM) provides a structured way to make visual changes to the user interface from code. The VSM introduces the concept of visual states. TabView can have several different visual appearances depending on its underlying state.

TabView have four specific VisualStates:

Scenarios

Let's see some samples covering common scenarios.

Basic Tabs

Let's see a basic example:

<TabView 
    TabStripPlacement="Bottom"
    TabStripBackgroundColor="Blue">
    <TabViewItem
        Icon="triangle.png"
        Text="Tab 1">
        <Grid 
            BackgroundColor="Gray">
            <Label
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Text="TabContent1" />
        </Grid>
    </TabViewItem>
    <TabViewItem
        Icon="circle.png"
        Text="Tab 2">
        <Grid>
            <Label    
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Text="TabContent2" />
        </Grid>
    </TabViewItem>
</TabView>

basic-tabs

TabItemsSource

Using TabItemsSource (dynamic tabs):

<TabView
    TabItemsSource="{Binding Monkeys}"
    TabViewItemDataTemplate="{StaticResource TabViewItemTemplate}"
    TabContentDataTemplate="{StaticResource TabContentTemplate}" />

tabitemssource

Custom Tabs

The appearance of each tab can be customized:

<ControlTemplate
    x:Key="TabItemTemplate">
    <Grid>
    ...
    </Grid>
</ControlTemplate>

<TabView>
    <TabViewItem
        Text="Tab 1"
        ControlTemplate="{StaticResource TabItemTemplate}">
    </TabViewItem>
</TabView>

custom-tabs

Cyclical Tabs

Do you want to navigate between the tabs cyclically?

<TabView
    IsCyclical="True">
    ...
</TabView>

iscyclical

Lazy Loading

Lazy tab loading:

<TabView
    IsLazy="True">
    ...
</TabView>

lazy-tabs

Tab Transitions and TabViewItem animations

Can use Xamarin.Forms animations to customize the transition between each tab, animate the tab when appears or disappears, or even animate the badge when appears or disappears.

<TabView>
    <TabView.TabTransition>
        <local:CustomTabTransition />
    </TabView.TabTransition>
    <TabViewItem
        Text="Tab 1">      
            <TabViewItem.TabAnimation>
                <local:CustomTabViewItemAnimation />
            </TabViewItem.TabAnimation>
        <Grid 
            BackgroundColor="LawnGreen">
            <Label
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Text="TabContent1" />
        </Grid>
    </TabViewItem>
    ...
</TabView>

custom-tabs-animation

Using VisualStates

Can use different visual states to customize the current tab, the next tab, etc.

<Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="TabViewStates">
            <VisualState x:Name="CurrentTab">
                <VisualState.Setters>
                    <Setter Property="Opacity" Value="1" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="PreviousTab">
                <VisualState.Setters>
                    <Setter Property="Opacity" Value="0.7" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="NextTab">
                <VisualState.Setters>
                    <Setter Property="Opacity" Value="0.7" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="DefaultTab">
                <VisualState.Setters>
                    <Setter Property="Opacity" Value="0.9" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Label Text="{Binding Index}" HorizontalOptions="Center" VerticalOptions="End" />
</Grid>

Create Tabs using C

You can use XAML or C# to create the UI in Xamarin.Forms. Let's see how we would create tabs using C#.

var tabView = new Tabs
{
    TabStripPlacement = TabStripPlacement.Bottom,
    TabStripBackgroundColor = Color.Blue,
    TabStripHeight = 60,
    TabIndicatorColor = Color.Yellow,
    TabContentBackgroundColor = Color.Yellow
};

var tabViewItem1 = new TabViewItem
{
    Icon = "triangle.png",
    Text = "Tab 1",
    TextColor = Color.White,
    TextColorSelected = Color.Yellow,
};

var tabViewItem1Content = new Grid
{
    BackgroundColor = Color.Gray
};

var label1 = new Label
{
    HorizontalOptions = LayoutOptions.Center,
    VerticalOptions = LayoutOptions.Center,
    Text = "TabContent1"
};

tabViewItem1Content.Children.Add(label1);

tabViewItem1.Content = tabViewItem1Content;

tabView.TabItems.Add(tabViewItem1);

var tabViewItem2 = new TabViewItem
{
    Icon = "circle.png",
    Text = "Tab 2",
    TextColor = Color.White,
    TextColorSelected = Color.Yellow
};

var tabViewItem2Content = new Grid
{
    BackgroundColor = Color.OrangeRed
};

var label2 = new Label
{
    HorizontalOptions = LayoutOptions.Center,
    VerticalOptions = LayoutOptions.Center,
    Text = "TabContent2"
};

tabViewItem2Content.Children.Add(label2);

tabViewItem2.Content = tabViewItem2Content;

tabView.TabItems.Add(tabViewItem2);

Using Styles

Can customize the appearance of the tab content, tab strip, tab item, etc. using XAML styles or CSS.

Using XAML:

<Style
    x:Key="TabItemStyle"
    TargetType="TabViewItem">
    <Setter
        Property="FontSize"
        Value="12" />
    <Setter
        Property="TextColor"
        Value="#979797" />
</Style>

Using CSS:

.customTabItem {
    font-size: medium;
    text-color: red;
}

Difficulty : Medium

More information

Based on https://github.com/xamarin/Xamarin.Forms/issues/10773

saint4eva commented 4 years ago

Can we see the C# sample in MVU?

jrc14 commented 4 years ago

It would be really helpful for some usage scenarios (e.g. mine) if the TabView behaviour was extended so that, if the display was wide enough, the tabs would 'unwrap', which is to say, they would show the contents of all the tabs across the screen. This allows a neat 'responsive design' which works really nicely with tablets.

On a phone, or a tablet held in portrait mode, the user sees a tabbed view with one pane shown on screen, and the other panes reachable via the 'switch tab' gesture; but when the tablet is rotated to landscape mode (or if on a desktop machine with a wide enough screen) the screen shows all the panes at the same time, next to one another, across the screen.

MhAllan commented 4 years ago

Icon to be of type View instead of ImageSource please. We want to show notifications (usually as small dots on the top corner of the tab icon)

irongut commented 4 years ago

Icon to be of type View instead of ImageSource please. We want to show notifications (usually as small dots on the top corner of the tab icon)

@MhAllan I believe that would be accomplished using the TabViewItem properties BadgeText, BadgeTextColor, BadgeTextColorSelected, BadgeBackgroundColor & BadgeBackgroundColorSelected.

I notice BadgeText seems to have the wrong type listed, I'm sure it is supposed to be String, not Bool.

MhAllan commented 4 years ago

@irongut , Thanks for the note. I think those are wrong design as well. There shouldn't be something like a BadgeText.

If we think of a framework that can meet future requirements we shouldn't limit developers with types like String or ImageSource. If do so then we will soon get issues like this: Make Badge Corner Rounded, Made Badge Bigger, Smaller, Shadow, Left to the Icon, Up, Down, Right, in front of the icon, behind the icon, Animated ... etc. And people will get frustrated they can't customise it easily. Writing this, I am currently making a notification badge that will rotate around X axis twice before it settles. see how weird customisation can be?

EmilAlipiev commented 4 years ago

@MhAllan Syncfusion's SfTabview is a good example how it can be done more dynamic.

MhAllan commented 4 years ago

Thanks, but who wants to take a look at a leech's work that is being sold for thousands of dollars when operating systems, programming languages, and awesome frameworks are free.

EmilAlipiev commented 4 years ago

I didnt mean that use Syncfusion. it was just to say that it is good example to see and inspire how they did it. Beside that they offer free for individual customers only paid for big companies over 1m revenue. Believe me they are 1-2 steps ahead of Xamarin itself. we cant even get a proper Collection/ListView here for months, for years.

Inrego commented 4 years ago

I agree that the TabViewItem as a whole should more or less just have a ContentView where we can put whatever view we want inside the tab items. The current of doing it, limits us to implementing tab views in the way that you envisioned them, not how we want them. If you want an "easy-to-use" tab view which has a default look, you can just make a SimpleTabItemView class, which people can use as the view for their tab items, while allowing us to implement our own look and feel via our own custom views.

serdarozkan41 commented 4 years ago

I agree that the TabViewItem as a whole should more or less just have a ContentView where we can put whatever view we want inside the tab items. The current of doing it, limits us to implementing tab views in the way that you envisioned them, not how we want them. If you want an "easy-to-use" tab view which has a default look, you can just make a SimpleTabItemView class, which people can use as the view for their tab items, while allowing us to implement our own look and feel via our own custom views.

I think it is good to have some limitations for stable operation

Inrego commented 4 years ago

I think it is good to have some limitations for stable operation

You can still have the default tab view for your easy to use "stable operation". There's no reason to limit the whole view.

PureWeen commented 4 years ago

These are moving to Xamarin Community Toolkit for now

davidbuckleyni commented 3 years ago

Silly questions but can we tell the tabs to open new pages or will that still be handled in shell