Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/roubachof/sharpnado.tabs
Pure MAUI and Xamarin.Forms Tabs, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, bendable tabs...
https://github.com/roubachof/sharpnado.tabs
android badge bottomtabs ios maui tabs xamarin xamarin-forms
Last synced: about 20 hours ago
JSON representation
Pure MAUI and Xamarin.Forms Tabs, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, bendable tabs...
- Host: GitHub
- URL: https://github.com/roubachof/sharpnado.tabs
- Owner: roubachof
- License: mit
- Created: 2020-10-09T13:57:06.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-09-23T07:10:45.000Z (2 days ago)
- Last Synced: 2024-09-23T09:11:38.616Z (2 days ago)
- Topics: android, badge, bottomtabs, ios, maui, tabs, xamarin, xamarin-forms
- Language: C#
- Homepage:
- Size: 19.4 MB
- Stars: 471
- Watchers: 16
- Forks: 61
- Open Issues: 30
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Sharpnado.Tabs for MAUI and Xamarin.Forms
Get it from NuGet:
[![Nuget](https://img.shields.io/nuget/v/Sharpnado.Tabs.svg)](https://www.nuget.org/packages/Sharpnado.Tabs)
[![Nuget](https://img.shields.io/nuget/v/Sharpnado.Tabs.Maui.svg)](https://www.nuget.org/packages/Sharpnado.Tabs.Maui)
| Supported MAUI platforms | Supported XF platforms |
|----------------------------|----------------------------|
| :heavy_check_mark: Android |:heavy_check_mark: Android |
| :heavy_check_mark: iOS |:heavy_check_mark: iOS |
| :question: Windows |:heavy_check_mark: UWP |
| :question: 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
```csharp
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.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](https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/custom-namespace-schemas)), you need to call tabs and shadows initializers from the `App.xaml.cs` file like this:
```csharp
public App()
{
InitializeComponent();Sharpnado.Tabs.Initializer.Initialize(false, false);
Sharpnado.Shades.Initializer.Initialize(loggerEnable: false);
...
}
```* Mandatory initializations on iOS:
```csharp
Xamarin.Forms.Forms.Init();
Sharpnado.Tabs.iOS.Preserver.Preserve();
```* Mandatory initializations on UWP:
```csharp
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).
https://user-images.githubusercontent.com/596903/193819937-eecca609-b0c0-4705-92d2-e52a24803f8d.mp4
All you have is wrap your view in a `DelayedView` inside your `ViewSwitcher`, or even anywhere in your app.
```xml
```
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](https://github.com/roubachof/Sharpnado.Shadows) repo.
## UnderlinedTabItem with ViewSwitcher
Let's consider this view:
And let's have a look at its code:
```xml
```
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
```csharp
public TaskLoaderNotifier 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 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 :)
```xml
<Setter Property="SelectedTabColor" Value="{StaticResource AccentColor}" />
<Setter Property="FontFamily" Value="{StaticResource FontSemiBold}" />
<Setter Property="LabelSize" Value="14" />
<Setter Property="UnselectedLabelColor" Value="White" />
```
## BottomTabItem with Neumorphism and corner radius
And let's have a look at its xaml:
```xml
```
*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
```xml
<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" />
```
## Scrollable tabs
A new Property `TabType` was added to the `TabHostView`:
```csharp
public TabType TabTypepublic 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](Docs/material_tabs.png)
`IconOptions` values:
1. TopIcon
2. IconOnly
3. LeadingIcon
4. TextOnlyYou 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````xml
```
## Version 2.1: Vertical tabsContributor: @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.```xml
```
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](Docs/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.
```xml
```
```xml
<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" />```
### Properties
IsSegmented
Enables segmentation thus clipping for theTabHostView
.
CornerRadius
Sets the corner radius for the view.
Only works ifIsSegmented
is set to true.
SegmentedOutlineColor
Sets the corner radius for the view.
Only works ifIsSegmented
is set to true.
SegmentedHasSeparator
Sets a separator between each tab item, the color is given by theSegmentedOutlineColor
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:
```csharp
public string IconImageSourcepublic 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:
```xml
```
So just a bit of translation and scale here.
You can also decide to have a more boring button, why not?
```xml
```
## 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*
```xml
```
### Badges on UnderlinedTabItem
*SillyDudePage.xml from the Silly! app*
```xml
```### 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.
```xml
...
...```
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.**```csharp
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;
});
}
```