using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; using JetBrains.Annotations; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace InABox.Mobile { public enum MobileTabStripItemLayout { TextOnly, ImageOnly, Vertical, Horizontal } public class MobileTabStripDataTemplateSelector : DataTemplateSelector { public MobileTabStripItemLayout SelectedLayout { get; set; } public DataTemplate VerticalTemplate { get; set; } public DataTemplate HorizontalTemplate { get; set; } public DataTemplate TextOnlyTemplate { get; set; } public DataTemplate ImageOnlyTemplate { get; set; } protected override DataTemplate OnSelectTemplate (object item, BindableObject container) { return SelectedLayout switch { MobileTabStripItemLayout.ImageOnly => ImageOnlyTemplate, MobileTabStripItemLayout.Vertical => VerticalTemplate, MobileTabStripItemLayout.Horizontal => HorizontalTemplate, _ => TextOnlyTemplate }; } } [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MobileTabStrip { public static readonly BindableProperty SelectedBackgroundProperty = BindableProperty.Create( nameof(SelectedBackground), typeof(Color), typeof(MobileTabStrip), XF.Material.Forms.Material.Color.Surface); public Color SelectedBackground { get => (Color)GetValue(SelectedBackgroundProperty); set => SetValue(SelectedBackgroundProperty, value); } public static readonly BindableProperty SelectedForegroundProperty = BindableProperty.Create( nameof(SelectedForeground), typeof(Color), typeof(MobileTabStrip), XF.Material.Forms.Material.Color.OnSurface); [TypeConverter(typeof(ColorTypeConverter))] public Color SelectedForeground { get => (Color)GetValue(SelectedForegroundProperty); set => SetValue(SelectedForegroundProperty, value); } public static readonly BindableProperty UnselectedBackgroundProperty = BindableProperty.Create( nameof(UnselectedBackground), typeof(Color), typeof(MobileTabStrip), XF.Material.Forms.Material.Color.Primary); [TypeConverter(typeof(ColorTypeConverter))] public Color UnselectedBackground { get => (Color)GetValue(UnselectedBackgroundProperty); set => SetValue(UnselectedBackgroundProperty, value); } public static readonly BindableProperty UnselectedForegroundProperty = BindableProperty.Create( nameof(UnselectedForeground), typeof(Color), typeof(MobileTabStrip), XF.Material.Forms.Material.Color.OnPrimary); [TypeConverter(typeof(ColorTypeConverter))] public Color UnselectedForeground { get => (Color)GetValue(UnselectedForegroundProperty); set => SetValue(UnselectedForegroundProperty, value); } // private readonly BindableProperty SeparatorColorProperty = BindableProperty.Create( // nameof(SeparatorColor), // typeof(Color), // typeof(MobileTabStrip), // XF.Material.Forms.Material.Color.Primary); // // public Color SeparatorColor // { // get => (Color)GetValue(SeparatorColorProperty); // set => SetValue(SeparatorColorProperty, value); // } public static readonly BindableProperty BorderColorProperty = BindableProperty.Create( nameof(BorderColor), typeof(Color), typeof(MobileTabStrip), XF.Material.Forms.Material.Color.Primary); public Color BorderColor { get => (Color)GetValue(BorderColorProperty); set => SetValue(BorderColorProperty, value); } public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create( nameof(CornerRadius), typeof(float), typeof(MobileTabStrip), 5f); public float CornerRadius { get => (float)GetValue(CornerRadiusProperty); set => SetValue(CornerRadiusProperty, value); } public static readonly BindableProperty FontSizeProperty = BindableProperty.Create( nameof(FontSize), typeof(double), typeof(MobileTabStrip), Device.GetNamedSize(NamedSize.Small, typeof(Label))); [TypeConverter(typeof(FontSizeConverter))] public double FontSize { get => (double)GetValue(FontSizeProperty); set => SetValue(FontSizeProperty, value); } public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create( nameof(FontAttributes), typeof(FontAttributes), typeof(MobileTabStrip), FontAttributes.None); public FontAttributes FontAttributes { get => (FontAttributes)GetValue(FontAttributesProperty); set => SetValue(FontAttributesProperty, value); } public static readonly BindableProperty ItemsLayoutProperty = BindableProperty.Create( nameof(ItemsLayout), typeof(MobileTabStripItemLayout), typeof(MobileTabStrip), MobileTabStripItemLayout.TextOnly); public MobileTabStripItemLayout ItemsLayout { get => (MobileTabStripItemLayout)GetValue(ItemsLayoutProperty); set { _mobileTabStripDataTemplateSelector.SelectedLayout = value; SetValue(ItemsLayoutProperty, value); } } public static readonly BindableProperty ImageSizeProperty = BindableProperty.Create( nameof(ImageSize), typeof(Size), typeof(MobileTabStrip), new Size(30,30)); public Size ImageSize { get => (Size)GetValue(ImageSizeProperty); set => SetValue(ImageSizeProperty, value); } public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create( nameof(SelectedIndex), typeof(int), typeof(MobileTabStrip), -1); public int SelectedIndex { get => (int)GetValue(SelectedIndexProperty); set => SelectItem((value > -1) && (value < Items.Count) ? Items[value] : null); } public MobileTabStripItem SelectedItem { get => Items.FirstOrDefault(x => x.Selected); set => SelectItem(value); } private void SelectItem(MobileTabStripItem value) { foreach (var item in Items) item.Selected = item == value; SetValue(SelectedIndexProperty,SelectedItem?.Index ?? -1); OnPropertyChanged(nameof(SelectedIndex)); OnPropertyChanged(nameof(SelectedItem)); } public event EventHandler SelectionChanged; public IList Items { get; private set; } public MobileTabStrip() { HeightRequest = 50; var items = new ObservableCollection(); items.CollectionChanged += ItemsChanged; Items = items; InitializeComponent(); BindableLayout.SetItemsSource(_grid, Items); } private void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e) { _grid.ColumnDefinitions.Clear(); foreach (var item in Items) { item.Index = _grid.ColumnDefinitions.Count; _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star }); } Device.BeginInvokeOnMainThread(() => { SelectedItem ??= Items.FirstOrDefault(); }); } private void DoTap(object sender, EventArgs e) { Device.BeginInvokeOnMainThread(() => { SelectedItem = (sender as BindableObject)?.BindingContext as MobileTabStripItem; SelectionChanged?.Invoke(this,EventArgs.Empty); }); } } }