├── README.md ├── SampleApp ├── ExtendedShellTabBarSample │ ├── AssemblyInfo.cs │ ├── Models │ │ └── Item.cs │ ├── Views │ │ ├── AboutPage.xaml.cs │ │ ├── ItemDetailPage.xaml.cs │ │ ├── NewItemPage.xaml.cs │ │ ├── LoginPage.xaml.cs │ │ ├── ItemDetailPage.xaml │ │ ├── LoginPage.xaml │ │ ├── ItemsPage.xaml.cs │ │ ├── NewItemPage.xaml │ │ ├── ItemsPage.xaml │ │ └── AboutPage.xaml │ ├── Services │ │ ├── IDataStore.cs │ │ └── MockDataStore.cs │ ├── ExtendedShellTabBarSample.csproj │ ├── ViewModels │ │ ├── AboutViewModel.cs │ │ ├── AppShellViewModel.cs │ │ ├── LoginViewModel.cs │ │ ├── ItemDetailViewModel.cs │ │ ├── BaseViewModel.cs │ │ ├── NewItemViewModel.cs │ │ └── ItemsViewModel.cs │ ├── AppShell.xaml.cs │ ├── App.xaml.cs │ ├── GettingStarted.txt │ ├── App.xaml │ └── AppShell.xaml ├── ExtendedShellTabBarSample.iOS │ ├── Resources │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── icon_about.png │ │ ├── icon_feed.png │ │ ├── icon_about@2x.png │ │ ├── icon_about@3x.png │ │ ├── icon_feed@2x.png │ │ ├── icon_feed@3x.png │ │ ├── xamarin_logo.png │ │ ├── Default-568h@2x.png │ │ ├── xamarin_logo@2x.png │ │ ├── xamarin_logo@3x.png │ │ ├── Default-Portrait.png │ │ ├── Default-Portrait@2x.png │ │ └── LaunchScreen.storyboard │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Icon1024.png │ │ │ ├── Icon120.png │ │ │ ├── Icon152.png │ │ │ ├── Icon167.png │ │ │ ├── Icon180.png │ │ │ ├── Icon20.png │ │ │ ├── Icon29.png │ │ │ ├── Icon40.png │ │ │ ├── Icon58.png │ │ │ ├── Icon60.png │ │ │ ├── Icon76.png │ │ │ ├── Icon80.png │ │ │ ├── Icon87.png │ │ │ └── Contents.json │ │ └── centeredadd.imageset │ │ │ ├── centeredadd.png │ │ │ ├── centeredadd@2x.png │ │ │ ├── centeredadd@3x.png │ │ │ └── Contents.json │ ├── Entitlements.plist │ ├── Main.cs │ ├── AppDelegate.cs │ ├── Info.plist │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ExtendedShellTabBarSample.iOS.csproj ├── ExtendedShellTabBarSample.Android │ ├── Resources │ │ ├── mipmap-hdpi │ │ │ ├── icon.png │ │ │ └── launcher_foreground.png │ │ ├── mipmap-mdpi │ │ │ ├── icon.png │ │ │ └── launcher_foreground.png │ │ ├── drawable │ │ │ ├── icon_about.png │ │ │ ├── icon_feed.png │ │ │ └── xamarin_logo.png │ │ ├── mipmap-xhdpi │ │ │ ├── icon.png │ │ │ └── launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ │ ├── icon.png │ │ │ └── launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── icon.png │ │ │ └── launcher_foreground.png │ │ ├── drawable-hdpi │ │ │ └── centeredadd.png │ │ ├── drawable-ldpi │ │ │ └── centeredadd.png │ │ ├── drawable-mdpi │ │ │ └── centeredadd.png │ │ ├── drawable-xhdpi │ │ │ └── centeredadd.png │ │ ├── drawable-xxhdpi │ │ │ └── centeredadd.png │ │ ├── drawable-xxxhdpi │ │ │ └── centeredadd.png │ │ ├── mipmap-anydpi-v26 │ │ │ ├── icon.xml │ │ │ └── icon_round.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ └── AboutResources.txt │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Assets │ │ └── AboutAssets.txt │ ├── MainActivity.cs │ └── ExtendedShellTabBarSample.Android.csproj ├── ExtendedShellTabBarSample.sln └── .gitignore ├── Sources ├── ExtendedShellTabBar │ ├── images │ │ └── icon.png │ ├── Renderers │ │ ├── ExtendedShellRenderer.ios.cs │ │ ├── ExtendedShellRenderer.android.cs │ │ ├── ExtendedShellItemRenderer.ios.cs │ │ └── ExtendedShellItemRenderer.android.cs │ ├── Enums │ │ └── CornerTransformType.shared.cs │ ├── VisualElements │ │ ├── ExtendedShellTabBar.shared.cs │ │ └── ExtendedShellCenteredTab.shared.cs │ ├── license │ │ └── license.txt │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Controls │ │ └── ExtendedButton.android.cs │ ├── Extensions │ │ ├── ImageSourceExtensions.ios.cs │ │ └── ImageSourceExtensions.android.cs │ └── ExtendedShellTabBar.csproj └── ExtendedShellTabBar.sln ├── LICENSE └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # ExtendedShellTabBar 2 | Add a centered action button 3 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using Xamarin.Forms.Xaml; 2 | 3 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)] -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/Sources/ExtendedShellTabBar/images/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_about@3x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/icon_feed@3x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/xamarin_logo@3x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-Portrait.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-hdpi/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-mdpi/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Resources/Default-Portrait@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/icon_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/icon_about.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/icon_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/icon_feed.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xhdpi/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxhdpi/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxxhdpi/icon.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/xamarin_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable/xamarin_logo.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-hdpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-hdpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-ldpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-ldpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-mdpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-mdpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xhdpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xhdpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xxhdpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xxhdpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xxxhdpi/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/drawable-xxxhdpi/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-hdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-hdpi/launcher_foreground.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-mdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-mdpi/launcher_foreground.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd@2x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maui-plaroche/ExtendedShellTabBar/HEAD/SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/centeredadd@3x.png -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Models/Item.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ExtendedShellTabBarSample.Models 4 | { 5 | public class Item 6 | { 7 | public string Id { get; set; } 8 | public string Text { get; set; } 9 | public string Description { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-anydpi-v26/icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/mipmap-anydpi-v26/icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #3F51B5 5 | #303F9F 6 | #FF4081 7 | 8 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/AboutPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Xaml; 5 | 6 | namespace ExtendedShellTabBarSample.Views 7 | { 8 | public partial class AboutPage : ContentPage 9 | { 10 | public AboutPage() 11 | { 12 | InitializeComponent(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/ItemDetailPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Xamarin.Forms; 3 | using ExtendedShellTabBarSample.ViewModels; 4 | 5 | namespace ExtendedShellTabBarSample.Views 6 | { 7 | public partial class ItemDetailPage : ContentPage 8 | { 9 | public ItemDetailPage() 10 | { 11 | InitializeComponent(); 12 | BindingContext = new ItemDetailViewModel(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Services/IDataStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace ExtendedShellTabBarSample.Services 6 | { 7 | public interface IDataStore 8 | { 9 | Task AddItemAsync(T item); 10 | Task UpdateItemAsync(T item); 11 | Task DeleteItemAsync(string id); 12 | Task GetItemAsync(string id); 13 | Task> GetItemsAsync(bool forceRefresh = false); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ExtendedShellTabBarSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Assets.xcassets/centeredadd.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "centeredadd@3x.png", 5 | "scale": "3x", 6 | "idiom": "universal" 7 | }, 8 | { 9 | "filename": "centeredadd@2x.png", 10 | "scale": "2x", 11 | "idiom": "universal" 12 | }, 13 | { 14 | "filename": "centeredadd.png", 15 | "scale": "1x", 16 | "idiom": "universal" 17 | } 18 | ], 19 | "info": { 20 | "version": 1, 21 | "author": "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/AboutViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Xamarin.Essentials; 4 | using Xamarin.Forms; 5 | 6 | namespace ExtendedShellTabBarSample.ViewModels 7 | { 8 | public class AboutViewModel : BaseViewModel 9 | { 10 | public AboutViewModel() 11 | { 12 | Title = "About"; 13 | OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamarin-quickstart")); 14 | } 15 | 16 | public ICommand OpenWebCommand { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Renderers/ExtendedShellRenderer.ios.cs: -------------------------------------------------------------------------------- 1 | using ExtendedShellTabBar.Renderers.iOS; 2 | using Xamarin.Forms; 3 | using Xamarin.Forms.Platform.iOS; 4 | 5 | [assembly: ExportRenderer(typeof(Shell), typeof(ExtendedShellRenderer))] 6 | namespace ExtendedShellTabBar.Renderers.iOS 7 | { 8 | public class ExtendedShellRenderer : ShellRenderer 9 | { 10 | protected override IShellItemRenderer CreateShellItemRenderer(ShellItem item) 11 | { 12 | return new ExtendedShellItemRenderer(this) { ShellItem = item }; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Foundation; 6 | using UIKit; 7 | 8 | namespace ExtendedShellTabBarSample.iOS 9 | { 10 | public class Application 11 | { 12 | // This is the main entry point of the application. 13 | static void Main(string[] args) 14 | { 15 | // if you want to use a different Application Delegate class from "AppDelegate" 16 | // you can specify it here. 17 | UIApplication.Main(args, null, "AppDelegate"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/AppShellViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | using Xamarin.Forms; 4 | 5 | namespace ExtendedShellTabBarSample.ViewModels 6 | { 7 | public class AppShellViewModel 8 | { 9 | public ICommand ClickCommand { get; set; } 10 | 11 | public AppShellViewModel() 12 | { 13 | 14 | ClickCommand = new Command(async () => 15 | { 16 | await Application.Current.MainPage.DisplayAlert("Click !", "You click the centered button inside the TabBar", "OK"); 17 | }); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/NewItemPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using Xamarin.Forms; 5 | using Xamarin.Forms.Xaml; 6 | 7 | using ExtendedShellTabBarSample.Models; 8 | using ExtendedShellTabBarSample.ViewModels; 9 | 10 | namespace ExtendedShellTabBarSample.Views 11 | { 12 | public partial class NewItemPage : ContentPage 13 | { 14 | public Item Item { get; set; } 15 | 16 | public NewItemPage() 17 | { 18 | InitializeComponent(); 19 | BindingContext = new NewItemViewModel(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/LoginPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ExtendedShellTabBarSample.ViewModels; 7 | using Xamarin.Forms; 8 | using Xamarin.Forms.Xaml; 9 | 10 | namespace ExtendedShellTabBarSample.Views 11 | { 12 | [XamlCompilation(XamlCompilationOptions.Compile)] 13 | public partial class LoginPage : ContentPage 14 | { 15 | public LoginPage() 16 | { 17 | InitializeComponent(); 18 | this.BindingContext = new LoginViewModel(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Enums/CornerTransformType.shared.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | namespace ExtendedShellTabBar.Enums 3 | { 4 | [Flags] 5 | public enum CornerTransformType 6 | { 7 | TopLeftRounded = 0x10, 8 | TopRightRounded = 0x20, 9 | BottomLeftRounded = 0x40, 10 | BottomRightRounded = 0x80, 11 | 12 | AllRounded = TopLeftRounded | TopRightRounded | BottomLeftRounded | BottomRightRounded, 13 | LeftRounded = TopLeftRounded | BottomLeftRounded, 14 | RightRounded = TopRightRounded | BottomRightRounded, 15 | TopRounded = TopLeftRounded | TopRightRounded, 16 | BottomRounded = BottomLeftRounded | BottomRightRounded, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/ItemDetailPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using ExtendedShellTabBarSample.ViewModels; 4 | using ExtendedShellTabBarSample.Views; 5 | using Xamarin.Forms; 6 | 7 | namespace ExtendedShellTabBarSample 8 | { 9 | public partial class AppShell : Xamarin.Forms.Shell 10 | { 11 | public AppShell() 12 | { 13 | InitializeComponent(); 14 | 15 | this.BindingContext = new AppShellViewModel(); 16 | 17 | Routing.RegisterRoute(nameof(ItemDetailPage), typeof(ItemDetailPage)); 18 | Routing.RegisterRoute(nameof(NewItemPage), typeof(NewItemPage)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Renderers/ExtendedShellRenderer.android.cs: -------------------------------------------------------------------------------- 1 | using Android.Content; 2 | using ExtendedShellTabBar.Renderers; 3 | using Xamarin.Forms; 4 | using Xamarin.Forms.Platform.Android; 5 | 6 | [assembly: ExportRenderer(typeof(Shell), typeof(ExtendedShellRenderer))] 7 | namespace ExtendedShellTabBar.Renderers 8 | { 9 | public class ExtendedShellRenderer : ShellRenderer 10 | { 11 | public ExtendedShellRenderer(Context context) : base(context) 12 | { 13 | } 14 | 15 | protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem) 16 | { 17 | return new ExtendedShellItemRenderer(this); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xamarin.Forms; 3 | using Xamarin.Forms.Xaml; 4 | using ExtendedShellTabBarSample.Services; 5 | using ExtendedShellTabBarSample.Views; 6 | 7 | namespace ExtendedShellTabBarSample 8 | { 9 | public partial class App : Application 10 | { 11 | 12 | public App() 13 | { 14 | InitializeComponent(); 15 | 16 | DependencyService.Register(); 17 | MainPage = new AppShell(); 18 | } 19 | 20 | protected override void OnStart() 21 | { 22 | } 23 | 24 | protected override void OnSleep() 25 | { 26 | } 27 | 28 | protected override void OnResume() 29 | { 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/LoginPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Android.App; 4 | using Android.Content.PM; 5 | using Android.Runtime; 6 | using Android.OS; 7 | 8 | namespace ExtendedShellTabBarSample.Droid 9 | { 10 | [Activity(Label = "ExtendedShellTabBarSample", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)] 11 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 12 | { 13 | protected override void OnCreate(Bundle savedInstanceState) 14 | { 15 | base.OnCreate(savedInstanceState); 16 | 17 | Xamarin.Essentials.Platform.Init(this, savedInstanceState); 18 | global::Xamarin.Forms.Forms.Init(this, savedInstanceState); 19 | LoadApplication(new App()); 20 | } 21 | public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) 22 | { 23 | Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); 24 | 25 | base.OnRequestPermissionsResult(requestCode, permissions, grantResults); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/GettingStarted.txt: -------------------------------------------------------------------------------- 1 | Welcome to Xamarin.Forms! Here are some tips to get started building your app. 2 | 3 | Building Your App UI 4 | -------------------- 5 | 6 | XAML Hot Reload quickly applies UI changes as you make them to your running app. 7 | This is the most productive way to preview and iteratively create your UI. 8 | 9 | Try it out: 10 | 11 | 1. Run the app by clicking the Start Debugging (play) button in the above toolbar. 12 | 2. Open \Views\AboutPage.xaml. 13 | Don't stop the app - keep it running while making changes. 14 | 3. Change something! Hint: change the Accent color on line 14 from "#96d1ff" to "Pink". 15 | 4. Watch the About screen update on the device or emulator, with the logo background now pink. 16 | 17 | Keep going and try more changes! 18 | 19 | QuickStart Guide 20 | ---------------- 21 | 22 | Learn more of the fundamentals for building apps with Xamarin here: https://aka.ms/xamarin-quickstart 23 | 24 | Your App Shell 25 | -------------- 26 | 27 | This template uses Shell, an app container that reduces the complexity of your apps by providing fundamental features including: 28 | 29 | - A single place to describe the app's visual hierarchy. 30 | - Common navigation such as a flyout menu and tabs. 31 | - A URI-based navigation scheme that permits navigation to any page in the application. 32 | - An integrated search handler. 33 | 34 | Open AppShell.xaml to begin exploring. To learn more about Shell visit: https://docs.microsoft.com/xamarin/xamarin-forms/app-fundamentals/shell/introduction 35 | -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ExtendedShellTabBar")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ExtendedShellTabBar")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UISupportedInterfaceOrientations 11 | 12 | UIInterfaceOrientationPortrait 13 | UIInterfaceOrientationLandscapeLeft 14 | UIInterfaceOrientationLandscapeRight 15 | 16 | UISupportedInterfaceOrientations~ipad 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationPortraitUpsideDown 20 | UIInterfaceOrientationLandscapeLeft 21 | UIInterfaceOrientationLandscapeRight 22 | 23 | MinimumOSVersion 24 | 8.0 25 | CFBundleDisplayName 26 | ExtendedShellTabBarSample 27 | CFBundleIdentifier 28 | com.mobile-concept.extendedshelltabbar.ExtendedShellTabBarSample 29 | CFBundleVersion 30 | 1.0 31 | UILaunchStoryboardName 32 | LaunchScreen 33 | CFBundleName 34 | ExtendedShellTabBarSample 35 | XSAppIconAssets 36 | Assets.xcassets/AppIcon.appiconset 37 | 38 | 39 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ExtendedShellTabBarSample.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ExtendedShellTabBarSample.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/ItemDetailViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Threading.Tasks; 4 | using ExtendedShellTabBarSample.Models; 5 | using Xamarin.Forms; 6 | 7 | namespace ExtendedShellTabBarSample.ViewModels 8 | { 9 | [QueryProperty(nameof(ItemId), nameof(ItemId))] 10 | public class ItemDetailViewModel : BaseViewModel 11 | { 12 | private string itemId; 13 | private string text; 14 | private string description; 15 | public string Id { get; set; } 16 | 17 | public string Text 18 | { 19 | get => text; 20 | set => SetProperty(ref text, value); 21 | } 22 | 23 | public string Description 24 | { 25 | get => description; 26 | set => SetProperty(ref description, value); 27 | } 28 | 29 | public string ItemId 30 | { 31 | get 32 | { 33 | return itemId; 34 | } 35 | set 36 | { 37 | itemId = value; 38 | LoadItemId(value); 39 | } 40 | } 41 | 42 | public async void LoadItemId(string itemId) 43 | { 44 | try 45 | { 46 | var item = await DataStore.GetItemAsync(itemId); 47 | Id = item.Id; 48 | Text = item.Text; 49 | Description = item.Description; 50 | } 51 | catch (Exception) 52 | { 53 | Debug.WriteLine("Failed to Load Item"); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 10 | #2196F3 11 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Controls/ExtendedButton.android.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using Android.Content; 4 | using Android.Graphics; 5 | using Android.Widget; 6 | using static Android.Graphics.Paint; 7 | using static Android.Graphics.PorterDuff; 8 | using Color = Android.Graphics.Color; 9 | 10 | namespace ExtendedShellTabBar.Controls.Droid 11 | { 12 | public class ExtendedButton : Button 13 | { 14 | public Android.Graphics.Color BorderColor { get; set; } 15 | public int BorderThickness { get; set; } 16 | public float CornerRadius { get; set; } 17 | 18 | public ExtendedButton(Context context) : base(context) 19 | { 20 | } 21 | 22 | protected override void OnDraw(Canvas canvas) 23 | { 24 | 25 | if (CornerRadius > 0) 26 | { 27 | Rect rc = new Rect(); 28 | GetDrawingRect(rc); 29 | 30 | Rect interior = rc; 31 | interior.Inset((int)BorderThickness, (int)BorderThickness); 32 | 33 | Paint p = new Paint() 34 | { 35 | Color = Color.Transparent, 36 | AntiAlias = true, 37 | }; 38 | 39 | canvas.DrawRoundRect(new RectF(interior), (float)CornerRadius, (float)CornerRadius, p); 40 | 41 | p.Color = BorderColor; 42 | p.StrokeWidth = (float)BorderThickness; 43 | p.SetStyle(Style.Stroke); 44 | 45 | canvas.DrawRoundRect(new RectF(rc), (float)CornerRadius, (float)CornerRadius, p); 46 | 47 | canvas.ClipRect(interior); 48 | } 49 | else 50 | { 51 | base.OnDraw(canvas); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Extensions/ImageSourceExtensions.ios.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using UIKit; 5 | using Xamarin.Forms; 6 | using Xamarin.Forms.Internals; 7 | using Xamarin.Forms.Platform.iOS; 8 | 9 | namespace ExtendedShellTabBar.Extensions.iOS 10 | { 11 | public static class ImageSourceExtensions 12 | { 13 | public static IImageSourceHandler GetHandler(this ImageSource source) 14 | { 15 | //Image source handler to return 16 | IImageSourceHandler returnValue = null; 17 | //check the specific source type and return the correct image source handler 18 | if (source is UriImageSource) 19 | { 20 | returnValue = new ImageLoaderSourceHandler(); 21 | } 22 | else if (source is FileImageSource) 23 | { 24 | returnValue = new FileImageSourceHandler(); 25 | } 26 | else if (source is StreamImageSource) 27 | { 28 | returnValue = new StreamImagesourceHandler(); 29 | } 30 | return returnValue; 31 | } 32 | 33 | public static async Task GetNativeImageAsync(this ImageSource source, CancellationToken cancellationToken = default(CancellationToken)) 34 | { 35 | if (source == null || source.IsEmpty) 36 | return null; 37 | 38 | var handler = source.GetHandler(); 39 | if (handler == null) 40 | return null; 41 | 42 | try 43 | { 44 | float scale = (float)UIScreen.MainScreen.Scale; 45 | return await handler.LoadImageAsync(source, scale: scale, cancelationToken: cancellationToken); 46 | } 47 | catch (OperationCanceledException) 48 | { 49 | Log.Warning("Image loading", "Image load cancelled"); 50 | } 51 | catch (Exception ex) 52 | { 53 | Log.Warning("Image loading", $"Image load failed: {ex}"); 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/BaseViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Runtime.CompilerServices; 5 | 6 | using Xamarin.Forms; 7 | 8 | using ExtendedShellTabBarSample.Models; 9 | using ExtendedShellTabBarSample.Services; 10 | 11 | namespace ExtendedShellTabBarSample.ViewModels 12 | { 13 | public class BaseViewModel : INotifyPropertyChanged 14 | { 15 | public IDataStore DataStore => DependencyService.Get>(); 16 | 17 | bool isBusy = false; 18 | public bool IsBusy 19 | { 20 | get { return isBusy; } 21 | set { SetProperty(ref isBusy, value); } 22 | } 23 | 24 | string title = string.Empty; 25 | public string Title 26 | { 27 | get { return title; } 28 | set { SetProperty(ref title, value); } 29 | } 30 | 31 | protected bool SetProperty(ref T backingStore, T value, 32 | [CallerMemberName] string propertyName = "", 33 | Action onChanged = null) 34 | { 35 | if (EqualityComparer.Default.Equals(backingStore, value)) 36 | return false; 37 | 38 | backingStore = value; 39 | onChanged?.Invoke(); 40 | OnPropertyChanged(propertyName); 41 | return true; 42 | } 43 | 44 | #region INotifyPropertyChanged 45 | public event PropertyChangedEventHandler PropertyChanged; 46 | protected void OnPropertyChanged([CallerMemberName] string propertyName = "") 47 | { 48 | var changed = PropertyChanged; 49 | if (changed == null) 50 | return; 51 | 52 | changed.Invoke(this, new PropertyChangedEventArgs(propertyName)); 53 | } 54 | #endregion 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample.Android/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.xml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/NewItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Input; 5 | using ExtendedShellTabBarSample.Models; 6 | using Xamarin.Forms; 7 | 8 | namespace ExtendedShellTabBarSample.ViewModels 9 | { 10 | public class NewItemViewModel : BaseViewModel 11 | { 12 | private string text; 13 | private string description; 14 | 15 | public NewItemViewModel() 16 | { 17 | SaveCommand = new Command(OnSave, ValidateSave); 18 | CancelCommand = new Command(OnCancel); 19 | this.PropertyChanged += 20 | (_, __) => SaveCommand.ChangeCanExecute(); 21 | } 22 | 23 | private bool ValidateSave() 24 | { 25 | return !String.IsNullOrWhiteSpace(text) 26 | && !String.IsNullOrWhiteSpace(description); 27 | } 28 | 29 | public string Text 30 | { 31 | get => text; 32 | set => SetProperty(ref text, value); 33 | } 34 | 35 | public string Description 36 | { 37 | get => description; 38 | set => SetProperty(ref description, value); 39 | } 40 | 41 | public Command SaveCommand { get; } 42 | public Command CancelCommand { get; } 43 | 44 | private async void OnCancel() 45 | { 46 | // This will pop the current page off the navigation stack 47 | await Shell.Current.GoToAsync(".."); 48 | } 49 | 50 | private async void OnSave() 51 | { 52 | Item newItem = new Item() 53 | { 54 | Id = Guid.NewGuid().ToString(), 55 | Text = Text, 56 | Description = Description 57 | }; 58 | 59 | await DataStore.AddItemAsync(newItem); 60 | 61 | // This will pop the current page off the navigation stack 62 | await Shell.Current.GoToAsync(".."); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/ExtendedShellTabBar/Renderers/ExtendedShellItemRenderer.ios.cs: -------------------------------------------------------------------------------- 1 | using CoreGraphics; 2 | using ExtendedShellTabBar.Extensions.iOS; 3 | using UIKit; 4 | using Xamarin.Forms.Platform.iOS; 5 | 6 | namespace ExtendedShellTabBar.Renderers.iOS 7 | { 8 | /* 9 | * ShellItemRenderer is UITabBarController 10 | * */ 11 | public class ExtendedShellItemRenderer : ShellItemRenderer 12 | { 13 | IShellContext _context; 14 | 15 | public ExtendedShellItemRenderer(IShellContext context) : base(context) 16 | { 17 | _context = context; 18 | } 19 | 20 | public override async void ViewWillLayoutSubviews() 21 | { 22 | base.ViewWillLayoutSubviews(); 23 | 24 | if (ShellItem != null && ShellItem is VisualElements.ExtendedShellTabBar) 25 | { 26 | var tabbar = (VisualElements.ExtendedShellTabBar)ShellItem; 27 | 28 | var centeredTab = tabbar.CenteredTab; 29 | 30 | if (centeredTab != null && centeredTab.Icon != null) 31 | { 32 | var x = (TabBar.Frame.Width - centeredTab.Width) / 2; 33 | var y = TabBar.Frame.Y - centeredTab.Height / 2; 34 | var imgView = new UIImageView(new CGRect(x, y, centeredTab.Width, centeredTab.Height)); 35 | 36 | var image = await centeredTab.Icon.GetNativeImageAsync(); 37 | imgView.Image = image; 38 | imgView.ClipsToBounds = true; 39 | imgView.Layer.CornerRadius = centeredTab.CornerRadius; 40 | imgView.Layer.BorderColor = centeredTab.BorderColor.ToCGColor(); 41 | imgView.Layer.BorderWidth = centeredTab.BorderThickness; 42 | imgView.UserInteractionEnabled = true; 43 | 44 | if (centeredTab.Command != null) 45 | { 46 | imgView.AddGestureRecognizer(new UITapGestureRecognizer(TapGesture)); 47 | } 48 | 49 | Add(imgView); 50 | } 51 | } 52 | } 53 | 54 | private void TapGesture() 55 | { 56 | var tabbar = (VisualElements.ExtendedShellTabBar)ShellItem; 57 | var centeredTab = tabbar.CenteredTab; 58 | centeredTab?.Command?.Execute(centeredTab); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Services/MockDataStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ExtendedShellTabBarSample.Models; 6 | 7 | namespace ExtendedShellTabBarSample.Services 8 | { 9 | public class MockDataStore : IDataStore 10 | { 11 | readonly List items; 12 | 13 | public MockDataStore() 14 | { 15 | items = new List() 16 | { 17 | new Item { Id = Guid.NewGuid().ToString(), Text = "First item", Description="This is an item description." }, 18 | new Item { Id = Guid.NewGuid().ToString(), Text = "Second item", Description="This is an item description." }, 19 | new Item { Id = Guid.NewGuid().ToString(), Text = "Third item", Description="This is an item description." }, 20 | new Item { Id = Guid.NewGuid().ToString(), Text = "Fourth item", Description="This is an item description." }, 21 | new Item { Id = Guid.NewGuid().ToString(), Text = "Fifth item", Description="This is an item description." }, 22 | new Item { Id = Guid.NewGuid().ToString(), Text = "Sixth item", Description="This is an item description." } 23 | }; 24 | } 25 | 26 | public async Task AddItemAsync(Item item) 27 | { 28 | items.Add(item); 29 | 30 | return await Task.FromResult(true); 31 | } 32 | 33 | public async Task UpdateItemAsync(Item item) 34 | { 35 | var oldItem = items.Where((Item arg) => arg.Id == item.Id).FirstOrDefault(); 36 | items.Remove(oldItem); 37 | items.Add(item); 38 | 39 | return await Task.FromResult(true); 40 | } 41 | 42 | public async Task DeleteItemAsync(string id) 43 | { 44 | var oldItem = items.Where((Item arg) => arg.Id == id).FirstOrDefault(); 45 | items.Remove(oldItem); 46 | 47 | return await Task.FromResult(true); 48 | } 49 | 50 | public async Task GetItemAsync(string id) 51 | { 52 | return await Task.FromResult(items.FirstOrDefault(s => s.Id == id)); 53 | } 54 | 55 | public async Task> GetItemsAsync(bool forceRefresh = false) 56 | { 57 | return await Task.FromResult(items); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/ItemsPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 21 | 22 | 23 | 24 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/ViewModels/ItemsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.Diagnostics; 4 | using System.Threading.Tasks; 5 | 6 | using Xamarin.Forms; 7 | 8 | using ExtendedShellTabBarSample.Models; 9 | using ExtendedShellTabBarSample.Views; 10 | 11 | namespace ExtendedShellTabBarSample.ViewModels 12 | { 13 | public class ItemsViewModel : BaseViewModel 14 | { 15 | private Item _selectedItem; 16 | 17 | public ObservableCollection Items { get; } 18 | public Command LoadItemsCommand { get; } 19 | public Command AddItemCommand { get; } 20 | public Command ItemTapped { get; } 21 | 22 | public ItemsViewModel() 23 | { 24 | Title = "Browse"; 25 | Items = new ObservableCollection(); 26 | LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand()); 27 | 28 | ItemTapped = new Command(OnItemSelected); 29 | 30 | AddItemCommand = new Command(OnAddItem); 31 | } 32 | 33 | async Task ExecuteLoadItemsCommand() 34 | { 35 | IsBusy = true; 36 | 37 | try 38 | { 39 | Items.Clear(); 40 | var items = await DataStore.GetItemsAsync(true); 41 | foreach (var item in items) 42 | { 43 | Items.Add(item); 44 | } 45 | } 46 | catch (Exception ex) 47 | { 48 | Debug.WriteLine(ex); 49 | } 50 | finally 51 | { 52 | IsBusy = false; 53 | } 54 | } 55 | 56 | public void OnAppearing() 57 | { 58 | IsBusy = true; 59 | SelectedItem = null; 60 | } 61 | 62 | public Item SelectedItem 63 | { 64 | get => _selectedItem; 65 | set 66 | { 67 | SetProperty(ref _selectedItem, value); 68 | OnItemSelected(value); 69 | } 70 | } 71 | 72 | private async void OnAddItem(object obj) 73 | { 74 | await Shell.Current.GoToAsync(nameof(NewItemPage)); 75 | } 76 | 77 | async void OnItemSelected(Item item) 78 | { 79 | if (item == null) 80 | return; 81 | 82 | // This will push the ItemDetailPage onto the navigation stack 83 | await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?{nameof(ItemDetailViewModel.ItemId)}={item.Id}"); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /SampleApp/ExtendedShellTabBarSample/Views/AboutPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | #96d1ff 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |