First pass at tab view

This commit is contained in:
watsonb8 2019-12-22 17:10:06 -05:00
parent 7560e122f8
commit 945b7e8e11

View File

@ -1,4 +1,4 @@
using CarouselView.FormsPlugin.Abstractions; // using CarouselView.FormsPlugin.Abstractions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -10,7 +10,7 @@ using Aurora.Design.Converters;
namespace Aurora.Design.Components.TabView namespace Aurora.Design.Components.TabView
{ {
public delegate void PositionChangingEventHandler(object sender, PositionChangingEventArgs e); public delegate void PositionChangingEventHandler(object sender, PositionChangingEventArgs e);
public delegate void PositionChangedEventHandler(object sender, PositionChangedEventArgs e); public delegate void PositionChangedEventHandler(object sender, TabChangedEventArgs e);
public class PositionChangingEventArgs : EventArgs public class PositionChangingEventArgs : EventArgs
{ {
@ -19,7 +19,7 @@ namespace Aurora.Design.Components.TabView
public int OldPosition { get; set; } public int OldPosition { get; set; }
} }
public class PositionChangedEventArgs : EventArgs public class TabChangedEventArgs : EventArgs
{ {
public int NewPosition { get; set; } public int NewPosition { get; set; }
public int OldPosition { get; set; } public int OldPosition { get; set; }
@ -36,19 +36,21 @@ namespace Aurora.Design.Components.TabView
{ {
private StackLayout _mainContainerSL; private StackLayout _mainContainerSL;
private Grid _headerContainerGrid; private Grid _headerContainerGrid;
private CarouselViewControl _carouselView; // private CarouselViewControl _carouselView;
private ScrollView _tabHeadersContainerSv; private ScrollView _tabHeadersContainerSv;
private ContentPresenter _tabPresenter;
public event PositionChangingEventHandler PositionChanging; public event PositionChangingEventHandler PositionChanging;
public event PositionChangedEventHandler PositionChanged; public event PositionChangedEventHandler PositionChanged;
protected virtual void OnPositionChanging(ref PositionChangingEventArgs e) protected virtual void OnTabChanging(ref PositionChangingEventArgs e)
{ {
PositionChangingEventHandler handler = PositionChanging; PositionChangingEventHandler handler = PositionChanging;
handler?.Invoke(this, e); handler?.Invoke(this, e);
} }
protected virtual void OnPositionChanged(PositionChangedEventArgs e) protected virtual void OnTabChanged(TabChangedEventArgs e)
{ {
PositionChangedEventHandler handler = PositionChanged; PositionChangedEventHandler handler = PositionChanged;
handler?.Invoke(this, e); handler?.Invoke(this, e);
@ -108,33 +110,39 @@ namespace Aurora.Design.Components.TabView
} }
private bool _supressCarouselViewPositionChangedEvent; private bool _supressCarouselViewPositionChangedEvent;
private void _carouselView_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(_carouselView.Position) && !_supressCarouselViewPositionChangedEvent)
{
var positionChangingArgs = new PositionChangingEventArgs()
{
Canceled = false,
NewPosition = _carouselView.Position,
OldPosition = SelectedTabIndex
};
OnPositionChanging(ref positionChangingArgs); /// <summary>
/// Allows for intercepting carousel property changing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
// private void _carouselView_PropertyChanged(object sender, PropertyChangedEventArgs e)
// {
// if (e.PropertyName == nameof(_carouselView.Position) && !_supressCarouselViewPositionChangedEvent)
// {
// var positionChangingArgs = new PositionChangingEventArgs()
// {
// Canceled = false,
// NewPosition = _carouselView.Position,
// OldPosition = SelectedTabIndex
// };
if (positionChangingArgs != null && positionChangingArgs.Canceled) // OnPositionChanging(ref positionChangingArgs);
{
_supressCarouselViewPositionChangedEvent = true;
_carouselView.PositionSelected -= _carouselView_PositionSelected;
_carouselView.PropertyChanged -= _carouselView_PropertyChanged;
_carouselView.Position = SelectedTabIndex;
_carouselView.PositionSelected += _carouselView_PositionSelected;
_carouselView.PropertyChanged += _carouselView_PropertyChanged;
_supressCarouselViewPositionChangedEvent = false;
}
SetPosition(positionChangingArgs.NewPosition); // if (positionChangingArgs != null && positionChangingArgs.Canceled)
} // {
} // _supressCarouselViewPositionChangedEvent = true;
// _carouselView.PositionSelected -= _carouselView_PositionSelected;
// _carouselView.PropertyChanged -= _carouselView_PropertyChanged;
// _carouselView.Position = SelectedTabIndex;
// _carouselView.PositionSelected += _carouselView_PositionSelected;
// _carouselView.PropertyChanged += _carouselView_PropertyChanged;
// _supressCarouselViewPositionChangedEvent = false;
// }
// SetPosition(positionChangingArgs.NewPosition);
// }
// }
private void Init() private void Init()
{ {
@ -158,30 +166,32 @@ namespace Aurora.Design.Components.TabView
HorizontalOptions = LayoutOptions.FillAndExpand HorizontalOptions = LayoutOptions.FillAndExpand
}; };
_carouselView = new CarouselViewControl _tabPresenter = new ContentPresenter();
{ // _carouselView = new CarouselViewControl
HorizontalOptions = LayoutOptions.FillAndExpand, // {
VerticalOptions = LayoutOptions.FillAndExpand, // HorizontalOptions = LayoutOptions.FillAndExpand,
HeightRequest = ContentHeight, // VerticalOptions = LayoutOptions.FillAndExpand,
ShowArrows = false, // HeightRequest = ContentHeight,
ShowIndicators = false, // ShowArrows = false,
BindingContext = this // ShowIndicators = false,
}; // BindingContext = this
// };
_carouselView.PropertyChanged += _carouselView_PropertyChanged; // _carouselView.PropertyChanged += _carouselView_PropertyChanged;
_carouselView.PositionSelected += _carouselView_PositionSelected; // _carouselView.PositionSelected += _carouselView_PositionSelected;
_mainContainerSL = new StackLayout _mainContainerSL = new StackLayout
{ {
HorizontalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand,
Children = { _tabHeadersContainerSv, _carouselView }, Children = { _tabHeadersContainerSv, _tabPresenter },
// Children = { _tabHeadersContainerSv, _carouselView }, //Need to set new child in place of carousel
Spacing = 0 Spacing = 0
}; };
Content = _mainContainerSL; Content = _mainContainerSL;
ItemSource.CollectionChanged += ItemSource_CollectionChanged; ItemSource.CollectionChanged += ItemSource_CollectionChanged;
SetPosition(SelectedTabIndex, true); SetCurrentTab(SelectedTabIndex, true);
} }
protected override void OnBindingContextChanged() protected override void OnBindingContextChanged()
@ -199,13 +209,13 @@ namespace Aurora.Design.Components.TabView
} }
} }
private void _carouselView_PositionSelected(object sender, PositionSelectedEventArgs e) // private void _carouselView_PositionSelected(object sender, PositionSelectedEventArgs e)
{ // {
if (_carouselView.Position != e.NewValue || SelectedTabIndex != e.NewValue) // if (_carouselView.Position != e.NewValue || SelectedTabIndex != e.NewValue)
{ // {
SetPosition(e.NewValue); // SetPosition(e.NewValue);
} // }
} // }
private void AddTabToView(TabItem tab) private void AddTabToView(TabItem tab)
{ {
@ -266,7 +276,7 @@ namespace Aurora.Design.Components.TabView
{ {
if (e.PropertyName == nameof(TabItem.IsCurrent)) if (e.PropertyName == nameof(TabItem.IsCurrent))
{ {
SetPosition(ItemSource.IndexOf((TabItem)((BoxView)sender).BindingContext)); SetCurrentTab(ItemSource.IndexOf((TabItem)((BoxView)sender).BindingContext));
} }
if (e.PropertyName == nameof(WidthRequest)) if (e.PropertyName == nameof(WidthRequest))
{ {
@ -282,33 +292,21 @@ namespace Aurora.Design.Components.TabView
Spacing = 0 Spacing = 0
}; };
var tapRecognizer = new TapGestureRecognizer(); var tapRecognizer = new TapGestureRecognizer();
//Appears to set the current view
tapRecognizer.Tapped += (object s, EventArgs e) => tapRecognizer.Tapped += (object s, EventArgs e) =>
{ {
_supressCarouselViewPositionChangedEvent = true; // _supressCarouselViewPositionChangedEvent = true;
var capturedIndex = _headerContainerGrid.Children.IndexOf((View)s); var capturedIndex = _headerContainerGrid.Children.IndexOf((View)s);
SetPosition(capturedIndex); SetCurrentTab(capturedIndex);
_supressCarouselViewPositionChangedEvent = false; // _supressCarouselViewPositionChangedEvent = false;
}; };
headerItemSL.GestureRecognizers.Add(tapRecognizer); headerItemSL.GestureRecognizers.Add(tapRecognizer);
_headerContainerGrid.Children.Add(headerItemSL, _headerContainerGrid.ColumnDefinitions.Count - 1, 0); _headerContainerGrid.Children.Add(headerItemSL, _headerContainerGrid.ColumnDefinitions.Count - 1, 0);
_carouselView.ItemsSource = ItemSource.Select(t => t.Content);
}
#region IsSwipingEnabled //Sets caourselview itemssource to current tab
public bool IsSwipingEnabled // _carouselView.ItemsSource = ItemSource.Select(t => t.Content);
{
get { return (bool)GetValue(IsSwipingEnabledProperty); }
set { SetValue(IsSwipingEnabledProperty, value); }
} }
private static void IsSwipingEnabledChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is TabViewControl tabViewControl)
{
tabViewControl._carouselView.IsSwipeEnabled = (bool)newValue;
}
}
public static readonly BindableProperty IsSwipingEnabledProperty = BindableProperty.Create(nameof(IsSwipingEnabled), typeof(bool), typeof(TabViewControl), true, BindingMode.Default, null, IsSwipingEnabledChanged);
#endregion
#region HeaderBackgroundColor #region HeaderBackgroundColor
public Color HeaderBackgroundColor public Color HeaderBackgroundColor
@ -354,10 +352,11 @@ namespace Aurora.Design.Components.TabView
} }
private static void ContentHeightChanged(BindableObject bindable, object oldValue, object newValue) private static void ContentHeightChanged(BindableObject bindable, object oldValue, object newValue)
{ {
if (bindable is TabViewControl tabViewControl && tabViewControl._carouselView != null) throw new NotImplementedException();
{ // if (bindable is TabViewControl tabViewControl && tabViewControl._carouselView != null)
tabViewControl._carouselView.HeightRequest = (double)newValue; // {
} // tabViewControl._carouselView.HeightRequest = (double)newValue;
// }
} }
public static readonly BindableProperty ContentHeightProperty = BindableProperty.Create(nameof(ContentHeight), typeof(double), typeof(TabViewControl), (double)200, BindingMode.Default, null, ContentHeightChanged); public static readonly BindableProperty ContentHeightProperty = BindableProperty.Create(nameof(ContentHeight), typeof(double), typeof(TabViewControl), (double)200, BindingMode.Default, null, ContentHeightChanged);
#endregion #endregion
@ -510,10 +509,9 @@ namespace Aurora.Design.Components.TabView
public static readonly BindableProperty SelectedTabIndexProperty = BindableProperty.Create(nameof(SelectedTabIndex), typeof(int), typeof(TabViewControl), 0, propertyChanged: OnSelectedTabIndexChanged); public static readonly BindableProperty SelectedTabIndexProperty = BindableProperty.Create(nameof(SelectedTabIndex), typeof(int), typeof(TabViewControl), 0, propertyChanged: OnSelectedTabIndexChanged);
private static void OnSelectedTabIndexChanged(BindableObject bindable, object oldValue, object newValue) private static void OnSelectedTabIndexChanged(BindableObject bindable, object oldValue, object newValue)
{ {
if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null && if (bindable is TabViewControl tabViewControl && tabViewControl.ItemSource != null)
tabViewControl._carouselView.Position != (int)newValue)
{ {
tabViewControl.SetPosition((int)newValue); tabViewControl.SetCurrentTab((int)newValue);
} }
} }
public int SelectedTabIndex public int SelectedTabIndex
@ -523,7 +521,7 @@ namespace Aurora.Design.Components.TabView
} }
#endregion #endregion
public void SetPosition(int position, bool initialRun = false) public void SetCurrentTab(int position, bool initialRun = false)
{ {
if (SelectedTabIndex == position && !initialRun) if (SelectedTabIndex == position && !initialRun)
{ {
@ -537,60 +535,76 @@ namespace Aurora.Design.Components.TabView
NewPosition = position, NewPosition = position,
OldPosition = oldPosition OldPosition = oldPosition
}; };
OnPositionChanging(ref positionChangingArgs); OnTabChanging(ref positionChangingArgs);
if (positionChangingArgs != null && positionChangingArgs.Canceled) if (positionChangingArgs != null && positionChangingArgs.Canceled)
{ {
return; return;
} }
if ((position >= 0 && position < ItemSource.Count) || initialRun) if (((position >= 0 && position < ItemSource.Count) || initialRun) &&
{ oldPosition != position)
if (_carouselView.Position != position || initialRun)
{
_carouselView.PositionSelected -= _carouselView_PositionSelected;
_carouselView.Position = position;
_carouselView.PositionSelected += _carouselView_PositionSelected;
}
if (oldPosition != position)
{ {
if (oldPosition < ItemSource.Count) if (oldPosition < ItemSource.Count)
{ {
ItemSource[oldPosition].IsCurrent = false; ItemSource[oldPosition].IsCurrent = false;
} }
_tabPresenter.Content = ItemSource[position].Content;
ItemSource[position].IsCurrent = true; ItemSource[position].IsCurrent = true;
SelectedTabIndex = position; SelectedTabIndex = position;
Device.BeginInvokeOnMainThread(async () => await _tabHeadersContainerSv.ScrollToAsync(_headerContainerGrid.Children[position], ScrollToPosition.MakeVisible, false)); Device.BeginInvokeOnMainThread(async () => await _tabHeadersContainerSv.ScrollToAsync(_headerContainerGrid.Children[position], ScrollToPosition.MakeVisible, false));
}
} }
var positionChangedArgs = new PositionChangedEventArgs() //Need to change to not use carouselView
// if ((position >= 0 && position < ItemSource.Count) || initialRun)
// {
// if (_carouselView.Position != position || initialRun)
// {
// _carouselView.PositionSelected -= _carouselView_PositionSelected;
// _carouselView.Position = position;
// _carouselView.PositionSelected += _carouselView_PositionSelected;
// }
// if (oldPosition != position)
// {
// if (oldPosition < ItemSource.Count)
// {
// ItemSource[oldPosition].IsCurrent = false;
// }
// ItemSource[position].IsCurrent = true;
// SelectedTabIndex = position;
// Device.BeginInvokeOnMainThread(async () => await _tabHeadersContainerSv.ScrollToAsync(_headerContainerGrid.Children[position], ScrollToPosition.MakeVisible, false));
// }
// }
var tabChangedArgs = new TabChangedEventArgs()
{ {
NewPosition = SelectedTabIndex, NewPosition = SelectedTabIndex,
OldPosition = oldPosition OldPosition = oldPosition
}; };
OnPositionChanged(positionChangedArgs); OnTabChanged(tabChangedArgs);
} }
public void SelectNext() public void SelectNext()
{ {
SetPosition(SelectedTabIndex + 1); SetCurrentTab(SelectedTabIndex + 1);
} }
public void SelectPrevious() public void SelectPrevious()
{ {
SetPosition(SelectedTabIndex - 1); SetCurrentTab(SelectedTabIndex - 1);
} }
public void SelectFirst() public void SelectFirst()
{ {
SetPosition(0); SetCurrentTab(0);
} }
public void SelectLast() public void SelectLast()
{ {
SetPosition(ItemSource.Count - 1); SetCurrentTab(ItemSource.Count - 1);
} }
public void AddTab(TabItem tab, int position = -1, bool selectNewPosition = false) public void AddTab(TabItem tab, int position = -1, bool selectNewPosition = false)
@ -623,7 +637,7 @@ namespace Aurora.Design.Components.TabView
_headerContainerGrid.Children.RemoveAt(_headerContainerGrid.Children.Count - 1); _headerContainerGrid.Children.RemoveAt(_headerContainerGrid.Children.Count - 1);
_headerContainerGrid.ColumnDefinitions.Remove(_headerContainerGrid.ColumnDefinitions.Last()); _headerContainerGrid.ColumnDefinitions.Remove(_headerContainerGrid.ColumnDefinitions.Last());
} }
_carouselView.ItemsSource = ItemSource.Select(t => t.Content); // _carouselView.ItemsSource = ItemSource.Select(t => t.Content);
SelectedTabIndex = position >= 0 && position < ItemSource.Count ? position : ItemSource.Count - 1; SelectedTabIndex = position >= 0 && position < ItemSource.Count ? position : ItemSource.Count - 1;
} }
} }