Changing folder names
This commit is contained in:
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Aurora.Design.Components.Dialogs.Modal">
|
||||
<ContentView.Content>
|
||||
<ContentPresenter
|
||||
x:Name="ViewContent"/>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.Dialogs
|
||||
{
|
||||
public partial class Modal : ContentView
|
||||
{
|
||||
public Modal()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows.Input;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.HorizontalList
|
||||
{
|
||||
public class HorizontalList : Grid
|
||||
{
|
||||
private ICommand _innerSelectedCommand;
|
||||
private readonly ScrollView _scrollView;
|
||||
private readonly StackLayout _itemsStackLayout;
|
||||
|
||||
public event EventHandler SelectedItemChanged;
|
||||
private NotifyCollectionChangedEventHandler _itemsChangedHandler;
|
||||
|
||||
public StackOrientation ListOrientation { get; set; }
|
||||
|
||||
public double Spacing { get; set; }
|
||||
|
||||
public static readonly BindableProperty SelectedCommandProperty =
|
||||
BindableProperty.Create("SelectedCommand", typeof(ICommand), typeof(HorizontalList), null);
|
||||
|
||||
public static readonly BindableProperty ItemsSourceProperty =
|
||||
BindableProperty.Create("ItemsSource",
|
||||
returnType: typeof(ObservableCollection<object>),
|
||||
declaringType: typeof(HorizontalList),
|
||||
defaultValue: default(ObservableCollection<object>),
|
||||
defaultBindingMode: BindingMode.TwoWay,
|
||||
propertyChanged: ItemsSourceChanged);
|
||||
|
||||
public static readonly BindableProperty SelectedItemProperty =
|
||||
BindableProperty.Create("SelectedItem", typeof(object), typeof(HorizontalList), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
|
||||
|
||||
public static readonly BindableProperty ItemTemplateProperty =
|
||||
BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(HorizontalList), default(DataTemplate));
|
||||
|
||||
public ICommand SelectedCommand
|
||||
{
|
||||
get { return (ICommand)GetValue(SelectedCommandProperty); }
|
||||
set { SetValue(SelectedCommandProperty, value); }
|
||||
}
|
||||
|
||||
public ObservableCollection<object> ItemsSource
|
||||
{
|
||||
get { return (ObservableCollection<object>)GetValue(ItemsSourceProperty); }
|
||||
set { SetValue(ItemsSourceProperty, value); }
|
||||
}
|
||||
|
||||
public object SelectedItem
|
||||
{
|
||||
get { return (object)GetValue(SelectedItemProperty); }
|
||||
set { SetValue(SelectedItemProperty, value); }
|
||||
}
|
||||
|
||||
public DataTemplate ItemTemplate
|
||||
{
|
||||
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
|
||||
set { SetValue(ItemTemplateProperty, value); }
|
||||
}
|
||||
|
||||
private static void ItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
HorizontalList itemsLayout = bindable as HorizontalList;
|
||||
itemsLayout.SetItems();
|
||||
}
|
||||
|
||||
public HorizontalList()
|
||||
{
|
||||
_itemsChangedHandler = OnItemsChanged;
|
||||
// BackgroundColor = Color.FromHex("#1E2634");
|
||||
Spacing = 6;
|
||||
_scrollView = new ScrollView();
|
||||
_itemsStackLayout = new StackLayout
|
||||
{
|
||||
Padding = Padding,
|
||||
Spacing = Spacing,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand
|
||||
};
|
||||
|
||||
_scrollView.Content = _itemsStackLayout;
|
||||
Children.Add(_scrollView);
|
||||
}
|
||||
|
||||
~HorizontalList()
|
||||
{
|
||||
ItemsSource.CollectionChanged -= _itemsChangedHandler;
|
||||
}
|
||||
|
||||
protected virtual void SetItems()
|
||||
{
|
||||
_itemsStackLayout.Children.Clear();
|
||||
_itemsStackLayout.Spacing = Spacing;
|
||||
|
||||
_innerSelectedCommand = new Command<View>(view =>
|
||||
{
|
||||
SelectedItem = view.BindingContext;
|
||||
SelectedItem = null; // Allowing item second time selection
|
||||
});
|
||||
|
||||
_itemsStackLayout.Orientation = ListOrientation;
|
||||
_scrollView.Orientation = ListOrientation == StackOrientation.Horizontal
|
||||
? ScrollOrientation.Horizontal
|
||||
: ScrollOrientation.Vertical;
|
||||
|
||||
if (ItemsSource == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Setup collection events
|
||||
ItemsSource.CollectionChanged += _itemsChangedHandler;
|
||||
|
||||
foreach (var item in ItemsSource)
|
||||
{
|
||||
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||
}
|
||||
|
||||
SelectedItem = null;
|
||||
}
|
||||
|
||||
protected virtual View GetItemView(object item)
|
||||
{
|
||||
var content = ItemTemplate.CreateContent();
|
||||
var view = content as View;
|
||||
|
||||
if (view == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
view.BindingContext = item;
|
||||
|
||||
var gesture = new TapGestureRecognizer
|
||||
{
|
||||
Command = _innerSelectedCommand,
|
||||
CommandParameter = view
|
||||
};
|
||||
|
||||
AddGesture(view, gesture);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void AddGesture(View view, TapGestureRecognizer gesture)
|
||||
{
|
||||
view.GestureRecognizers.Add(gesture);
|
||||
|
||||
var layout = view as Layout<View>;
|
||||
|
||||
if (layout == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var child in layout.Children)
|
||||
{
|
||||
AddGesture(child, gesture);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
var itemsView = (HorizontalList)bindable;
|
||||
|
||||
if (newValue == oldValue && newValue != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
itemsView.SelectedItemChanged?.Invoke(itemsView, EventArgs.Empty);
|
||||
|
||||
if (itemsView.SelectedCommand?.CanExecute(newValue) ?? false)
|
||||
{
|
||||
itemsView.SelectedCommand?.Execute(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
switch (e.Action)
|
||||
{
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
|
||||
{
|
||||
foreach (object item in e.NewItems)
|
||||
{
|
||||
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
|
||||
{
|
||||
foreach (object item in e.OldItems)
|
||||
{
|
||||
//Clear layout and rebuild
|
||||
_itemsStackLayout.Children.Clear();
|
||||
foreach (var source in ItemsSource)
|
||||
{
|
||||
_itemsStackLayout.Children.Add(GetItemView(item));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Aurora.Design.Components.ImageButton.ImageButton">
|
||||
<ContentView.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="OnButtonTapped" />
|
||||
</ContentView.GestureRecognizers>
|
||||
<ContentView.Content>
|
||||
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
|
||||
<Image x:Name="imgButton" Aspect="AspectFit" />
|
||||
</StackLayout>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.ImageButton
|
||||
{
|
||||
public partial class ImageButton : ContentView
|
||||
{
|
||||
public ImageButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public static readonly BindableProperty SourceProperty =
|
||||
BindableProperty.Create(
|
||||
"Source",
|
||||
typeof(ImageSource),
|
||||
typeof(ImageButton),
|
||||
null,
|
||||
BindingMode.TwoWay,
|
||||
propertyChanged: (bindable, oldValue, newValue) =>
|
||||
{
|
||||
ImageButton control = (ImageButton)bindable;
|
||||
|
||||
control.imgButton.Source = (ImageSource)newValue;
|
||||
});
|
||||
|
||||
public static readonly BindableProperty CommandProperty = BindableProperty.Create(
|
||||
"Command",
|
||||
typeof(Command),
|
||||
typeof(ImageButton),
|
||||
null,
|
||||
propertyChanged: (bindable, oldValue, newValue) =>
|
||||
{
|
||||
ImageButton control = (ImageButton)bindable;
|
||||
var command = (Command)newValue;
|
||||
|
||||
CanExecute(command, control);
|
||||
|
||||
command.CanExecuteChanged += (sender, e) =>
|
||||
{
|
||||
CanExecute(sender, control);
|
||||
};
|
||||
});
|
||||
|
||||
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(
|
||||
"CommandParameter",
|
||||
typeof(object),
|
||||
typeof(ImageButton),
|
||||
null);
|
||||
|
||||
private static void CanExecute(object sender, ImageButton control)
|
||||
{
|
||||
var cmd = (Command)sender;
|
||||
control.imgButton.IsEnabled = cmd.CanExecute(null);
|
||||
}
|
||||
|
||||
public ImageSource Source
|
||||
{
|
||||
get { return (ImageSource)GetValue(SourceProperty); }
|
||||
set { SetValue(SourceProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public event EventHandler<EventArgs> Tapped;
|
||||
|
||||
public Command Command
|
||||
{
|
||||
get { return (Command)GetValue(CommandProperty); }
|
||||
set { SetValue(CommandProperty, value); }
|
||||
}
|
||||
|
||||
public object CommandParameter
|
||||
{
|
||||
get { return GetValue(CommandParameterProperty); }
|
||||
set { SetValue(CommandParameterProperty, value); }
|
||||
}
|
||||
|
||||
protected void OnButtonTapped(object sender, EventArgs args)
|
||||
{
|
||||
object resolvedParameter;
|
||||
|
||||
if (CommandParameter != null)
|
||||
{
|
||||
resolvedParameter = CommandParameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedParameter = args;
|
||||
}
|
||||
|
||||
if (Command?.CanExecute(resolvedParameter) ?? true)
|
||||
{
|
||||
this.AbortAnimation("imgButtonAnim");
|
||||
new Animation(v => imgButton.Scale = v, 1, 0.5).Commit(imgButton, "imgButtonAnim", 16, 150, Easing.SinOut,
|
||||
(v, c) =>
|
||||
{
|
||||
imgButton.Scale = 1;
|
||||
Tapped?.Invoke(this, args);
|
||||
Command?.Execute(resolvedParameter);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
Label {
|
||||
margin-left: 25;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
font-size: 14;
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
|
||||
x:Class="Aurora.Design.Components.Library.Library">
|
||||
<ContentView.Resources>
|
||||
<StyleSheet
|
||||
Source="Library.css"/>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<dg:DataGrid
|
||||
x:Name="LibraryDataGrid"
|
||||
SelectionEnabled="True"
|
||||
RowHeight="30"
|
||||
BorderColor="#181818"
|
||||
BorderThickness="0"
|
||||
HeaderHeight="45"
|
||||
HeaderBackground="#181818">
|
||||
<dg:DataGrid.HeaderLabelStyle>
|
||||
<Style
|
||||
TargetType="Label">
|
||||
<Setter
|
||||
Property="HorizontalOptions"
|
||||
Value="Start"/>
|
||||
<Setter
|
||||
Property="FontSize"
|
||||
Value="14"/>
|
||||
<Setter
|
||||
Property="TextColor"
|
||||
Value="White"/>
|
||||
</Style>
|
||||
</dg:DataGrid.HeaderLabelStyle>
|
||||
<dg:DataGrid.GestureRecognizers>
|
||||
<TapGestureRecognizer
|
||||
NumberOfTapsRequired="2"/>
|
||||
</dg:DataGrid.GestureRecognizers>
|
||||
<dg:DataGrid.Columns>
|
||||
<dg:DataGridColumn
|
||||
Title=""
|
||||
PropertyName="Icon"
|
||||
Width="15">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Image
|
||||
Source="../../Resources/unselected.png"/>
|
||||
</DataTemplate>
|
||||
</dg:DataGridColumn.CellTemplate>
|
||||
</dg:DataGridColumn>
|
||||
<dg:DataGridColumn
|
||||
Title="Title"
|
||||
PropertyName="Metadata.Title"
|
||||
Width="2*">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Label
|
||||
LineBreakMode="TailTruncation"
|
||||
Text="{Binding .}"/>
|
||||
</DataTemplate>
|
||||
</dg:DataGridColumn.CellTemplate>
|
||||
</dg:DataGridColumn>
|
||||
<dg:DataGridColumn
|
||||
Title="Album"
|
||||
PropertyName="Metadata.Album"
|
||||
Width="0.95*">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Label
|
||||
LineBreakMode="TailTruncation"
|
||||
Text="{Binding .}"/>
|
||||
</DataTemplate>
|
||||
</dg:DataGridColumn.CellTemplate>
|
||||
</dg:DataGridColumn>
|
||||
<dg:DataGridColumn
|
||||
Title="Artist"
|
||||
PropertyName="Metadata.Artist"
|
||||
Width="1*">
|
||||
<dg:DataGridColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Label
|
||||
LineBreakMode="TailTruncation"
|
||||
Text="{Binding .}"/>
|
||||
</DataTemplate>
|
||||
</dg:DataGridColumn.CellTemplate>
|
||||
</dg:DataGridColumn>
|
||||
</dg:DataGrid.Columns>
|
||||
<dg:DataGrid.RowsTextColorPalette>
|
||||
<dg:PaletteCollection>
|
||||
<Color>White</Color>
|
||||
</dg:PaletteCollection>
|
||||
</dg:DataGrid.RowsTextColorPalette>
|
||||
<dg:DataGrid.RowsBackgroundColorPalette>
|
||||
<dg:PaletteCollection>
|
||||
<Color>Transparent</Color>
|
||||
</dg:PaletteCollection>
|
||||
</dg:DataGrid.RowsBackgroundColorPalette>
|
||||
</dg:DataGrid>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.Library
|
||||
{
|
||||
public partial class Library : ContentView
|
||||
{
|
||||
public Library()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.LibraryDataGrid.ItemSelected += (sender, e) =>
|
||||
{
|
||||
this.SelectedItem = e.SelectedItem;
|
||||
};
|
||||
}
|
||||
|
||||
#region ItemsSource Property
|
||||
/// <summary>
|
||||
/// Bindable Property for the ItemsSource of the datagrid.
|
||||
/// </summary>
|
||||
/// <param name=""ItemsSource""></param>
|
||||
/// <param name="typeof(IEnumerable<object>"></param>
|
||||
/// <returns></returns>
|
||||
public static readonly BindableProperty ItemsSourceProperty =
|
||||
BindableProperty.Create(propertyName: "ItemsSource",
|
||||
returnType: typeof(IEnumerable<object>),
|
||||
declaringType: typeof(Library),
|
||||
defaultBindingMode: BindingMode.Default,
|
||||
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||
{
|
||||
Library control = bindable as Library;
|
||||
control.LibraryDataGrid.ItemsSource = (IEnumerable<object>)newValue;
|
||||
});
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Backing property for the ItemsSource property.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public IEnumerable<object> ItemsSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return (IEnumerable<object>)GetValue(ItemsSourceProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion ItemsSource Property
|
||||
|
||||
/// <summary>
|
||||
/// Bindable property for the selected item field on the datagrid.
|
||||
/// </summary>
|
||||
/// <param name=""SelectedItem""></param>
|
||||
/// <param name="typeof(BaseMetadata"></param>
|
||||
/// <returns></returns>
|
||||
public static readonly BindableProperty SelectedItemProperty =
|
||||
BindableProperty.Create(propertyName: "SelectedItem",
|
||||
returnType: typeof(object),
|
||||
declaringType: typeof(Library),
|
||||
defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// Backing property for the SelectedItem property.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public object SelectedItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((object)GetValue(SelectedItemProperty));
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(SelectedItemProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Bindable property for the item double clicked command
|
||||
/// </summary>
|
||||
/// <param name=""SelectedItem""></param>
|
||||
/// <param name="typeof(BaseMetadata"></param>
|
||||
/// <returns></returns>
|
||||
public static readonly BindableProperty ItemDoubleClickedProperty =
|
||||
BindableProperty.Create(propertyName: "ItemDoubleClicked",
|
||||
returnType: typeof(Command),
|
||||
declaringType: typeof(Library),
|
||||
propertyChanged: OnDoubleClickPropertyChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Public backing property
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public Command ItemDoubleClicked
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Command)GetValue(ItemDoubleClickedProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(ItemDoubleClickedProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for double click property. Adds command execute handler.
|
||||
/// </summary>
|
||||
/// <param name="bindable"></param>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="oldValue"></param>
|
||||
private static void OnDoubleClickPropertyChanged(BindableObject bindable, object newValue, object oldValue)
|
||||
{
|
||||
Library control = bindable as Library;
|
||||
var dataGrid = control.LibraryDataGrid;
|
||||
if (dataGrid.GestureRecognizers.Count > 0)
|
||||
{
|
||||
var gestureRecognizer = dataGrid.GestureRecognizers.First();
|
||||
|
||||
if (gestureRecognizer is TapGestureRecognizer)
|
||||
{
|
||||
TapGestureRecognizer tap = gestureRecognizer as TapGestureRecognizer;
|
||||
tap.Tapped += (sender, e) =>
|
||||
{
|
||||
control.ItemDoubleClicked.Execute(null);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#PlayerControlContainer {
|
||||
background-color: #303030;
|
||||
}
|
||||
|
||||
Label {
|
||||
color: white;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#MediaInfoContainer {
|
||||
width: 150;
|
||||
margin-top: 10;
|
||||
margin-bottom: 10;
|
||||
}
|
||||
|
||||
#MediaInfoContainer label {
|
||||
margin-left: 20;
|
||||
}
|
||||
|
||||
#AlbumArtBoxView {
|
||||
background-color: black;
|
||||
width: 80;
|
||||
}
|
||||
|
||||
.PlayButton {
|
||||
width: 40;
|
||||
}
|
||||
|
||||
.DirectionButton {
|
||||
width: 30;
|
||||
}
|
||||
|
||||
.LibraryButton {
|
||||
width: 25;
|
||||
}
|
||||
|
||||
ImageButton {
|
||||
margin-top: 10;
|
||||
margin-left: 15;
|
||||
margin-right: 15;
|
||||
margin-bottom: 10;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:imgBtn="clr-namespace:Aurora.Design.Components.ImageButton"
|
||||
x:Class="Aurora.Design.Components.MediaPlayer.Player">
|
||||
<ContentView.Resources>
|
||||
<StyleSheet
|
||||
Source="Player.css"/>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition
|
||||
Width="200"/>
|
||||
<ColumnDefinition
|
||||
Width="*"/>
|
||||
<ColumnDefinition
|
||||
Width="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackLayout
|
||||
Grid.Column="0"
|
||||
Orientation="Horizontal">
|
||||
<BoxView
|
||||
x:Name="AlbumArtBoxView"/>
|
||||
<StackLayout
|
||||
x:Name="MediaInfoContainer"
|
||||
HorizontalOptions="StartAndExpand">
|
||||
<Label
|
||||
x:Name="SongTitleLabel"
|
||||
LineBreakMode="TailTruncation"/>
|
||||
<Label
|
||||
x:Name="ArtistNameLabel"
|
||||
LineBreakMode="TailTruncation"/>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout
|
||||
x:Name="PlayerControlContainer"
|
||||
Grid.Column="1"
|
||||
HorizontalOptions="Center"
|
||||
Orientation="Horizontal">
|
||||
<imgBtn:ImageButton
|
||||
x:Name="ShuffleButton"
|
||||
StyleClass="LibraryButton"
|
||||
Source="Resources/shuffle.png"/>
|
||||
<imgBtn:ImageButton
|
||||
x:Name="PreviousButton"
|
||||
StyleClass="DirectionButton"
|
||||
Source="Resources/backward.png"/>
|
||||
<imgBtn:ImageButton
|
||||
x:Name="PlayButton"
|
||||
StyleClass="PlayButton"/>
|
||||
<imgBtn:ImageButton
|
||||
x:Name="NextButton"
|
||||
StyleClass="DirectionButton"
|
||||
Source="Resources/forwards.png"/>
|
||||
<imgBtn:ImageButton
|
||||
x:Name="LoopButton"
|
||||
StyleClass="LibraryButton"
|
||||
Source="Resources/loop.png"/>
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,303 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.MediaPlayer
|
||||
{
|
||||
public partial class Player : ContentView
|
||||
{
|
||||
public Player()
|
||||
{
|
||||
|
||||
InitializeComponent();
|
||||
PlayButton.Source = ImageSource.FromFile("Resources/play.png");
|
||||
}
|
||||
|
||||
#region SongTitle Bindable
|
||||
public static readonly BindableProperty SongTitleProperty =
|
||||
BindableProperty.Create(propertyName: "SongTitle",
|
||||
returnType: typeof(string),
|
||||
declaringType: typeof(Player),
|
||||
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||
{
|
||||
Player component = bindable as Player;
|
||||
component.SongTitleLabel.Text = (string)newValue;
|
||||
});
|
||||
|
||||
public string SongTitle
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)GetValue(SongTitleProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(SongTitleProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion SongTitle Bindable
|
||||
|
||||
#region ArtistName Bindable
|
||||
public static readonly BindableProperty ArtistNameProperty =
|
||||
BindableProperty.Create(propertyName: "ArtistName",
|
||||
returnType: typeof(string),
|
||||
declaringType: typeof(Player),
|
||||
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||
{
|
||||
Player component = bindable as Player;
|
||||
component.ArtistNameLabel.Text = (string)newValue;
|
||||
});
|
||||
|
||||
public string ArtistName
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)GetValue(ArtistNameProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(ArtistNameProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion ArtistName Bindable
|
||||
|
||||
#region PreviousButton
|
||||
public static readonly BindableProperty PreviousButtonCommandProperty =
|
||||
BindableProperty.Create(propertyName: "PreviousButtonCommand",
|
||||
returnType: typeof(Command),
|
||||
propertyChanged: OnPreviousButtonPropertyChanged,
|
||||
declaringType: typeof(Player));
|
||||
|
||||
public Command PreviousButtonCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Command)GetValue(PreviousButtonCommandProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(PreviousButtonCommandProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPreviousButtonClicked(object sender, EventArgs args)
|
||||
{
|
||||
if (PreviousButtonCommand.CanExecute(null))
|
||||
{
|
||||
PreviousButtonCommand.Execute(null);
|
||||
PreviousButtonCommand.ChangeCanExecute();
|
||||
PlayButtonCommand.ChangeCanExecute();
|
||||
NextButtonCommand.ChangeCanExecute();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to hook up can execute events on property changed
|
||||
/// </summary>
|
||||
/// <param name="bindable"></param>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="oldValue"></param>
|
||||
private static void OnPreviousButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
Player component = bindable as Player;
|
||||
if (newValue is Command)
|
||||
{
|
||||
Command cmd = newValue as Command;
|
||||
component.PreviousButton.Tapped += component.OnPreviousButtonClicked;
|
||||
cmd.CanExecuteChanged += (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
|
||||
if (oldValue is Command && oldValue != null)
|
||||
{
|
||||
Command cmd = newValue as Command;
|
||||
component.PreviousButton.Tapped -= component.OnPreviousButtonClicked;
|
||||
cmd.CanExecuteChanged -= (sender, e) => OnPreviousButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can execute changed event handler
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventArgs"></param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="cmd"></param>
|
||||
private static void OnPreviousButtonCanExecuteChanged(object sender,
|
||||
EventArgs eventArgs,
|
||||
Player component,
|
||||
Command cmd)
|
||||
{
|
||||
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||
}
|
||||
#endregion PreviousButton
|
||||
|
||||
#region PlayButton
|
||||
public static readonly BindableProperty PlayButtonCommandProperty =
|
||||
BindableProperty.Create(propertyName: "PlayButtonCommand",
|
||||
returnType: typeof(Command),
|
||||
propertyChanged: OnPlayButtonPropertyChanged,
|
||||
declaringType: typeof(Player));
|
||||
|
||||
public Command PlayButtonCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Command)GetValue(PlayButtonCommandProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(PlayButtonCommandProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayButtonClicked(object sender, EventArgs args)
|
||||
{
|
||||
if (PlayButtonCommand.CanExecute(null))
|
||||
{
|
||||
PlayButtonCommand.Execute(null);
|
||||
PreviousButtonCommand.ChangeCanExecute();
|
||||
PlayButtonCommand.ChangeCanExecute();
|
||||
NextButtonCommand.ChangeCanExecute();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to hook up can execute events on property changed
|
||||
/// </summary>
|
||||
/// <param name="bindable"></param>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="oldValue"></param>
|
||||
private static void OnPlayButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
Player component = bindable as Player;
|
||||
if (newValue is Command)
|
||||
{
|
||||
Command cmd = newValue as Command;
|
||||
component.PlayButton.Tapped += component.OnPlayButtonClicked;
|
||||
cmd.CanExecuteChanged += (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
|
||||
if (oldValue is Command && oldValue != null)
|
||||
{
|
||||
Command cmd = newValue as Command;
|
||||
component.PlayButton.Tapped -= component.OnPlayButtonClicked;
|
||||
cmd.CanExecuteChanged -= (sender, e) => OnPlayButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can execute changed event handler
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventArgs"></param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="cmd"></param>
|
||||
private static void OnPlayButtonCanExecuteChanged(object sender,
|
||||
EventArgs eventArgs,
|
||||
Player component,
|
||||
Command cmd)
|
||||
{
|
||||
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||
}
|
||||
#endregion PlayButton
|
||||
|
||||
#region NextButton
|
||||
public static readonly BindableProperty NextButtonCommandProperty =
|
||||
BindableProperty.Create(propertyName: "NextButtonCommand",
|
||||
returnType: typeof(Command),
|
||||
declaringType: typeof(Player),
|
||||
propertyChanged: OnNextButtonPropertyChanged);
|
||||
|
||||
public Command NextButtonCommand
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Command)GetValue(NextButtonCommandProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(NextButtonCommandProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNextButtonClicked(object sender, EventArgs args)
|
||||
{
|
||||
if (NextButtonCommand.CanExecute(null))
|
||||
{
|
||||
NextButtonCommand.Execute(null);
|
||||
PreviousButtonCommand.ChangeCanExecute();
|
||||
PlayButtonCommand.ChangeCanExecute();
|
||||
NextButtonCommand.ChangeCanExecute();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to hook up can execute events on property changed
|
||||
/// </summary>
|
||||
/// <param name="bindable"></param>
|
||||
/// <param name="newValue"></param>
|
||||
/// <param name="oldValue"></param>
|
||||
private static void OnNextButtonPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
Player component = bindable as Player;
|
||||
if (newValue is Command)
|
||||
{
|
||||
Command cmd = newValue as Command;
|
||||
component.NextButton.Tapped += component.OnNextButtonClicked;
|
||||
cmd.CanExecuteChanged += (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
|
||||
if (oldValue is Command && oldValue != null)
|
||||
{
|
||||
Command cmd = oldValue as Command;
|
||||
component.NextButton.Tapped -= component.OnNextButtonClicked;
|
||||
cmd.CanExecuteChanged -= (sender, e) => OnNextButtonCanExecuteChanged(sender, e, component, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can execute changed event handler
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="eventArgs"></param>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="cmd"></param>
|
||||
private static void OnNextButtonCanExecuteChanged(object sender,
|
||||
EventArgs eventArgs,
|
||||
Player component,
|
||||
Command cmd)
|
||||
{
|
||||
|
||||
component.NextButton.IsEnabled = cmd.CanExecute(null);
|
||||
}
|
||||
#endregion PlayButton
|
||||
|
||||
#region Playing Bindable
|
||||
public static readonly BindableProperty IsPlayingProperty =
|
||||
BindableProperty.Create(
|
||||
propertyName: "IsPlaying",
|
||||
returnType: typeof(bool),
|
||||
declaringType: typeof(Player),
|
||||
propertyChanged: (BindableObject bindable, object oldValue, object newValue) =>
|
||||
{
|
||||
Player control = (Player)bindable;
|
||||
if ((bool)newValue == true)
|
||||
{
|
||||
control.PlayButton.Source = ImageSource.FromFile("Resources/pause.png");
|
||||
}
|
||||
else
|
||||
{
|
||||
control.PlayButton.Source = ImageSource.FromFile("Resources/play.png");
|
||||
}
|
||||
});
|
||||
|
||||
public bool IsPlaying
|
||||
{
|
||||
get { return (bool)GetValue(IsPlayingProperty); }
|
||||
set { SetValue(IsPlayingProperty, value); }
|
||||
}
|
||||
|
||||
#endregion Playing Binadable
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#MembersList {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
Grid {
|
||||
margin-left: 20;
|
||||
margin-right: 20;
|
||||
margin-top: 20;
|
||||
margin-bottom: 20;
|
||||
width: 150;
|
||||
border-radius: 25;
|
||||
background-color: #626363;
|
||||
}
|
||||
|
||||
Grid Label {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
color: white;
|
||||
font-size: 20;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
|
||||
x:Class="Aurora.Design.Components.MemberList.MemberList">
|
||||
<ContentView.Resources>
|
||||
<StyleSheet
|
||||
Source="./MemberList.css"/>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<flv:FlowListView
|
||||
x:Name="MembersList"
|
||||
FlowColumnMinWidth="150"
|
||||
RowHeight="150"
|
||||
SeparatorVisibility="None"
|
||||
BackgroundColor="#181818"
|
||||
HasUnevenRows="false">
|
||||
<flv:FlowListView.FlowColumnTemplate>
|
||||
<DataTemplate>
|
||||
<Grid
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand">
|
||||
<Label
|
||||
Text="{Binding UserName}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</flv:FlowListView.FlowColumnTemplate>
|
||||
</flv:FlowListView>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
using Aurora.Proto.Party;
|
||||
using DLToolkit.Forms.Controls;
|
||||
|
||||
namespace Aurora.Design.Components.MemberList
|
||||
{
|
||||
public partial class MemberList : ContentView
|
||||
{
|
||||
public MemberList()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bindable property for members list.
|
||||
/// </summary>
|
||||
/// <param name=""Members""></param>
|
||||
/// <param name="typeof(IEnumerable<string>"></param>
|
||||
/// <returns></returns>
|
||||
public static readonly BindableProperty MembersProperty =
|
||||
BindableProperty.Create(propertyName: "Members",
|
||||
returnType: typeof(ObservableCollection<Member>),
|
||||
declaringType: typeof(MemberList),
|
||||
defaultBindingMode: BindingMode.Default,
|
||||
propertyChanged: OnMembersChanged);
|
||||
|
||||
/// <summary>
|
||||
/// Backing property for MembersProperty
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
public ObservableCollection<Member> Members
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ObservableCollection<Member>)GetValue(MembersProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(MembersProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Memberes changed event handler. Assign member list source.
|
||||
/// </summary>
|
||||
/// <param name="bindable"></param>
|
||||
/// <param name="oldValue"></param>
|
||||
/// <param name="newValue"></param>
|
||||
private static void OnMembersChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
var control = (MemberList)bindable;
|
||||
var membersList = control.FindByName("MembersList") as FlowListView;
|
||||
|
||||
if (newValue is ICollection source)
|
||||
{
|
||||
membersList.FlowItemsSource = source;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Aurora.Design.Components.NavigationMenu
|
||||
{
|
||||
public class NavigationGroupItem : List<NavigationItem>
|
||||
{
|
||||
public NavigationGroupItem()
|
||||
{
|
||||
}
|
||||
|
||||
public NavigationGroupItem(string heading)
|
||||
{
|
||||
GroupHeading = heading;
|
||||
}
|
||||
|
||||
public List<NavigationItem> Items => this;
|
||||
public string GroupHeading { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Aurora.Design.Views.Main;
|
||||
|
||||
namespace Aurora.Design.Components.NavigationMenu
|
||||
{
|
||||
public class NavigationItem
|
||||
{
|
||||
public NavigationItem()
|
||||
{
|
||||
}
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Group { get; set; }
|
||||
public Type TargetType { get; set; }
|
||||
public Type TargetViewModelType { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
ListView {
|
||||
margin-left: 15;
|
||||
margin-top: 40;
|
||||
}
|
||||
|
||||
#GroupTemplate {
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
#GroupCell Label {
|
||||
color: lightgray;
|
||||
font-size: 12;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
font-style: italic;
|
||||
padding-top: 20;
|
||||
}
|
||||
|
||||
#ItemCell Label {
|
||||
color: white;
|
||||
font-size: 15;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
font-style: normal;
|
||||
text-align: left;
|
||||
padding-top: 12;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView
|
||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Aurora.Design.Components.NavigationMenu.NavigationMenu">
|
||||
<ContentView.Resources>
|
||||
<StyleSheet
|
||||
Source="NavigationMenu.css"/>
|
||||
</ContentView.Resources>
|
||||
<ContentView.Content>
|
||||
<StackLayout
|
||||
x:Name="Layout"
|
||||
StyleClass="primaryColor">
|
||||
<ListView
|
||||
x:Name="MenuItemsListView"
|
||||
HasUnevenRows="true"
|
||||
SeparatorVisibility="None"
|
||||
IsGroupingEnabled="true"
|
||||
RowHeight="35"
|
||||
StyleClass="primaryColor"
|
||||
CachingStrategy="RecycleElement">
|
||||
<ListView.GroupHeaderTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell
|
||||
x:Name="GroupCell">
|
||||
<Label
|
||||
VerticalTextAlignment="Center"
|
||||
Text="{Binding GroupHeading}"/>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.GroupHeaderTemplate>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell
|
||||
x:Name="ItemCell">
|
||||
<Label
|
||||
StyleClass="primaryColor"
|
||||
Text="{Binding Title}"/>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentView.Content>
|
||||
</ContentView>
|
@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.NavigationMenu
|
||||
{
|
||||
public partial class NavigationMenu : ContentView
|
||||
{
|
||||
public NavigationMenu()
|
||||
{
|
||||
InitializeComponent();
|
||||
ListView = MenuItemsListView;
|
||||
ListView.ItemSelected += ListView_ItemSelected;
|
||||
}
|
||||
|
||||
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
|
||||
{
|
||||
this.SelectedItem = e.SelectedItem as NavigationItem;
|
||||
}
|
||||
|
||||
public ListView ListView;
|
||||
|
||||
public static readonly BindableProperty SelectedItemProperty =
|
||||
BindableProperty.Create(propertyName: nameof(SelectedItem),
|
||||
returnType: typeof(NavigationItem),
|
||||
declaringType: typeof(NavigationMenu),
|
||||
defaultBindingMode: BindingMode.OneWayToSource);
|
||||
|
||||
public NavigationItem SelectedItem
|
||||
{
|
||||
get
|
||||
{
|
||||
return (NavigationItem)GetValue(SelectedItemProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(SelectedItemProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static readonly BindableProperty ItemsProperty =
|
||||
BindableProperty.Create(propertyName: nameof(Items),
|
||||
returnType: typeof(ObservableCollection<NavigationItem>),
|
||||
declaringType: typeof(NavigationMenu),
|
||||
defaultBindingMode: BindingMode.TwoWay,
|
||||
propertyChanged: OnItemsChanged);
|
||||
|
||||
public ObservableCollection<NavigationItem> Items
|
||||
{
|
||||
get
|
||||
{
|
||||
return (ObservableCollection<NavigationItem>)GetValue(ItemsProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(ItemsProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Items changed event handler. Organizes items in groups for display.
|
||||
/// </summary>
|
||||
/// <param name="bindable">The changed Item.</param>
|
||||
/// <param name="oldValue">The previous value.</param>
|
||||
/// <param name="newValue">The new value.</param>
|
||||
private static void OnItemsChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
var control = (NavigationMenu)bindable;
|
||||
ObservableCollection<NavigationItem> items = (ObservableCollection<NavigationItem>)newValue;
|
||||
Dictionary<string, NavigationGroupItem> groupDictioanry = new Dictionary<string, NavigationGroupItem>();
|
||||
|
||||
//Populate dictionary where group heading is the key
|
||||
foreach (NavigationItem item in items)
|
||||
{
|
||||
if (groupDictioanry.ContainsKey(item.Group))
|
||||
{
|
||||
groupDictioanry.TryGetValue(item.Group, out var groupItem);
|
||||
groupItem.Items.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationGroupItem groupItem = new NavigationGroupItem(item.Group);
|
||||
groupItem.Add(item);
|
||||
|
||||
groupDictioanry.Add(item.Group, groupItem);
|
||||
}
|
||||
}
|
||||
|
||||
ObservableCollection<NavigationGroupItem> groups = new ObservableCollection<NavigationGroupItem>();
|
||||
foreach (string groupHeading in groupDictioanry.Keys)
|
||||
{
|
||||
groupDictioanry.TryGetValue(groupHeading, out var groupItem);
|
||||
groups.Add(groupItem);
|
||||
}
|
||||
|
||||
control.MenuItemsListView.ItemsSource = groups;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Aurora.Design.Components.TabView
|
||||
{
|
||||
[ContentProperty(nameof(Content))]
|
||||
public class TabItem : BindableObject
|
||||
{
|
||||
public TabItem()
|
||||
{
|
||||
//Parameterless constructor required for xaml instantiation.
|
||||
}
|
||||
|
||||
public void TriggerPropertyChange(string propertyName = null)
|
||||
{
|
||||
base.OnPropertyChanged(propertyName);
|
||||
}
|
||||
|
||||
public TabItem(string headerText, View content, ImageSource headerIcon = null)
|
||||
{
|
||||
HeaderText = headerText;
|
||||
Content = content;
|
||||
if (headerIcon != null)
|
||||
HeaderIcon = headerIcon;
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderIconProperty = BindableProperty.Create(nameof(HeaderIcon), typeof(ImageSource), typeof(TabItem));
|
||||
public ImageSource HeaderIcon
|
||||
{
|
||||
get => (ImageSource)GetValue(HeaderIconProperty);
|
||||
set { SetValue(HeaderIconProperty, value); }
|
||||
}
|
||||
|
||||
public readonly BindableProperty HeaderIconSizeProperty = BindableProperty.Create(nameof(HeaderIconSize), typeof(double), typeof(TabItem), 32.0);
|
||||
public double HeaderIconSize
|
||||
{
|
||||
get => (double)GetValue(HeaderIconSizeProperty);
|
||||
set { SetValue(HeaderIconSizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderTextProperty = BindableProperty.Create(nameof(HeaderText), typeof(string), typeof(TabItem), string.Empty);
|
||||
public string HeaderText
|
||||
{
|
||||
get => (string)GetValue(HeaderTextProperty);
|
||||
set { SetValue(HeaderTextProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(TabItem));
|
||||
public View Content
|
||||
{
|
||||
get => (View)GetValue(ContentProperty);
|
||||
set { SetValue(ContentProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty IsCurrentProperty = BindableProperty.Create(nameof(IsCurrent), typeof(bool), typeof(TabItem), false);
|
||||
public bool IsCurrent
|
||||
{
|
||||
get => (bool)GetValue(IsCurrentProperty);
|
||||
set { SetValue(IsCurrentProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderTextColorProperty = BindableProperty.Create(nameof(HeaderTextColor), typeof(Color), typeof(TabItem), Color.White);
|
||||
public Color HeaderTextColor
|
||||
{
|
||||
get => (Color)GetValue(HeaderTextColorProperty);
|
||||
set { SetValue(HeaderTextColorProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineColorProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineColor), typeof(Color), typeof(TabItem), Color.Transparent);
|
||||
public Color HeaderSelectionUnderlineColor
|
||||
{
|
||||
get => (Color)GetValue(HeaderSelectionUnderlineColorProperty);
|
||||
set { SetValue(HeaderSelectionUnderlineColorProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineThicknessProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineThickness), typeof(double), typeof(TabItem), (double)5);
|
||||
public double HeaderSelectionUnderlineThickness
|
||||
{
|
||||
get => (double)GetValue(HeaderSelectionUnderlineThicknessProperty);
|
||||
set { SetValue(HeaderSelectionUnderlineThicknessProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineWidthProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineWidth), typeof(double), typeof(TabItem), (double)40);
|
||||
public double HeaderSelectionUnderlineWidth
|
||||
{
|
||||
get => (double)GetValue(HeaderSelectionUnderlineWidthProperty);
|
||||
set { SetValue(HeaderSelectionUnderlineWidthProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderTabTextFontSizeProperty = BindableProperty.Create(nameof(HeaderTabTextFontSize), typeof(double), typeof(TabItem), TabDefaults.DefaultTextSize);
|
||||
[TypeConverter(typeof(FontSizeConverter))]
|
||||
public double HeaderTabTextFontSize
|
||||
{
|
||||
get => (double)GetValue(HeaderTabTextFontSizeProperty);
|
||||
set { SetValue(HeaderTabTextFontSizeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderTabTextFontFamilyProperty = BindableProperty.Create(nameof(HeaderTabTextFontFamily), typeof(string), typeof(TabItem));
|
||||
public string HeaderTabTextFontFamily
|
||||
{
|
||||
get => (string)GetValue(HeaderTabTextFontFamilyProperty);
|
||||
set { SetValue(HeaderTabTextFontFamilyProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty HeaderTabTextFontAttributesProperty = BindableProperty.Create(nameof(HeaderTabTextFontAttributes), typeof(FontAttributes), typeof(TabItem), FontAttributes.None);
|
||||
public FontAttributes HeaderTabTextFontAttributes
|
||||
{
|
||||
get => (FontAttributes)GetValue(HeaderTabTextFontAttributesProperty);
|
||||
set { SetValue(HeaderTabTextFontAttributesProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,571 @@
|
||||
// using CarouselView.FormsPlugin.Abstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Xamarin.Forms;
|
||||
using Aurora.Design.Converters;
|
||||
|
||||
namespace Aurora.Design.Components.TabView
|
||||
{
|
||||
public delegate void PositionChangingEventHandler(object sender, TabChangingEventArgs e);
|
||||
public delegate void PositionChangedEventHandler(object sender, TabChangedEventArgs e);
|
||||
|
||||
public class TabChangingEventArgs : EventArgs
|
||||
{
|
||||
public bool Canceled { get; set; }
|
||||
public int NewPosition { get; set; }
|
||||
public int OldPosition { get; set; }
|
||||
}
|
||||
|
||||
public class TabChangedEventArgs : EventArgs
|
||||
{
|
||||
public int NewPosition { get; set; }
|
||||
public int OldPosition { get; set; }
|
||||
}
|
||||
|
||||
static class TabDefaults
|
||||
{
|
||||
public static readonly Color DefaultColor = Color.White;
|
||||
public const double DefaultThickness = 5;
|
||||
public const double DefaultTextSize = 14;
|
||||
}
|
||||
|
||||
public class TabViewControl : ContentView
|
||||
{
|
||||
private StackLayout _mainContainerSL;
|
||||
private Grid _headerContainerGrid;
|
||||
private ScrollView _tabHeadersContainerSv;
|
||||
|
||||
public event PositionChangingEventHandler PositionChanging;
|
||||
public event PositionChangedEventHandler PositionChanged;
|
||||
|
||||
protected virtual void OnTabChanging(ref TabChangingEventArgs e)
|
||||
{
|
||||
PositionChangingEventHandler handler = PositionChanging;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnTabChanged(TabChangedEventArgs e)
|
||||
{
|
||||
PositionChangedEventHandler handler = PositionChanged;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public TabViewControl()
|
||||
{
|
||||
//Parameterless constructor required for xaml instantiation.
|
||||
Init();
|
||||
}
|
||||
|
||||
public TabViewControl(IList<TabItem> tabItems, int selectedTabIndex = 0)
|
||||
{
|
||||
Init();
|
||||
foreach (var tab in tabItems)
|
||||
{
|
||||
ItemSource.Add(tab);
|
||||
}
|
||||
if (selectedTabIndex > 0)
|
||||
{
|
||||
SelectedTabIndex = selectedTabIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.NewItems != null)
|
||||
{
|
||||
foreach (var tab in e.NewItems)
|
||||
{
|
||||
if (tab is TabItem newTab)
|
||||
{
|
||||
SetTabProps(newTab);
|
||||
AddTabToView(newTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTabProps(TabItem tab)
|
||||
{
|
||||
//Set the tab properties from the main control only if not set in xaml at the individual tab level.
|
||||
if (tab.HeaderTextColor == TabDefaults.DefaultColor && HeaderTabTextColor != TabDefaults.DefaultColor)
|
||||
tab.HeaderTextColor = HeaderTabTextColor;
|
||||
if (tab.HeaderSelectionUnderlineColor == TabDefaults.DefaultColor && HeaderSelectionUnderlineColor != TabDefaults.DefaultColor)
|
||||
tab.HeaderSelectionUnderlineColor = HeaderSelectionUnderlineColor;
|
||||
if (tab.HeaderSelectionUnderlineThickness.Equals(TabDefaults.DefaultThickness) && !HeaderSelectionUnderlineThickness.Equals(TabDefaults.DefaultThickness))
|
||||
tab.HeaderSelectionUnderlineThickness = HeaderSelectionUnderlineThickness;
|
||||
if (tab.HeaderSelectionUnderlineWidth > 0)
|
||||
tab.HeaderSelectionUnderlineWidth = HeaderSelectionUnderlineWidth;
|
||||
if (tab.HeaderTabTextFontSize.Equals(TabDefaults.DefaultTextSize) && !HeaderTabTextFontSize.Equals(TabDefaults.DefaultTextSize))
|
||||
tab.HeaderTabTextFontSize = HeaderTabTextFontSize;
|
||||
if (tab.HeaderTabTextFontFamily is null && !string.IsNullOrWhiteSpace(HeaderTabTextFontFamily))
|
||||
tab.HeaderTabTextFontFamily = HeaderTabTextFontFamily;
|
||||
if (tab.HeaderTabTextFontAttributes == FontAttributes.None && HeaderTabTextFontAttributes != FontAttributes.None)
|
||||
tab.HeaderTabTextFontAttributes = HeaderTabTextFontAttributes;
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
ItemSource = new ObservableCollection<TabItem>();
|
||||
|
||||
_headerContainerGrid = new Grid
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.Start,
|
||||
// BackgroundColor = Color.White, // tab sepeartor color
|
||||
MinimumHeightRequest = 50,
|
||||
ColumnSpacing = 0, // seperator thickness
|
||||
};
|
||||
|
||||
_tabHeadersContainerSv = new ScrollView()
|
||||
{
|
||||
HorizontalScrollBarVisibility = ScrollBarVisibility.Never,
|
||||
Orientation = ScrollOrientation.Horizontal,
|
||||
Content = _headerContainerGrid,
|
||||
BackgroundColor = HeaderBackgroundColor,
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand
|
||||
};
|
||||
|
||||
_mainContainerSL = new StackLayout
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
Children = { _tabHeadersContainerSv },
|
||||
Spacing = 0
|
||||
};
|
||||
|
||||
Content = _mainContainerSL;
|
||||
ItemSource.CollectionChanged += ItemSource_CollectionChanged;
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
if (BindingContext != null)
|
||||
{
|
||||
foreach (var tab in ItemSource)
|
||||
{
|
||||
if (tab is TabItem view)
|
||||
{
|
||||
view.Content.BindingContext = BindingContext;
|
||||
}
|
||||
}
|
||||
|
||||
SetCurrentTab(SelectedTabIndex, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTabToView(TabItem tab)
|
||||
{
|
||||
var tabSize = (TabSizeOption.IsAbsolute && TabSizeOption.Value.Equals(0)) ? new GridLength(1, GridUnitType.Star) : TabSizeOption;
|
||||
|
||||
_headerContainerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = tabSize });
|
||||
|
||||
tab.IsCurrent = _headerContainerGrid.ColumnDefinitions.Count - 1 == SelectedTabIndex;
|
||||
|
||||
var headerIcon = new Image
|
||||
{
|
||||
Margin = new Thickness(0, 8, 0, 0),
|
||||
BindingContext = tab,
|
||||
HorizontalOptions = LayoutOptions.CenterAndExpand,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
WidthRequest = tab.HeaderIconSize,
|
||||
HeightRequest = tab.HeaderIconSize
|
||||
};
|
||||
headerIcon.SetBinding(Image.SourceProperty, nameof(TabItem.HeaderIcon));
|
||||
headerIcon.SetBinding(IsVisibleProperty, nameof(TabItem.HeaderIcon), converter: new NullToBoolConverter());
|
||||
|
||||
var headerLabel = new Label
|
||||
{
|
||||
BindingContext = tab,
|
||||
VerticalTextAlignment = TextAlignment.Center,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||
Margin = new Thickness(5, 8, 5, 5)
|
||||
};
|
||||
|
||||
headerLabel.SetBinding(Label.TextProperty, nameof(TabItem.HeaderText));
|
||||
headerLabel.SetBinding(Label.TextColorProperty, nameof(TabItem.HeaderTextColor));
|
||||
headerLabel.SetBinding(Label.FontSizeProperty, nameof(TabItem.HeaderTabTextFontSize));
|
||||
headerLabel.SetBinding(Label.FontFamilyProperty, nameof(TabItem.HeaderTabTextFontFamily));
|
||||
headerLabel.SetBinding(Label.FontAttributesProperty, nameof(TabItem.HeaderTabTextFontAttributes));
|
||||
headerLabel.SetBinding(IsVisibleProperty, nameof(TabItem.HeaderText), converter: new NullToBoolConverter());
|
||||
|
||||
var selectionBarBoxView = new BoxView
|
||||
{
|
||||
VerticalOptions = LayoutOptions.End,
|
||||
BindingContext = tab,
|
||||
HeightRequest = HeaderSelectionUnderlineThickness,
|
||||
WidthRequest = HeaderSelectionUnderlineWidth
|
||||
};
|
||||
var underlineColorBinding = new Binding(nameof(TabItem.IsCurrent), BindingMode.OneWay, new SelectedTabHeaderToTabBackgroundColorConverter(), this);
|
||||
selectionBarBoxView.SetBinding(BoxView.BackgroundColorProperty, underlineColorBinding);
|
||||
|
||||
selectionBarBoxView.SetBinding(WidthRequestProperty, nameof(TabItem.HeaderSelectionUnderlineWidth));
|
||||
selectionBarBoxView.SetBinding(HeightRequestProperty, nameof(TabItem.HeaderSelectionUnderlineThickness));
|
||||
selectionBarBoxView.SetBinding(HorizontalOptionsProperty,
|
||||
nameof(TabItem.HeaderSelectionUnderlineWidthProperty),
|
||||
converter: new DoubleToLayoutOptionsConverter());
|
||||
|
||||
selectionBarBoxView.PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TabItem.IsCurrent))
|
||||
{
|
||||
SetCurrentTab(ItemSource.IndexOf((TabItem)((BoxView)sender).BindingContext));
|
||||
}
|
||||
if (e.PropertyName == nameof(WidthRequest))
|
||||
{
|
||||
selectionBarBoxView.HorizontalOptions = tab.HeaderSelectionUnderlineWidth > 0 ? LayoutOptions.CenterAndExpand : LayoutOptions.FillAndExpand;
|
||||
}
|
||||
};
|
||||
|
||||
var headerItemSL = new StackLayout
|
||||
{
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
Children = { headerIcon, headerLabel, selectionBarBoxView },
|
||||
BackgroundColor = HeaderBackgroundColor,
|
||||
Spacing = 0
|
||||
};
|
||||
var tapRecognizer = new TapGestureRecognizer();
|
||||
|
||||
tapRecognizer.Tapped += (object s, EventArgs e) =>
|
||||
{
|
||||
var capturedIndex = _headerContainerGrid.Children.IndexOf((View)s);
|
||||
SetCurrentTab(capturedIndex);
|
||||
};
|
||||
|
||||
headerItemSL.GestureRecognizers.Add(tapRecognizer);
|
||||
_headerContainerGrid.Children.Add(headerItemSL, _headerContainerGrid.ColumnDefinitions.Count - 1, 0);
|
||||
}
|
||||
|
||||
#region HeaderBackgroundColor
|
||||
public Color HeaderBackgroundColor
|
||||
{
|
||||
get { return (Color)GetValue(HeaderBackgroundColorProperty); }
|
||||
set { SetValue(HeaderBackgroundColorProperty, value); }
|
||||
}
|
||||
private static void HeaderBackgroundColorChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl)
|
||||
{
|
||||
tabViewControl._tabHeadersContainerSv.BackgroundColor = (Color)newValue;
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderBackgroundColorProperty = BindableProperty.Create(nameof(HeaderBackgroundColor), typeof(Color), typeof(TabViewControl), Color.SkyBlue, BindingMode.Default, null, HeaderBackgroundColorChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderTabTextColor
|
||||
public Color HeaderTabTextColor
|
||||
{
|
||||
get { return (Color)GetValue(HeaderTabTextColorProperty); }
|
||||
set { SetValue(HeaderTabTextColorProperty, value); }
|
||||
}
|
||||
private static void HeaderTabTextColorChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderTextColor = (Color)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderTabTextColorProperty =
|
||||
BindableProperty.Create(nameof(HeaderTabTextColor), typeof(Color), typeof(TabViewControl), TabDefaults.DefaultColor, BindingMode.OneWay, null, HeaderTabTextColorChanged);
|
||||
#endregion
|
||||
|
||||
#region ContentHeight
|
||||
public double ContentHeight
|
||||
{
|
||||
get { return (double)GetValue(ContentHeightProperty); }
|
||||
set { SetValue(ContentHeightProperty, value); }
|
||||
}
|
||||
private static void ContentHeightChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// if (bindable is TabViewControl tabViewControl && tabViewControl._carouselView != null)
|
||||
// {
|
||||
// tabViewControl._carouselView.HeightRequest = (double)newValue;
|
||||
// }
|
||||
}
|
||||
public static readonly BindableProperty ContentHeightProperty = BindableProperty.Create(nameof(ContentHeight), typeof(double), typeof(TabViewControl), (double)200, BindingMode.Default, null, ContentHeightChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderSelectionUnderlineColor
|
||||
public Color HeaderSelectionUnderlineColor
|
||||
{
|
||||
get { return (Color)GetValue(HeaderSelectionUnderlineColorProperty); }
|
||||
set { SetValue(HeaderSelectionUnderlineColorProperty, value); }
|
||||
}
|
||||
private static void HeaderSelectionUnderlineColorChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderSelectionUnderlineColor = (Color)newValue;
|
||||
tab.TriggerPropertyChange(nameof(tab.IsCurrent));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineColorProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineColor), typeof(Color), typeof(TabViewControl), Color.White, BindingMode.Default, null, HeaderSelectionUnderlineColorChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderSelectionUnderlineThickness
|
||||
public double HeaderSelectionUnderlineThickness
|
||||
{
|
||||
get { return (double)GetValue(HeaderSelectionUnderlineThicknessProperty); }
|
||||
set { SetValue(HeaderSelectionUnderlineThicknessProperty, value); }
|
||||
}
|
||||
private static void HeaderSelectionUnderlineThicknessChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderSelectionUnderlineThickness = (double)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineThicknessProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineThickness), typeof(double), typeof(TabViewControl), TabDefaults.DefaultThickness, BindingMode.Default, null, HeaderSelectionUnderlineThicknessChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderSelectionUnderlineWidth
|
||||
public double HeaderSelectionUnderlineWidth
|
||||
{
|
||||
get { return (double)GetValue(HeaderSelectionUnderlineWidthProperty); }
|
||||
set { SetValue(HeaderSelectionUnderlineWidthProperty, value); }
|
||||
}
|
||||
private static void HeaderSelectionUnderlineWidthChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderSelectionUnderlineWidth = (double)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderSelectionUnderlineWidthProperty = BindableProperty.Create(nameof(HeaderSelectionUnderlineWidth), typeof(double), typeof(TabViewControl), (double)0, BindingMode.Default, null, HeaderSelectionUnderlineWidthChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderTabTextFontSize
|
||||
[Xamarin.Forms.TypeConverter(typeof(FontSizeConverter))]
|
||||
public double HeaderTabTextFontSize
|
||||
{
|
||||
get { return (double)GetValue(HeaderTabTextFontSizeProperty); }
|
||||
set { SetValue(HeaderTabTextFontSizeProperty, value); }
|
||||
}
|
||||
private static void HeaderTabTextFontSizeChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderTabTextFontSize = (double)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderTabTextFontSizeProperty = BindableProperty.Create(nameof(HeaderTabTextFontSize), typeof(double), typeof(TabViewControl), (double)14, BindingMode.Default, null, HeaderTabTextFontSizeChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderTabTextFontFamily
|
||||
public string HeaderTabTextFontFamily
|
||||
{
|
||||
get { return (string)GetValue(HeaderTabTextFontFamilyProperty); }
|
||||
set { SetValue(HeaderTabTextFontFamilyProperty, value); }
|
||||
}
|
||||
private static void HeaderTabTextFontFamilyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderTabTextFontFamily = (string)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderTabTextFontFamilyProperty = BindableProperty.Create(nameof(HeaderTabTextFontFamily), typeof(string), typeof(TabViewControl), null, BindingMode.Default, null, HeaderTabTextFontFamilyChanged);
|
||||
#endregion
|
||||
|
||||
#region HeaderTabTextFontAttributes
|
||||
public FontAttributes HeaderTabTextFontAttributes
|
||||
{
|
||||
get { return (FontAttributes)GetValue(HeaderTabTextFontAttributesProperty); }
|
||||
set { SetValue(HeaderTabTextFontAttributesProperty, value); }
|
||||
}
|
||||
private static void HeaderTabTextFontAttributesChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tab in tabViewControl.ItemSource)
|
||||
{
|
||||
tab.HeaderTabTextFontAttributes = (FontAttributes)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty HeaderTabTextFontAttributesProperty = BindableProperty.Create(nameof(HeaderTabTextFontAttributes), typeof(FontAttributes), typeof(TabViewControl), FontAttributes.None, BindingMode.Default, null, HeaderTabTextFontAttributesChanged);
|
||||
#endregion
|
||||
|
||||
#region ItemSource
|
||||
public static readonly BindableProperty ItemSourceProperty = BindableProperty.Create(nameof(ItemSource), typeof(ObservableCollection<TabItem>), typeof(TabViewControl));
|
||||
public ObservableCollection<TabItem> ItemSource
|
||||
{
|
||||
get => (ObservableCollection<TabItem>)GetValue(ItemSourceProperty);
|
||||
set { SetValue(ItemSourceProperty, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TabSizeOption
|
||||
public static readonly BindableProperty TabSizeOptionProperty = BindableProperty.Create(nameof(TabSizeOption), typeof(GridLength), typeof(TabViewControl), default(GridLength), propertyChanged: OnTabSizeOptionChanged);
|
||||
private static void OnTabSizeOptionChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl._headerContainerGrid != null && tabViewControl.ItemSource != null)
|
||||
{
|
||||
foreach (var tabContainer in tabViewControl._headerContainerGrid.ColumnDefinitions)
|
||||
{
|
||||
tabContainer.Width = (GridLength)newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
public GridLength TabSizeOption
|
||||
{
|
||||
get => (GridLength)GetValue(TabSizeOptionProperty);
|
||||
set { SetValue(TabSizeOptionProperty, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SelectedTabIndex
|
||||
public static readonly BindableProperty SelectedTabIndexProperty = BindableProperty.Create(
|
||||
nameof(SelectedTabIndex),
|
||||
typeof(int),
|
||||
typeof(TabViewControl),
|
||||
defaultValue: 0,
|
||||
defaultBindingMode: BindingMode.TwoWay,
|
||||
propertyChanged: OnSelectedTabIndexChanged);
|
||||
private static void OnSelectedTabIndexChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
|
||||
{
|
||||
tabViewControl.SetCurrentTab((int)newValue);
|
||||
}
|
||||
}
|
||||
public int SelectedTabIndex
|
||||
{
|
||||
get => (int)GetValue(SelectedTabIndexProperty);
|
||||
set { SetValue(SelectedTabIndexProperty, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void SetCurrentTab(int position, bool initialRun = false)
|
||||
{
|
||||
if (SelectedTabIndex == position && !initialRun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int oldPosition = SelectedTabIndex;
|
||||
|
||||
var tabChangingArgs = new TabChangingEventArgs()
|
||||
{
|
||||
Canceled = false,
|
||||
NewPosition = position,
|
||||
OldPosition = oldPosition
|
||||
};
|
||||
OnTabChanging(ref tabChangingArgs);
|
||||
|
||||
if (tabChangingArgs != null && tabChangingArgs.Canceled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (((position >= 0 && position < ItemSource.Count) || initialRun))
|
||||
{
|
||||
if (oldPosition < ItemSource.Count)
|
||||
{
|
||||
List<bool> tabActiveList = ItemSource.Select((TabItem tab, int index) =>
|
||||
{
|
||||
return index == position;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
for (int i = 0; i < tabActiveList.Count(); i++)
|
||||
{
|
||||
ItemSource[i].IsCurrent = tabActiveList[i];
|
||||
}
|
||||
// Remove second child
|
||||
if (_mainContainerSL.Children.Count == 2)
|
||||
{
|
||||
_mainContainerSL.Children.RemoveAt(1);
|
||||
}
|
||||
}
|
||||
_mainContainerSL.Children.Add(ItemSource[position].Content);
|
||||
SelectedTabIndex = position;
|
||||
Device.BeginInvokeOnMainThread(async () => await _tabHeadersContainerSv.ScrollToAsync(_headerContainerGrid.Children[position], ScrollToPosition.MakeVisible, false));
|
||||
|
||||
}
|
||||
|
||||
var tabChangedArgs = new TabChangedEventArgs()
|
||||
{
|
||||
NewPosition = SelectedTabIndex,
|
||||
OldPosition = oldPosition
|
||||
};
|
||||
OnTabChanged(tabChangedArgs);
|
||||
}
|
||||
|
||||
public void SelectNext()
|
||||
{
|
||||
SetCurrentTab(SelectedTabIndex + 1);
|
||||
}
|
||||
|
||||
public void SelectPrevious()
|
||||
{
|
||||
SetCurrentTab(SelectedTabIndex - 1);
|
||||
}
|
||||
|
||||
public void SelectFirst()
|
||||
{
|
||||
SetCurrentTab(0);
|
||||
}
|
||||
|
||||
public void SelectLast()
|
||||
{
|
||||
SetCurrentTab(ItemSource.Count - 1);
|
||||
}
|
||||
|
||||
public void AddTab(TabItem tab, int position = -1, bool selectNewPosition = false)
|
||||
{
|
||||
if (position > -1)
|
||||
{
|
||||
ItemSource.Insert(position, tab);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemSource.Add(tab);
|
||||
}
|
||||
if (selectNewPosition)
|
||||
{
|
||||
SelectedTabIndex = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveTab(int position = -1)
|
||||
{
|
||||
if (position > -1)
|
||||
{
|
||||
ItemSource.RemoveAt(position);
|
||||
_headerContainerGrid.Children.RemoveAt(position);
|
||||
_headerContainerGrid.ColumnDefinitions.RemoveAt(position);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemSource.Remove(ItemSource.Last());
|
||||
_headerContainerGrid.Children.RemoveAt(_headerContainerGrid.Children.Count - 1);
|
||||
_headerContainerGrid.ColumnDefinitions.Remove(_headerContainerGrid.ColumnDefinitions.Last());
|
||||
}
|
||||
SelectedTabIndex = position >= 0 && position < ItemSource.Count ? position : ItemSource.Count - 1;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user