namespace Xamarin.Forms.Platform.iOS
{
- public class CarouselViewController : ItemsViewController
+ public class CarouselViewController : ItemsViewController<CarouselView>
{
CarouselView _carouselView;
- ItemsViewLayout _layout;
bool _viewInitialized;
public CarouselViewController(CarouselView itemsView, ItemsViewLayout layout) : base(itemsView, layout)
{
_carouselView = itemsView;
- _layout = layout;
- Delegator.CarouselViewController = this;
CollectionView.AllowsSelection = false;
CollectionView.AllowsMultipleSelection = false;
}
+ protected override UICollectionViewDelegateFlowLayout CreateDelegator()
+ {
+ return new CarouselViewDelegator(ItemsViewLayout, this);
+ }
+
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = base.GetCell(collectionView, indexPath);
--- /dev/null
+using UIKit;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CarouselViewDelegator : ItemsViewDelegator<CarouselView, CarouselViewController>
+ {
+ public CarouselViewDelegator(ItemsViewLayout itemsViewLayout, CarouselViewController itemsViewController)
+ : base(itemsViewLayout, itemsViewController)
+ {
+ }
+
+ public override void DraggingStarted(UIScrollView scrollView)
+ {
+ ViewController?.DraggingStarted(scrollView);
+
+ PreviousHorizontalOffset = (float)scrollView.ContentOffset.X;
+ PreviousVerticalOffset = (float)scrollView.ContentOffset.Y;
+ }
+
+ public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
+ {
+ PreviousHorizontalOffset = 0;
+ PreviousVerticalOffset = 0;
+
+ ViewController?.DraggingEnded(scrollView, willDecelerate);
+ }
+ }
+}
\ No newline at end of file
namespace Xamarin.Forms.Platform.iOS
{
- public class CarouselViewRenderer : ItemsViewRenderer
+ public class CarouselViewRenderer : ItemsViewRenderer<CarouselView, CarouselViewController>
{
- CarouselView CarouselView => (CarouselView)Element;
-
- CarouselViewController CarouselViewController => (CarouselViewController)ItemsViewController;
+ CarouselView CarouselView => Element;
public CarouselViewRenderer()
{
CollectionView.VerifyCollectionViewFlagEnabled(nameof(CarouselViewRenderer));
}
- protected override ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout)
+ protected override CarouselViewController CreateController(CarouselView newElement, ItemsViewLayout layout)
{
- return new CarouselViewController(newElement as CarouselView, layout);
+ return new CarouselViewController(newElement, layout);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
if (changedProperty.IsOneOf(CarouselView.PeekAreaInsetsProperty, CarouselView.NumberOfSideItemsProperty))
{
- (CarouselViewController.Layout as CarouselViewLayout).UpdateConstraints(Frame.Size);
- CarouselViewController.Layout.InvalidateLayout();
+ (Controller.Layout as CarouselViewLayout).UpdateConstraints(Frame.Size);
+ Controller.Layout.InvalidateLayout();
}
else if (changedProperty.Is(CarouselView.IsSwipeEnabledProperty))
UpdateIsSwipeEnabled();
return new CarouselViewLayout(CarouselView.ItemsLayout, CarouselView.ItemSizingStrategy, CarouselView);
}
- protected override void SetUpNewElement(ItemsView newElement)
+ protected override void SetUpNewElement(CarouselView newElement)
{
base.SetUpNewElement(newElement);
UpdateIsSwipeEnabled();
UpdateIsBounceEnabled();
}
- protected override void TearDownOldElement(ItemsView oldElement)
+ protected override void TearDownOldElement(CarouselView oldElement)
{
- CarouselViewController?.TearDown();
+ Controller?.TearDown();
base.TearDownOldElement(oldElement);
}
if (CarouselView == null)
return;
- CarouselViewController.CollectionView.ScrollEnabled = CarouselView.IsSwipeEnabled;
+ Controller.CollectionView.ScrollEnabled = CarouselView.IsSwipeEnabled;
}
void UpdateIsBounceEnabled()
if (CarouselView == null)
return;
- CarouselViewController.CollectionView.Bounces = CarouselView.IsBounceEnabled;
+ Controller.CollectionView.Bounces = CarouselView.IsBounceEnabled;
}
}
}
namespace Xamarin.Forms.Platform.iOS
{
- public class CollectionViewRenderer : GroupableItemsViewRenderer { }
+ public class CollectionViewRenderer : GroupableItemsViewRenderer<GroupableItemsView, GroupableItemsViewController<GroupableItemsView>> { }
}
\ No newline at end of file
namespace Xamarin.Forms.Platform.iOS
{
- public class GroupableItemsViewController : SelectableItemsViewController
+ public class GroupableItemsViewController<TItemsView> : SelectableItemsViewController<TItemsView>
+ where TItemsView : GroupableItemsView
{
- GroupableItemsView GroupableItemsView => (GroupableItemsView)ItemsView;
-
// Keep a cached value for the current state of grouping around so we can avoid hitting the
// BindableProperty all the time
bool _isGrouped;
Action _scrollAnimationEndedCallback;
- public GroupableItemsViewController(GroupableItemsView groupableItemsView, ItemsViewLayout layout)
+ public GroupableItemsViewController(TItemsView groupableItemsView, ItemsViewLayout layout)
: base(groupableItemsView, layout)
{
- _isGrouped = GroupableItemsView.IsGrouped;
+ _isGrouped = ItemsView.IsGrouped;
+ }
+
+ protected override UICollectionViewDelegateFlowLayout CreateDelegator()
+ {
+ return new GroupableItemsViewDelegator<TItemsView, GroupableItemsViewController<TItemsView>>(ItemsViewLayout, this);
}
protected override IItemsViewSource CreateItemsViewSource()
{
// Use the BindableProperty here (instead of _isGroupingEnabled) because the cached value might not be set yet
- if (GroupableItemsView.IsGrouped)
+ if (ItemsView.IsGrouped)
{
- return ItemsSourceFactory.CreateGrouped(GroupableItemsView.ItemsSource, CollectionView);
+ return ItemsSourceFactory.CreateGrouped(ItemsView.ItemsSource, CollectionView);
}
return base.CreateItemsViewSource();
public override void UpdateItemsSource()
{
- _isGrouped = GroupableItemsView.IsGrouped;
+ _isGrouped = ItemsView.IsGrouped;
base.UpdateItemsSource();
}
void UpdateTemplatedSupplementaryView(TemplatedCell cell, NSString elementKind, NSIndexPath indexPath)
{
DataTemplate template = elementKind == UICollectionElementKindSectionKey.Header
- ? GroupableItemsView.GroupHeaderTemplate
- : GroupableItemsView.GroupFooterTemplate;
+ ? ItemsView.GroupHeaderTemplate
+ : ItemsView.GroupFooterTemplate;
var bindingContext = ItemsSource.Group(indexPath);
{
if (elementKind == UICollectionElementKindSectionKey.Header)
{
- return DetermineViewReuseId(GroupableItemsView.GroupHeaderTemplate);
+ return DetermineViewReuseId(ItemsView.GroupHeaderTemplate);
}
- return DetermineViewReuseId(GroupableItemsView.GroupFooterTemplate);
+ return DetermineViewReuseId(ItemsView.GroupFooterTemplate);
}
string DetermineViewReuseId(DataTemplate template)
--- /dev/null
+using System;
+using CoreGraphics;
+using UIKit;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class GroupableItemsViewDelegator<TItemsView, TViewController> : SelectableItemsViewDelegator<TItemsView, TViewController>
+ where TItemsView : GroupableItemsView
+ where TViewController : GroupableItemsViewController<TItemsView>
+ {
+ public GroupableItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
+ : base(itemsViewLayout, itemsViewController)
+ {
+ }
+
+ public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
+ {
+ return ViewController.GetReferenceSizeForHeader(collectionView, layout, section);
+ }
+
+ public override CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
+ {
+ return ViewController.GetReferenceSizeForFooter(collectionView, layout, section);
+ }
+
+ public override void ScrollAnimationEnded(UIScrollView scrollView)
+ {
+ ViewController?.HandleScrollAnimationEnded();
+ }
+ }
+}
\ No newline at end of file
namespace Xamarin.Forms.Platform.iOS
{
- public class GroupableItemsViewRenderer : SelectableItemsViewRenderer
+ public class GroupableItemsViewRenderer<TItemsView, TViewController> : SelectableItemsViewRenderer<TItemsView, TViewController>
+ where TItemsView : GroupableItemsView
+ where TViewController : GroupableItemsViewController<TItemsView>
{
- GroupableItemsView GroupableItemsView => (GroupableItemsView)Element;
- GroupableItemsViewController GroupableItemsViewController => (GroupableItemsViewController)ItemsViewController;
-
- protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
+ protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
- return new GroupableItemsViewController(itemsView as GroupableItemsView, layout);
+ return new GroupableItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
if (changedProperty.Is(GroupableItemsView.IsGroupedProperty))
{
- GroupableItemsViewController?.UpdateItemsSource();
+ Controller?.UpdateItemsSource();
}
}
{
if (args.IsAnimated)
{
- GroupableItemsViewController.SetScrollAnimationEndedCallback(() => base.ScrollToRequested(sender, args));
+ Controller.SetScrollAnimationEndedCallback(() => base.ScrollToRequested(sender, args));
}
else
{
bool WillNeedScrollAdjustment(ScrollToRequestEventArgs args)
{
- return GroupableItemsView.ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems
- && GroupableItemsView.IsGrouped
+ return ItemsView.ItemSizingStrategy == ItemSizingStrategy.MeasureAllItems
+ && ItemsView.IsGrouped
&& (args.ScrollToPosition == ScrollToPosition.End || args.ScrollToPosition == ScrollToPosition.MakeVisible);
}
}
namespace Xamarin.Forms.Platform.iOS
{
// TODO hartez 2018/06/01 14:21:24 Add a method for updating the layout
- public abstract class ItemsViewController : UICollectionViewController
+ public abstract class ItemsViewController<TItemsView> : UICollectionViewController
+ where TItemsView : ItemsView
{
public IItemsViewSource ItemsSource { get; protected set; }
- public ItemsView ItemsView { get; }
+ public TItemsView ItemsView { get; }
protected ItemsViewLayout ItemsViewLayout { get; set; }
bool _initialConstraintsSet;
bool _isEmpty;
UIView _emptyUIView;
VisualElement _emptyViewFormsElement;
- protected UICollectionViewDelegator Delegator { get; set; }
+ protected UICollectionViewDelegateFlowLayout Delegator { get; set; }
- public ItemsViewController(ItemsView itemsView, ItemsViewLayout layout) : base(layout)
+ public ItemsViewController(TItemsView itemsView, ItemsViewLayout layout) : base(layout)
{
ItemsView = itemsView;
ItemsSource = CreateItemsViewSource();
ItemsViewLayout = layout;
ItemsViewLayout.GetPrototype = GetPrototype;
- // If we're updating from a previous layout, we should keep any settings for the SelectableItemsViewController around
- var selectableItemsViewController = Delegator?.SelectableItemsViewController;
Delegator = CreateDelegator();
CollectionView.Delegate = Delegator;
}
}
- protected virtual UICollectionViewDelegator CreateDelegator()
+ protected virtual UICollectionViewDelegateFlowLayout CreateDelegator()
{
- return new UICollectionViewDelegator(ItemsViewLayout, this);
+ return new ItemsViewDelegator<TItemsView, ItemsViewController<TItemsView>>(ItemsViewLayout, this);
}
protected virtual IItemsViewSource CreateItemsViewSource()
--- /dev/null
+using System;
+using System.Linq;
+using CoreGraphics;
+using Foundation;
+using UIKit;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ItemsViewDelegator<TItemsView, TViewController> : UICollectionViewDelegateFlowLayout
+ where TItemsView : ItemsView
+ where TViewController : ItemsViewController<TItemsView>
+ {
+ public ItemsViewLayout ItemsViewLayout { get; }
+ public TViewController ViewController { get; }
+
+ protected float PreviousHorizontalOffset, PreviousVerticalOffset;
+
+ public ItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
+ {
+ ItemsViewLayout = itemsViewLayout;
+ ViewController = itemsViewController;
+ }
+
+ public override void Scrolled(UIScrollView scrollView)
+ {
+ var indexPathsForVisibleItems = ViewController.CollectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList();
+
+ if (indexPathsForVisibleItems.Count == 0)
+ return;
+
+ var contentInset = scrollView.ContentInset;
+ var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left;
+ var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top;
+
+ var firstVisibleItemIndex = (int)indexPathsForVisibleItems.First().Item;
+
+ var collectionView = ViewController.CollectionView;
+ var centerPoint = new CGPoint(collectionView.Center.X + collectionView.ContentOffset.X, collectionView.Center.Y + collectionView.ContentOffset.Y);
+ var centerIndexPath = collectionView.IndexPathForItemAtPoint(centerPoint);
+ var centerItemIndex = centerIndexPath?.Row ?? firstVisibleItemIndex;
+ var lastVisibleItemIndex = (int)indexPathsForVisibleItems.Last().Item;
+ var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
+ {
+ HorizontalDelta = contentOffsetX - PreviousHorizontalOffset,
+ VerticalDelta = contentOffsetY - PreviousVerticalOffset,
+ HorizontalOffset = contentOffsetX,
+ VerticalOffset = contentOffsetY,
+ FirstVisibleItemIndex = firstVisibleItemIndex,
+ CenterItemIndex = centerItemIndex,
+ LastVisibleItemIndex = lastVisibleItemIndex
+ };
+
+ var itemsView = ViewController.ItemsView;
+ var source = ViewController.ItemsSource;
+ itemsView.SendScrolled(itemsViewScrolledEventArgs);
+
+ PreviousHorizontalOffset = (float)contentOffsetX;
+ PreviousVerticalOffset = (float)contentOffsetY;
+
+ switch (itemsView.RemainingItemsThreshold)
+ {
+ case -1:
+ return;
+ case 0:
+ if (lastVisibleItemIndex == source.ItemCount - 1)
+ itemsView.SendRemainingItemsThresholdReached();
+ break;
+ default:
+ if (source.ItemCount - 1 - lastVisibleItemIndex <= itemsView.RemainingItemsThreshold)
+ itemsView.SendRemainingItemsThresholdReached();
+ break;
+ }
+ }
+
+ public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout,
+ nint section)
+ {
+ if (ItemsViewLayout == null)
+ {
+ return default;
+ }
+
+ return ItemsViewLayout.GetInsetForSection(collectionView, layout, section);
+ }
+
+ public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView,
+ UICollectionViewLayout layout, nint section)
+ {
+ if (ItemsViewLayout == null)
+ {
+ return default;
+ }
+
+ return ItemsViewLayout.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
+ }
+
+ public override nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView,
+ UICollectionViewLayout layout, nint section)
+ {
+ if (ItemsViewLayout == null)
+ {
+ return default;
+ }
+
+ return ItemsViewLayout.GetMinimumLineSpacingForSection(collectionView, layout, section);
+ }
+
+ public override void CellDisplayingEnded(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
+ {
+ if (ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal)
+ {
+ var actualWidth = collectionView.ContentSize.Width - collectionView.Bounds.Size.Width;
+ if (collectionView.ContentOffset.X >= actualWidth || collectionView.ContentOffset.X < 0)
+ return;
+ }
+ else
+ {
+ var actualHeight = collectionView.ContentSize.Height - collectionView.Bounds.Size.Height;
+
+ if (collectionView.ContentOffset.Y >= actualHeight || collectionView.ContentOffset.Y < 0)
+ return;
+ }
+ }
+ }
+}
\ No newline at end of file
namespace Xamarin.Forms.Platform.iOS
{
- public abstract class ItemsViewRenderer : ViewRenderer<ItemsView, UIView>
+ public abstract class ItemsViewRenderer<TItemsView, TViewController> : ViewRenderer<TItemsView, UIView>
+ where TItemsView : ItemsView
+ where TViewController : ItemsViewController<TItemsView>
{
ItemsViewLayout _layout;
bool _disposed;
bool? _defaultHorizontalScrollVisibility;
bool? _defaultVerticalScrollVisibility;
+ protected TItemsView ItemsView => Element;
+
public ItemsViewRenderer()
{
- CollectionView.VerifyCollectionViewFlagEnabled(nameof(ItemsViewRenderer));
+ CollectionView.VerifyCollectionViewFlagEnabled(nameof(ItemsViewRenderer<TItemsView, TViewController>));
}
- public override UIViewController ViewController => ItemsViewController;
+ public override UIViewController ViewController => Controller;
- protected ItemsViewController ItemsViewController { get; private set; }
+ protected TViewController Controller { get; private set; }
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
return Control.GetSizeRequest(widthConstraint, heightConstraint, 0, 0);
}
- protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> e)
+ protected override void OnElementChanged(ElementChangedEventArgs<TItemsView> e)
{
TearDownOldElement(e.OldElement);
SetUpNewElement(e.NewElement);
{
base.OnElementPropertyChanged(sender, changedProperty);
- if (changedProperty.Is(ItemsView.ItemsSourceProperty))
+ if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemsSourceProperty))
{
UpdateItemsSource();
}
- else if (changedProperty.Is(ItemsView.ItemTemplateProperty))
+ else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemTemplateProperty))
{
UpdateLayout();
}
- else if (changedProperty.IsOneOf(ItemsView.EmptyViewProperty, ItemsView.EmptyViewTemplateProperty))
+ else if (changedProperty.IsOneOf(Xamarin.Forms.ItemsView.EmptyViewProperty,
+ Xamarin.Forms.ItemsView.EmptyViewTemplateProperty))
{
- ItemsViewController.UpdateEmptyView();
+ Controller.UpdateEmptyView();
}
- else if (changedProperty.Is(ItemsView.ItemSizingStrategyProperty))
+ else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemSizingStrategyProperty))
{
UpdateItemSizingStrategy();
}
- else if (changedProperty.Is(ItemsView.HorizontalScrollBarVisibilityProperty))
+ else if (changedProperty.Is(Xamarin.Forms.ItemsView.HorizontalScrollBarVisibilityProperty))
{
UpdateHorizontalScrollBarVisibility();
}
- else if (changedProperty.Is(ItemsView.VerticalScrollBarVisibilityProperty))
+ else if (changedProperty.Is(Xamarin.Forms.ItemsView.VerticalScrollBarVisibilityProperty))
{
UpdateVerticalScrollBarVisibility();
}
- else if (changedProperty.Is(ItemsView.ItemsUpdatingScrollModeProperty))
+ else if (changedProperty.Is(Xamarin.Forms.ItemsView.ItemsUpdatingScrollModeProperty))
{
UpdateItemsUpdatingScrollMode();
}
protected abstract ItemsViewLayout SelectLayout();
- protected virtual void TearDownOldElement(ItemsView oldElement)
+ protected virtual void TearDownOldElement(TItemsView oldElement)
{
if (oldElement == null)
{
oldElement.ScrollToRequested -= ScrollToRequested;
}
- protected virtual void SetUpNewElement(ItemsView newElement)
+ protected virtual void SetUpNewElement(TItemsView newElement)
{
if (newElement == null)
{
}
UpdateLayout();
- ItemsViewController = CreateController(newElement, _layout);
+ Controller = CreateController(newElement, _layout);
if (Forms.IsiOS11OrNewer)
{
// CollectionView content when we're in landscape mode (to avoid the notch)
// The SetUseSafeArea Platform Specific is already taking care of this for us
// That said, at some point it's possible folks will want a PS for controlling this behavior
- ItemsViewController.CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
+ Controller.CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
}
- SetNativeControl(ItemsViewController.View);
- ItemsViewController.CollectionView.BackgroundColor = UIColor.Clear;
+ SetNativeControl(Controller.View);
+ Controller.CollectionView.BackgroundColor = UIColor.Clear;
UpdateHorizontalScrollBarVisibility();
UpdateVerticalScrollBarVisibility();
{
_layout = SelectLayout();
- if (ItemsViewController != null)
+ if (Controller != null)
{
- ItemsViewController.UpdateLayout(_layout);
+ Controller.UpdateLayout(_layout);
}
}
protected virtual void UpdateItemsUpdatingScrollMode()
{
- _layout.ItemsUpdatingScrollMode = Element.ItemsUpdatingScrollMode;
+ _layout.ItemsUpdatingScrollMode = ItemsView.ItemsUpdatingScrollMode;
}
protected virtual void UpdateItemsSource()
{
- ItemsViewController.UpdateItemsSource();
+ Controller.UpdateItemsSource();
}
- protected abstract ItemsViewController CreateController(ItemsView newElement, ItemsViewLayout layout);
+ protected abstract TViewController CreateController(TItemsView newElement, ItemsViewLayout layout);
NSIndexPath DetermineIndex(ScrollToRequestEventArgs args)
{
return NSIndexPath.Create(args.GroupIndex, args.Index);
}
- return ItemsViewController.GetIndexForItem(args.Item);
+ return Controller.GetIndexForItem(args.Item);
}
void UpdateVerticalScrollBarVisibility()
{
if (_defaultVerticalScrollVisibility == null)
- _defaultVerticalScrollVisibility = ItemsViewController.CollectionView.ShowsVerticalScrollIndicator;
+ _defaultVerticalScrollVisibility = Controller.CollectionView.ShowsVerticalScrollIndicator;
switch (Element.VerticalScrollBarVisibility)
{
case ScrollBarVisibility.Always:
- ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = true;
+ Controller.CollectionView.ShowsVerticalScrollIndicator = true;
break;
case ScrollBarVisibility.Never:
- ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = false;
+ Controller.CollectionView.ShowsVerticalScrollIndicator = false;
break;
case ScrollBarVisibility.Default:
- ItemsViewController.CollectionView.ShowsVerticalScrollIndicator = _defaultVerticalScrollVisibility.Value;
+ Controller.CollectionView.ShowsVerticalScrollIndicator = _defaultVerticalScrollVisibility.Value;
break;
}
}
void UpdateHorizontalScrollBarVisibility()
{
if (_defaultHorizontalScrollVisibility == null)
- _defaultHorizontalScrollVisibility = ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator;
+ _defaultHorizontalScrollVisibility = Controller.CollectionView.ShowsHorizontalScrollIndicator;
switch (Element.HorizontalScrollBarVisibility)
{
case ScrollBarVisibility.Always:
- ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = true;
+ Controller.CollectionView.ShowsHorizontalScrollIndicator = true;
break;
case ScrollBarVisibility.Never:
- ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = false;
+ Controller.CollectionView.ShowsHorizontalScrollIndicator = false;
break;
case ScrollBarVisibility.Default:
- ItemsViewController.CollectionView.ShowsHorizontalScrollIndicator = _defaultHorizontalScrollVisibility.Value;
+ Controller.CollectionView.ShowsHorizontalScrollIndicator = _defaultHorizontalScrollVisibility.Value;
break;
}
}
return;
}
- ItemsViewController.CollectionView.ScrollToItem(indexPath,
+ Controller.CollectionView.ScrollToItem(indexPath,
args.ScrollToPosition.ToCollectionViewScrollPosition(_layout.ScrollDirection), args.IsAnimated);
}
}
{
TearDownOldElement(Element);
- ItemsViewController?.Dispose();
- ItemsViewController = null;
+ Controller?.Dispose();
+ Controller = null;
}
base.Dispose(disposing);
return false;
}
- var collectionView = ItemsViewController.CollectionView;
+ var collectionView = Controller.CollectionView;
if (indexPath.Section >= collectionView.NumberOfSections())
{
return false;
namespace Xamarin.Forms.Platform.iOS
{
- public class SelectableItemsViewController : StructuredItemsViewController
+ public class SelectableItemsViewController<TItemsView> : StructuredItemsViewController<TItemsView>
+ where TItemsView : SelectableItemsView
{
- SelectableItemsView SelectableItemsView => (SelectableItemsView)ItemsView;
-
- public SelectableItemsViewController(SelectableItemsView selectableItemsView, ItemsViewLayout layout)
+ public SelectableItemsViewController(TItemsView selectableItemsView, ItemsViewLayout layout)
: base(selectableItemsView, layout)
{
}
+ protected override UICollectionViewDelegateFlowLayout CreateDelegator()
+ {
+ return new SelectableItemsViewDelegator<TItemsView, SelectableItemsViewController<TItemsView>>(ItemsViewLayout, this);
+ }
+
// _Only_ called if the user initiates the selection change; will not be called for programmatic selection
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
{
void FormsSelectItem(NSIndexPath indexPath)
{
- var mode = SelectableItemsView.SelectionMode;
+ var mode = ItemsView.SelectionMode;
switch (mode)
{
case SelectionMode.None:
break;
case SelectionMode.Single:
- SelectableItemsView.SelectedItem = GetItemAtIndex(indexPath);
+ ItemsView.SelectedItem = GetItemAtIndex(indexPath);
break;
case SelectionMode.Multiple:
- SelectableItemsView.SelectedItems.Add(GetItemAtIndex(indexPath));
+ ItemsView.SelectedItems.Add(GetItemAtIndex(indexPath));
break;
}
}
void FormsDeselectItem(NSIndexPath indexPath)
{
- var mode = SelectableItemsView.SelectionMode;
+ var mode = ItemsView.SelectionMode;
switch (mode)
{
case SelectionMode.Single:
break;
case SelectionMode.Multiple:
- SelectableItemsView.SelectedItems.Remove(GetItemAtIndex(indexPath));
+ ItemsView.SelectedItems.Remove(GetItemAtIndex(indexPath));
break;
}
}
internal void UpdateNativeSelection()
{
- if (SelectableItemsView == null)
+ if (ItemsView == null)
{
return;
}
- var mode = SelectableItemsView.SelectionMode;
+ var mode = ItemsView.SelectionMode;
switch (mode)
{
case SelectionMode.None:
return;
case SelectionMode.Single:
- var selectedItem = SelectableItemsView.SelectedItem;
+ var selectedItem = ItemsView.SelectedItem;
if (selectedItem != null)
{
internal void UpdateSelectionMode()
{
- var mode = SelectableItemsView.SelectionMode;
+ var mode = ItemsView.SelectionMode;
switch (mode)
{
void SynchronizeNativeSelectionWithSelectedItems()
{
- var selectedItems = SelectableItemsView.SelectedItems;
+ var selectedItems = ItemsView.SelectedItems;
var selectedIndexPaths = CollectionView.GetIndexPathsForSelectedItems();
foreach (var path in selectedIndexPaths)
--- /dev/null
+using Foundation;
+using UIKit;
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SelectableItemsViewDelegator<TItemsView, TViewController> : ItemsViewDelegator<TItemsView, TViewController>
+ where TItemsView : SelectableItemsView
+ where TViewController : SelectableItemsViewController<TItemsView>
+ {
+ public SelectableItemsViewDelegator(ItemsViewLayout itemsViewLayout, TViewController itemsViewController)
+ : base(itemsViewLayout, itemsViewController)
+ {
+ }
+
+ public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
+ {
+ ViewController?.ItemSelected(collectionView, indexPath);
+ }
+
+ public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath)
+ {
+ ViewController?.ItemDeselected(collectionView, indexPath);
+ }
+ }
+}
\ No newline at end of file
namespace Xamarin.Forms.Platform.iOS
{
- public class SelectableItemsViewRenderer : StructuredItemsViewRenderer
+ public class SelectableItemsViewRenderer<TItemsView, TViewController> : StructuredItemsViewRenderer<TItemsView, TViewController>
+ where TItemsView : SelectableItemsView
+ where TViewController : SelectableItemsViewController<TItemsView>
{
- SelectableItemsView SelectableItemsView => (SelectableItemsView)Element;
- SelectableItemsViewController SelectableItemsViewController => (SelectableItemsViewController)ItemsViewController;
-
- protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
+ protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
- return new SelectableItemsViewController(itemsView as SelectableItemsView, layout);
+ return new SelectableItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
}
}
- protected override void SetUpNewElement(ItemsView newElement)
+ protected override void SetUpNewElement(TItemsView newElement)
{
- if (newElement != null && !(newElement is SelectableItemsView))
- {
- throw new ArgumentException($"{nameof(newElement)} must be of type {typeof(SelectableItemsView).Name}");
- }
-
base.SetUpNewElement(newElement);
if (newElement == null)
protected virtual void UpdateNativeSelection()
{
- SelectableItemsViewController.UpdateNativeSelection();
+ Controller.UpdateNativeSelection();
}
protected virtual void UpdateSelectionMode()
{
- SelectableItemsViewController.UpdateSelectionMode();
+ Controller.UpdateSelectionMode();
}
protected override void UpdateItemsSource()
namespace Xamarin.Forms.Platform.iOS
{
- public class StructuredItemsViewController : ItemsViewController
+ public class StructuredItemsViewController<TItemsView> : ItemsViewController<TItemsView>
+ where TItemsView : StructuredItemsView
{
bool _disposed;
- StructuredItemsView StructuredItemsView => (StructuredItemsView)ItemsView;
-
UIView _headerUIView;
VisualElement _headerViewFormsElement;
UIView _footerUIView;
VisualElement _footerViewFormsElement;
- public StructuredItemsViewController(StructuredItemsView structuredItemsView, ItemsViewLayout layout)
+ public StructuredItemsViewController(TItemsView structuredItemsView, ItemsViewLayout layout)
: base(structuredItemsView, layout)
{
}
base.Dispose(disposing);
}
- protected override bool IsHorizontal => (StructuredItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
+ protected override bool IsHorizontal => (ItemsView?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
public override void ViewWillLayoutSubviews()
{
internal void UpdateFooterView()
{
- UpdateSubview(StructuredItemsView?.Footer, StructuredItemsView?.FooterTemplate,
+ UpdateSubview(ItemsView?.Footer, ItemsView?.FooterTemplate,
ref _footerUIView, ref _footerViewFormsElement);
UpdateHeaderFooterPosition();
}
internal void UpdateHeaderView()
{
- UpdateSubview(StructuredItemsView?.Header, StructuredItemsView?.HeaderTemplate,
+ UpdateSubview(ItemsView?.Header, ItemsView?.HeaderTemplate,
ref _headerUIView, ref _headerViewFormsElement);
UpdateHeaderFooterPosition();
}
namespace Xamarin.Forms.Platform.iOS
{
- public class StructuredItemsViewRenderer : ItemsViewRenderer
+ public class StructuredItemsViewRenderer<TItemsView, TViewController> : ItemsViewRenderer<TItemsView, TViewController>
+ where TItemsView : StructuredItemsView
+ where TViewController : StructuredItemsViewController<TItemsView>
{
- StructuredItemsView StructuredItemsView => (StructuredItemsView)Element;
- StructuredItemsViewController StructuredItemsViewController => (StructuredItemsViewController)ItemsViewController;
-
- protected override ItemsViewController CreateController(ItemsView itemsView, ItemsViewLayout layout)
+ protected override TViewController CreateController(TItemsView itemsView, ItemsViewLayout layout)
{
- return new StructuredItemsViewController(itemsView as StructuredItemsView, layout);
+ return new StructuredItemsViewController<TItemsView>(itemsView, layout) as TViewController;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs changedProperty)
if (changedProperty.IsOneOf(StructuredItemsView.HeaderProperty, StructuredItemsView.HeaderTemplateProperty))
{
- StructuredItemsViewController.UpdateHeaderView();
+ UpdateHeaderView();
}
else if (changedProperty.IsOneOf(StructuredItemsView.FooterProperty, StructuredItemsView.FooterTemplateProperty))
{
- StructuredItemsViewController.UpdateFooterView();
+ UpdateFooterView();
}
else if (changedProperty.Is(StructuredItemsView.ItemsLayoutProperty))
{
- StructuredItemsViewController.UpdateLayout(SelectLayout());
+ UpdateLayout();
}
}
- protected override void SetUpNewElement(ItemsView newElement)
+ protected override void SetUpNewElement(TItemsView newElement)
{
base.SetUpNewElement(newElement);
return;
}
- StructuredItemsViewController.UpdateFooterView();
- StructuredItemsViewController.UpdateHeaderView();
+ Controller.UpdateFooterView();
+ Controller.UpdateHeaderView();
}
protected override ItemsViewLayout SelectLayout()
{
- var itemSizingStrategy = StructuredItemsView.ItemSizingStrategy;
- var itemsLayout = StructuredItemsView.ItemsLayout;
+ var itemSizingStrategy = ItemsView.ItemSizingStrategy;
+ var itemsLayout = ItemsView.ItemsLayout;
if (itemsLayout is GridItemsLayout gridItemsLayout)
{
return new ListViewLayout(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), itemSizingStrategy);
}
+ protected virtual void UpdateHeaderView()
+ {
+ Controller.UpdateHeaderView();
+ }
+
+ protected virtual void UpdateFooterView()
+ {
+ Controller.UpdateFooterView();
+ }
+
public override void LayoutSubviews()
{
base.LayoutSubviews();
- StructuredItemsViewController.UpdateLayoutMeasurements();
+ Controller.UpdateLayoutMeasurements();
}
}
}
\ No newline at end of file
+++ /dev/null
-using System;
-using System.Linq;
-using CoreGraphics;
-using Foundation;
-using UIKit;
-
-namespace Xamarin.Forms.Platform.iOS
-{
- public class UICollectionViewDelegator : UICollectionViewDelegateFlowLayout
- {
- float _previousHorizontalOffset, _previousVerticalOffset;
-
- public ItemsViewLayout ItemsViewLayout { get; }
- public ItemsViewController ItemsViewController { get; }
- public SelectableItemsViewController SelectableItemsViewController => ItemsViewController as SelectableItemsViewController;
-
- public GroupableItemsViewController GroupableItemsViewController => ItemsViewController as GroupableItemsViewController;
-
- public UICollectionViewDelegator(ItemsViewLayout itemsViewLayout, ItemsViewController itemsViewController)
- {
- ItemsViewLayout = itemsViewLayout;
- ItemsViewController = itemsViewController;
- }
- public CarouselViewController CarouselViewController { get; set; }
-
- public override void DraggingStarted(UIScrollView scrollView)
- {
- CarouselViewController?.DraggingStarted(scrollView);
-
- _previousHorizontalOffset = (float)scrollView.ContentOffset.X;
- _previousVerticalOffset = (float)scrollView.ContentOffset.Y;
- }
-
- public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
- {
- _previousHorizontalOffset = 0;
- _previousVerticalOffset = 0;
-
- CarouselViewController?.DraggingEnded(scrollView, willDecelerate);
- }
-
- public override void Scrolled(UIScrollView scrollView)
- {
- var indexPathsForVisibleItems = ItemsViewController.CollectionView.IndexPathsForVisibleItems.OrderBy(x => x.Row).ToList();
-
- if (indexPathsForVisibleItems.Count == 0)
- return;
-
- var contentInset = scrollView.ContentInset;
- var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left;
- var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top;
-
- var firstVisibleItemIndex = (int)indexPathsForVisibleItems.First().Item;
- var centerPoint = new CGPoint(ItemsViewController.CollectionView.Center.X + ItemsViewController.CollectionView.ContentOffset.X, ItemsViewController.CollectionView.Center.Y + ItemsViewController.CollectionView.ContentOffset.Y);
- var centerIndexPath = ItemsViewController.CollectionView.IndexPathForItemAtPoint(centerPoint);
- var centerItemIndex = centerIndexPath?.Row ?? firstVisibleItemIndex;
- var lastVisibleItemIndex = (int)indexPathsForVisibleItems.Last().Item;
- var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
- {
- HorizontalDelta = contentOffsetX - _previousHorizontalOffset,
- VerticalDelta = contentOffsetY - _previousVerticalOffset,
- HorizontalOffset = contentOffsetX,
- VerticalOffset = contentOffsetY,
- FirstVisibleItemIndex = firstVisibleItemIndex,
- CenterItemIndex = centerItemIndex,
- LastVisibleItemIndex = lastVisibleItemIndex
- };
-
- ItemsViewController.ItemsView.SendScrolled(itemsViewScrolledEventArgs);
-
- _previousHorizontalOffset = (float)contentOffsetX;
- _previousVerticalOffset = (float)contentOffsetY;
-
- switch (ItemsViewController.ItemsView.RemainingItemsThreshold)
- {
- case -1:
- return;
- case 0:
- if (lastVisibleItemIndex == ItemsViewController.ItemsSource.ItemCount - 1)
- ItemsViewController.ItemsView.SendRemainingItemsThresholdReached();
- break;
- default:
- if (ItemsViewController.ItemsSource.ItemCount - 1 - lastVisibleItemIndex <= ItemsViewController.ItemsView.RemainingItemsThreshold)
- ItemsViewController.ItemsView.SendRemainingItemsThresholdReached();
- break;
- }
- }
-
- public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout,
- nint section)
- {
- if (ItemsViewLayout == null)
- {
- return default(UIEdgeInsets);
- }
-
- return ItemsViewLayout.GetInsetForSection(collectionView, layout, section);
- }
-
- public override nfloat GetMinimumInteritemSpacingForSection(UICollectionView collectionView,
- UICollectionViewLayout layout, nint section)
- {
- if (ItemsViewLayout == null)
- {
- return default(nfloat);
- }
-
- return ItemsViewLayout.GetMinimumInteritemSpacingForSection(collectionView, layout, section);
- }
-
- public override nfloat GetMinimumLineSpacingForSection(UICollectionView collectionView,
- UICollectionViewLayout layout, nint section)
- {
- if (ItemsViewLayout == null)
- {
- return default(nfloat);
- }
-
- return ItemsViewLayout.GetMinimumLineSpacingForSection(collectionView, layout, section);
- }
-
- public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
- {
- SelectableItemsViewController?.ItemSelected(collectionView, indexPath);
- }
-
- public override void ItemDeselected(UICollectionView collectionView, NSIndexPath indexPath)
- {
- SelectableItemsViewController?.ItemDeselected(collectionView, indexPath);
- }
-
- public override void CellDisplayingEnded(UICollectionView collectionView, UICollectionViewCell cell, NSIndexPath indexPath)
- {
- if (ItemsViewLayout.ScrollDirection == UICollectionViewScrollDirection.Horizontal)
- {
- var actualWidth = collectionView.ContentSize.Width - collectionView.Bounds.Size.Width;
- if (collectionView.ContentOffset.X >= actualWidth || collectionView.ContentOffset.X < 0)
- return;
- }
- else
- {
- var actualHeight = collectionView.ContentSize.Height - collectionView.Bounds.Size.Height;
-
- if (collectionView.ContentOffset.Y >= actualHeight || collectionView.ContentOffset.Y < 0)
- return;
- }
- }
-
- public override CGSize GetReferenceSizeForHeader(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
- {
- if (GroupableItemsViewController == null)
- {
- return CGSize.Empty;
- }
-
- return GroupableItemsViewController.GetReferenceSizeForHeader(collectionView, layout, section);
- }
-
- public override CGSize GetReferenceSizeForFooter(UICollectionView collectionView, UICollectionViewLayout layout, nint section)
- {
- if (GroupableItemsViewController == null)
- {
- return CGSize.Empty;
- }
-
- return GroupableItemsViewController.GetReferenceSizeForFooter(collectionView, layout, section);
- }
-
- public override void ScrollAnimationEnded(UIScrollView scrollView)
- {
- GroupableItemsViewController?.HandleScrollAnimationEnded();
- }
- }
-}
\ No newline at end of file
<Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CellExtensions.cs" />
<Compile Include="CADisplayLinkTicker.cs" />
+ <Compile Include="CollectionView\CarouselViewDelegator.cs" />
<Compile Include="CollectionView\CarouselViewRenderer.cs" />
<Compile Include="CollectionView\CollectionViewRenderer.cs" />
<Compile Include="CollectionView\EmptySource.cs" />
<Compile Include="CollectionView\GroupableItemsViewController.cs" />
+ <Compile Include="CollectionView\GroupableItemsViewDelegator.cs" />
<Compile Include="CollectionView\GroupableItemsViewRenderer.cs" />
<Compile Include="CollectionView\HorizontalCell.cs" />
<Compile Include="CollectionView\HorizontalDefaultSupplementalView.cs" />
<Compile Include="CollectionView\ObservableGroupedSource.cs" />
<Compile Include="CollectionView\ScrollToPositionExtensions.cs" />
<Compile Include="CollectionView\SelectableItemsViewController.cs" />
+ <Compile Include="CollectionView\SelectableItemsViewDelegator.cs" />
<Compile Include="CollectionView\SelectableItemsViewRenderer.cs" />
<Compile Include="CollectionView\TemplateHelpers.cs" />
- <Compile Include="CollectionView\UICollectionViewDelegator.cs" />
+ <Compile Include="CollectionView\ItemsViewDelegator.cs" />
<Compile Include="CollectionView\VerticalCell.cs" />
<Compile Include="CollectionView\StructuredItemsViewController.cs" />
<Compile Include="CollectionView\StructuredItemsViewRenderer.cs" />