MobileTabStrip.xaml.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Collections.Specialized;
  5. using System.Linq;
  6. using JetBrains.Annotations;
  7. using Xamarin.Forms;
  8. using Xamarin.Forms.Xaml;
  9. namespace InABox.Mobile
  10. {
  11. public enum MobileTabStripItemLayout
  12. {
  13. TextOnly,
  14. ImageOnly,
  15. Vertical,
  16. Horizontal
  17. }
  18. public class MobileTabStripDataTemplateSelector : DataTemplateSelector
  19. {
  20. public MobileTabStripItemLayout SelectedLayout { get; set; }
  21. public DataTemplate VerticalTemplate { get; set; }
  22. public DataTemplate HorizontalTemplate { get; set; }
  23. public DataTemplate TextOnlyTemplate { get; set; }
  24. public DataTemplate ImageOnlyTemplate { get; set; }
  25. protected override DataTemplate OnSelectTemplate (object item, BindableObject container)
  26. {
  27. return SelectedLayout switch
  28. {
  29. MobileTabStripItemLayout.ImageOnly => ImageOnlyTemplate,
  30. MobileTabStripItemLayout.Vertical => VerticalTemplate,
  31. MobileTabStripItemLayout.Horizontal => HorizontalTemplate,
  32. _ => TextOnlyTemplate
  33. };
  34. }
  35. }
  36. [XamlCompilation(XamlCompilationOptions.Compile)]
  37. public partial class MobileTabStrip
  38. {
  39. public static readonly BindableProperty SelectedBackgroundProperty = BindableProperty.Create(
  40. nameof(SelectedBackground),
  41. typeof(Color),
  42. typeof(MobileTabStrip),
  43. XF.Material.Forms.Material.Color.Surface);
  44. public Color SelectedBackground
  45. {
  46. get => (Color)GetValue(SelectedBackgroundProperty);
  47. set => SetValue(SelectedBackgroundProperty, value);
  48. }
  49. public static readonly BindableProperty SelectedForegroundProperty = BindableProperty.Create(
  50. nameof(SelectedForeground),
  51. typeof(Color),
  52. typeof(MobileTabStrip),
  53. XF.Material.Forms.Material.Color.OnSurface);
  54. [TypeConverter(typeof(ColorTypeConverter))]
  55. public Color SelectedForeground
  56. {
  57. get => (Color)GetValue(SelectedForegroundProperty);
  58. set => SetValue(SelectedForegroundProperty, value);
  59. }
  60. public static readonly BindableProperty UnselectedBackgroundProperty = BindableProperty.Create(
  61. nameof(UnselectedBackground),
  62. typeof(Color),
  63. typeof(MobileTabStrip),
  64. XF.Material.Forms.Material.Color.Primary);
  65. [TypeConverter(typeof(ColorTypeConverter))]
  66. public Color UnselectedBackground
  67. {
  68. get => (Color)GetValue(UnselectedBackgroundProperty);
  69. set => SetValue(UnselectedBackgroundProperty, value);
  70. }
  71. public static readonly BindableProperty UnselectedForegroundProperty = BindableProperty.Create(
  72. nameof(UnselectedForeground),
  73. typeof(Color),
  74. typeof(MobileTabStrip),
  75. XF.Material.Forms.Material.Color.OnPrimary);
  76. [TypeConverter(typeof(ColorTypeConverter))]
  77. public Color UnselectedForeground
  78. {
  79. get => (Color)GetValue(UnselectedForegroundProperty);
  80. set => SetValue(UnselectedForegroundProperty, value);
  81. }
  82. // private readonly BindableProperty SeparatorColorProperty = BindableProperty.Create(
  83. // nameof(SeparatorColor),
  84. // typeof(Color),
  85. // typeof(MobileTabStrip),
  86. // XF.Material.Forms.Material.Color.Primary);
  87. //
  88. // public Color SeparatorColor
  89. // {
  90. // get => (Color)GetValue(SeparatorColorProperty);
  91. // set => SetValue(SeparatorColorProperty, value);
  92. // }
  93. public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(
  94. nameof(BorderColor),
  95. typeof(Color),
  96. typeof(MobileTabStrip),
  97. XF.Material.Forms.Material.Color.Primary);
  98. public Color BorderColor
  99. {
  100. get => (Color)GetValue(BorderColorProperty);
  101. set => SetValue(BorderColorProperty, value);
  102. }
  103. public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
  104. nameof(CornerRadius),
  105. typeof(float),
  106. typeof(MobileTabStrip),
  107. 5f);
  108. public float CornerRadius
  109. {
  110. get => (float)GetValue(CornerRadiusProperty);
  111. set => SetValue(CornerRadiusProperty, value);
  112. }
  113. public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
  114. nameof(FontSize),
  115. typeof(double),
  116. typeof(MobileTabStrip),
  117. Device.GetNamedSize(NamedSize.Small, typeof(Label)));
  118. [TypeConverter(typeof(FontSizeConverter))]
  119. public double FontSize
  120. {
  121. get => (double)GetValue(FontSizeProperty);
  122. set => SetValue(FontSizeProperty, value);
  123. }
  124. public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create(
  125. nameof(FontAttributes),
  126. typeof(FontAttributes),
  127. typeof(MobileTabStrip),
  128. FontAttributes.None);
  129. public FontAttributes FontAttributes
  130. {
  131. get => (FontAttributes)GetValue(FontAttributesProperty);
  132. set => SetValue(FontAttributesProperty, value);
  133. }
  134. public static readonly BindableProperty ItemsLayoutProperty = BindableProperty.Create(
  135. nameof(ItemsLayout),
  136. typeof(MobileTabStripItemLayout),
  137. typeof(MobileTabStrip),
  138. MobileTabStripItemLayout.TextOnly);
  139. public MobileTabStripItemLayout ItemsLayout
  140. {
  141. get => (MobileTabStripItemLayout)GetValue(ItemsLayoutProperty);
  142. set
  143. {
  144. _mobileTabStripDataTemplateSelector.SelectedLayout = value;
  145. SetValue(ItemsLayoutProperty, value);
  146. }
  147. }
  148. public static readonly BindableProperty ImageSizeProperty = BindableProperty.Create(
  149. nameof(ImageSize),
  150. typeof(Size),
  151. typeof(MobileTabStrip),
  152. new Size(30,30));
  153. public Size ImageSize
  154. {
  155. get => (Size)GetValue(ImageSizeProperty);
  156. set => SetValue(ImageSizeProperty, value);
  157. }
  158. public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(
  159. nameof(SelectedIndex),
  160. typeof(int),
  161. typeof(MobileTabStrip),
  162. -1);
  163. public int SelectedIndex
  164. {
  165. get => (int)GetValue(SelectedIndexProperty);
  166. set => SelectItem((value > -1) && (value < Items.Count) ? Items[value] : null);
  167. }
  168. public MobileTabStripItem SelectedItem
  169. {
  170. get => Items.FirstOrDefault(x => x.Selected);
  171. set => SelectItem(value);
  172. }
  173. private void SelectItem(MobileTabStripItem value)
  174. {
  175. foreach (var item in Items)
  176. item.Selected = item == value;
  177. SetValue(SelectedIndexProperty,SelectedItem?.Index ?? -1);
  178. OnPropertyChanged(nameof(SelectedIndex));
  179. OnPropertyChanged(nameof(SelectedItem));
  180. }
  181. public event EventHandler SelectionChanged;
  182. public IList<MobileTabStripItem> Items { get; private set; }
  183. public MobileTabStrip()
  184. {
  185. HeightRequest = 50;
  186. var items = new ObservableCollection<MobileTabStripItem>();
  187. items.CollectionChanged += ItemsChanged;
  188. Items = items;
  189. InitializeComponent();
  190. BindableLayout.SetItemsSource(_grid, Items);
  191. }
  192. private void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
  193. {
  194. _grid.ColumnDefinitions.Clear();
  195. foreach (var item in Items)
  196. {
  197. item.Index = _grid.ColumnDefinitions.Count;
  198. _grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
  199. }
  200. Device.BeginInvokeOnMainThread(() =>
  201. {
  202. SelectedItem ??= Items.FirstOrDefault();
  203. });
  204. }
  205. private void DoTap(object sender, EventArgs e)
  206. {
  207. Device.BeginInvokeOnMainThread(() =>
  208. {
  209. SelectedItem = (sender as BindableObject)?.BindingContext as MobileTabStripItem;
  210. SelectionChanged?.Invoke(this,EventArgs.Empty);
  211. });
  212. }
  213. }
  214. }