Skip to content

Commit

Permalink
MAUI sample is done and ready to launch!
Browse files Browse the repository at this point in the history
  • Loading branch information
roubachof committed Oct 4, 2022
1 parent d00ba4f commit 5ff429b
Show file tree
Hide file tree
Showing 33 changed files with 623 additions and 115 deletions.
Binary file added Docs/MAUI/A_android.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/A_ios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/M_android.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/M_ios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/U_android.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/U_ios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/MAUI/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Docs/logo_maui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 14 additions & 27 deletions Maui.Tabs/BadgeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ public class BadgeView : Border
nameof(BadgePadding),
typeof(Thickness),
typeof(BadgeView),
defaultValueCreator: (b) => new Thickness(6, 2));
defaultValueCreator:
#if __ANDROID__
(b) => new Thickness(5, 2));
#else
(b) => new Thickness(4, 2));
#endif

public static readonly BindableProperty ShowIndicatorProperty = BindableProperty.Create(
nameof(ShowIndicator),
Expand All @@ -48,8 +53,6 @@ public class BadgeView : Border

public BadgeView()
{
_paddingInternalChange = true;
Padding = new Thickness(6, 2);
Margin = new Thickness(0, 4, 0, 0);

BackgroundColor = Colors.Red;
Expand All @@ -60,7 +63,11 @@ public BadgeView()
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
#if __ANDROID__
Margin = new Thickness(0, -1.5, 0, 0),
#else
Margin = new Thickness(0, -1, 0, 0),
#endif
BindingContext = this,
};

Expand Down Expand Up @@ -169,35 +176,15 @@ private void Update()

if (ShowIndicator)
{
double margin = (TextSize + BadgePadding.VerticalThickness) / 2;

TranslationX = HorizontalOptions.Alignment switch
{
LayoutAlignment.Start => margin,
LayoutAlignment.End => -margin,
_ => 0,
};

TranslationY = VerticalOptions.Alignment switch
{
LayoutAlignment.Start => margin,
LayoutAlignment.End => -margin,
_ => 0,
};

HeightRequest = 10;
WidthRequest = 10;
StrokeShape = new RoundRectangle { CornerRadius = new CornerRadius(5) };
return;
}
else
{
TranslationX = 0;
TranslationY = 0;
WidthRequest = -1;
HeightRequest = -1;
UpdateCornerRadius();
}

WidthRequest = -1;
HeightRequest = -1;
UpdateCornerRadius();

_paddingInternalChange = true;
Padding = BadgePadding;
Expand Down
57 changes: 31 additions & 26 deletions Maui.Tabs/MaterialUnderlinedTabItem.xaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>

<tabs:UnderlinedTabItemBase x:Class="Sharpnado.Tabs.MaterialUnderlinedTabItem"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:tabs="clr-namespace:Sharpnado.Tabs"
x:Name="RootLayout">
<tabs:UnderlinedTabItemBase
x:Class="Sharpnado.Tabs.MaterialUnderlinedTabItem"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:tabs="clr-namespace:Sharpnado.Tabs"
x:Name="RootLayout">

<ContentView.Resources>
<ResourceDictionary>
Expand Down Expand Up @@ -43,29 +44,33 @@
<Grid x:Name="Grid" RowSpacing="0">

<StackLayout x:Name="MainLayout" Style="{StaticResource LayoutIconWithText}">
<Path x:Name="IconPath"
Style="{StaticResource TabIconPath}"
Data="{Binding Source={x:Reference RootLayout}, Path=GeometryIcon}" />
<Image x:Name="IconImage"
Style="{StaticResource TabIconImage}"
WidthRequest="{Binding Source={x:Reference RootLayout}, Path=IconSize}"
HeightRequest="{Binding Source={x:Reference RootLayout}, Path=IconSize}"
Source="{Binding Source={x:Reference RootLayout}, Path=IconImageSource}" />
<Label x:Name="InnerLabel"
Style="{StaticResource TabTextHeader}"
FontFamily="{Binding Source={x:Reference RootLayout}, Path=FontFamily}"
FontSize="{Binding Source={x:Reference RootLayout}, Path=LabelSize}"
Text="{Binding Source={x:Reference RootLayout}, Path=Label}" />
<Path
x:Name="IconPath"
Data="{Binding Source={x:Reference RootLayout}, Path=GeometryIcon}"
Style="{StaticResource TabIconPath}" />
<Image
x:Name="IconImage"
HeightRequest="{Binding Source={x:Reference RootLayout}, Path=IconSize}"
Source="{Binding Source={x:Reference RootLayout}, Path=IconImageSource}"
Style="{StaticResource TabIconImage}"
WidthRequest="{Binding Source={x:Reference RootLayout}, Path=IconSize}" />
<Label
x:Name="InnerLabel"
FontFamily="{Binding Source={x:Reference RootLayout}, Path=FontFamily}"
FontSize="{Binding Source={x:Reference RootLayout}, Path=LabelSize}"
Style="{StaticResource TabTextHeader}"
Text="{Binding Source={x:Reference RootLayout}, Path=Label}" />
</StackLayout>
<BoxView x:Name="Underline"
HeightRequest="0"
HorizontalOptions="Center"
VerticalOptions="End"
BackgroundColor="Transparent">
<BoxView
x:Name="Underline"
HeightRequest="0"
HorizontalOptions="Center"
VerticalOptions="End">
<BoxView.Triggers>
<DataTrigger Binding="{Binding Source={x:Reference RootLayout}, Path=IsSelected}"
TargetType="BoxView"
Value="true">
<DataTrigger
Binding="{Binding Source={x:Reference RootLayout}, Path=IsSelected}"
TargetType="BoxView"
Value="true">
<Setter Property="HeightRequest" Value="{Binding Source={x:Reference RootLayout}, Path=UnderlineHeight}" />
</DataTrigger>
</BoxView.Triggers>
Expand Down
21 changes: 11 additions & 10 deletions Maui.Tabs/Maui.Tabs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@

<PropertyGroup>
<Product>$(AssemblyName) ($(TargetFramework))</Product>
<AssemblyVersion>2.3.0.0</AssemblyVersion>
<AssemblyFileVersion>2.3.0.0</AssemblyFileVersion>
<Version>2.3.0</Version>
<AssemblyVersion>3.0.0</AssemblyVersion>
<AssemblyFileVersion>3.0.0</AssemblyFileVersion>
<Version>3.0.0</Version>
<PackOnBuild>true</PackOnBuild>
<NeutralLanguage>en</NeutralLanguage>

Expand All @@ -37,15 +37,15 @@
<PackageId>Sharpnado.Tabs.Maui</PackageId>
<PackageProjectUrl>https://github.com/roubachof/Sharpnado.Tabs</PackageProjectUrl>
<RepositoryUrl>https://github.com/roubachof/Sharpnado.Tabs</RepositoryUrl>
<PackageIcon>images\logo_2_1.png</PackageIcon>
<PackageIcon>images\logo_maui.png</PackageIcon>
<PackageReadmeFile>docs\ReadMe.md</PackageReadmeFile>
<PackageTags>maui dotnetmaui xamarin.forms android ios uwp netstandard tabs segmented control bottombar fixed tabs scrollable tabs badge</PackageTags>

<PackageReleaseNotes>
First MAUI release \o/
</PackageReleaseNotes>

<Title>"Pure" MAUI Tabs (no renderers)</Title>
<Summary>Including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, ...</Summary>
<Summary>The Ultimate Tabs customization solution for .net MAUI, including fixed tabs, scrollable tabs, bottom tabs, badge, segmented control, custom tabs, button tabs, ...</Summary>
<Description>
Pure MAUI Tabs:
* Fixed tabs (android tabs style)
Expand All @@ -64,15 +64,15 @@

## Installation

* In Core project, in `App.xaml.cs`:
* In Core project, in `MauiProgram.cs`:

```csharp
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UseSharpnadoTabs();
.UseSharpnadoTabs(loggerEnabled: false);
}
```

Expand All @@ -88,11 +88,12 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<FileVersion>2.3.0.0</FileVersion>
<FileVersion>3.0.0</FileVersion>
</PropertyGroup>

<ItemGroup>
<None Include="..\Docs\logo_2_1.png" Pack="true" PackagePath="\images\" />
<None Include="..\Docs\logo_maui.png" Pack="true" PackagePath="\images\" />
<None Include="ReadMe.md" Pack="true" PackagePath="\docs\" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.iOS')) != true AND $(TargetFramework.StartsWith('net6.0-ios')) != true AND $(TargetFramework.StartsWith('net6.0-maccatalyst')) != true ">
Expand Down
2 changes: 1 addition & 1 deletion Maui.Tabs/Platforms/Android/TouchEffectPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected override void OnAttached() {

if (Container is not ViewGroup group)
{
throw new InvalidOperationException("Container must be a ViewGroup");
throw new InvalidOperationException("Touch color effect requires to be attached to a container like a ContentView or a layout (Grid, StackLayout, etc...)");
}

View.Clickable = true;
Expand Down
18 changes: 11 additions & 7 deletions Maui.Tabs/Platforms/iOS/TouchEffectPlatform.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
using System.ComponentModel;
using UIKit;
using Microsoft.Maui.Controls.Compatibility.Platform.iOS;

using Microsoft.Maui.Controls.Platform;

using Sharpnado.Tabs.Effects;
using Sharpnado.Tabs.Effects.iOS;
using ObjCRuntime;
using Sharpnado.Tabs.Effects.iOS.GestureCollectors;
using Sharpnado.Tabs.Effects.iOS.GestureRecognizers;
using UIKit;

namespace Sharpnado.Tabs.Effects.iOS {
public class TouchEffectPlatform : PlatformEffect {
public bool IsDisposed => (Container as IVisualElementRenderer)?.Element == null;
public class TouchEffectPlatform : PlatformEffect
{
public bool IsDisposed => Container == null || Container.Handle == NativeHandle.Zero;
public UIView View => Control ?? Container;

UIView _layer;
Expand Down Expand Up @@ -46,14 +44,17 @@ protected override void OnDetached() {
void OnTouch(TouchGestureRecognizer.TouchArgs e) {
switch (e.State) {
case TouchGestureRecognizer.TouchState.Started:
InternalLogger.Debug($"OnTouch Started");
BringLayer();
break;

case TouchGestureRecognizer.TouchState.Ended:
InternalLogger.Debug($"OnTouch Ended");
EndAnimation();
break;

case TouchGestureRecognizer.TouchState.Cancelled:
InternalLogger.Debug($"OnTouch Cancelled");
if (!IsDisposed && _layer != null) {
_layer.Layer.RemoveAllAnimations();
_layer.Alpha = 0;
Expand All @@ -77,18 +78,21 @@ void UpdateEffectColor() {
return;
}

InternalLogger.Debug($"UpdateEffectColor");
_alpha = color.Alpha < 1.0 ? 1 : (float)0.3;
_layer.BackgroundColor = color.ToUIColor();
}

void BringLayer() {
InternalLogger.Debug($"BringLayer");
_layer.Layer.RemoveAllAnimations();
_layer.Alpha = _alpha;
View.BringSubviewToFront(_layer);
}

void EndAnimation() {
if (!IsDisposed && _layer != null) {
InternalLogger.Debug($"EndAnimation");
_layer.Layer.RemoveAllAnimations();
UIView.Animate(0.225,
() => {
Expand Down
2 changes: 1 addition & 1 deletion Maui.Tabs/Platforms/iOS/TouchGestureRecognizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public override bool ShouldReceiveTouch(UIGestureRecognizer recognizer, UITouch
return false;
}

return touch.View == _view;
return touch.View.IsDescendantOfView(_view);
}
}
}
98 changes: 98 additions & 0 deletions Maui.Tabs/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Pure MAUI Tabs
* Fixed tabs (android tabs style)
* Scrollable tabs
* Vertical tabs
* Material design tabs (top and leading icon)
* Lazy and Delayed views
* Support for SVG images
* Segmented tabs
* Custom shadows (neumorphism ready)
* Badges on tabs
* Circle button in tab bar
* Bottom bar tabs (ios tabs style)
* Custom tabs (be creative just implement TabItem)
* Independent ViewSwitcher
* Bindable with ItemsSource

## Installation

* In Core project, in `MauiProgram.cs`:

```csharp
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UseSharpnadoTabs(loggerEnabled: false);
}
```

## Usage

First create a `TabHostView` which will contains all your tabs:

```xml
<tabs:TabHostView WidthRequest="250"
HeightRequest="60"
Padding="20,0"
HorizontalOptions="Center"
BackgroundColor="{StaticResource Gray900}"
CornerRadius="30"
IsSegmented="True"
Orientation="Horizontal"
SegmentedOutlineColor="{StaticResource Gray950}"
SelectedIndex="{Binding Source={x:Reference Switcher}, Path=SelectedIndex, Mode=TwoWay}"
TabType="Fixed">
<tabs:TabHostView.Shadow>
<Shadow Brush="{StaticResource Primary}"
Opacity="0.7"
Radius="30"
Offset="0,10" />
</tabs:TabHostView.Shadow>
<tabs:BottomTabItem Style="{StaticResource BottomTab}" Label="M" />
<tabs:BottomTabItem Style="{StaticResource BottomTab}" Label="A">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView BackgroundColor="{StaticResource Tertiary}" Text="new" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
<tabs:UnderlinedTabItem FontFamily="OpenSansExtraBold"
Label="U"
LabelSize="36"
SelectedTabColor="{StaticResource Primary}"
UnselectedLabelColor="{StaticResource White}" />
<tabs:BottomTabItem Style="{StaticResource BottomTab}"
Padding="0,0,10,0"
Label="I">
<tabs:BottomTabItem.Badge>
<tabs:BadgeView BackgroundColor="{StaticResource Tertiary}" Text="2" />
</tabs:BottomTabItem.Badge>
</tabs:BottomTabItem>
</tabs:TabHostView>
```


Then bind the `SelectedIndex` with a `ViewSwitcher` that will accordingly select your views.

```xml
<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>
```
Loading

0 comments on commit 5ff429b

Please sign in to comment.