[iOS] Various fixes with ItemsViewController (#7618)
authoradrianknight89 <adrianknight89@outlook.com>
Tue, 15 Oct 2019 08:32:26 +0000 (03:32 -0500)
committerRui Marinho <me@ruimarinho.net>
Tue, 15 Oct 2019 08:32:26 +0000 (09:32 +0100)
* various fixes

* remove comment

* move delegator setting to ViewDidLoad

* fix delegator

* fix accessibility issue

Xamarin.Forms.Platform.iOS/CollectionView/ItemsSourceFactory.cs
Xamarin.Forms.Platform.iOS/CollectionView/ItemsViewController.cs
Xamarin.Forms.Platform.iOS/CollectionView/ItemsViewRenderer.cs
Xamarin.Forms.Platform.iOS/CollectionView/StructuredItemsViewController.cs

index e637cf3..7ec7df2 100644 (file)
@@ -16,13 +16,12 @@ namespace Xamarin.Forms.Platform.iOS
 
                        switch (itemsSource)
                        {
-                               case IList _ when itemsSource is INotifyCollectionChanged:
+                               case INotifyCollectionChanged _:
                                        return new ObservableItemsSource(itemsSource as IList, collectionView);
-                               case IEnumerable<object> generic:
-                                       return new ListSource(generic);
+                               case IEnumerable _:
+                               default:
+                                       return new ListSource(itemsSource);
                        }
-
-                       return new ListSource(itemsSource);
                }
 
                public static IItemsViewSource CreateGrouped(IEnumerable itemsSource, UICollectionView collectionView)
index 8a2549b..8102155 100644 (file)
@@ -1,17 +1,12 @@
 using System;
-using System.Drawing;
-using System.Threading.Tasks;
-using CoreGraphics;
 using Foundation;
 using UIKit;
-using Xamarin.Forms.Internals;
 
 namespace Xamarin.Forms.Platform.iOS
 {
-       // TODO hartez 2018/06/01 14:21:24 Add a method for updating the layout 
        public abstract class ItemsViewController<TItemsView> : UICollectionViewController
-               where TItemsView : ItemsView
-       {
+       where TItemsView : ItemsView
+       { 
                public IItemsViewSource ItemsSource { get; protected set; }
                public TItemsView ItemsView { get; }
                protected ItemsViewLayout ItemsViewLayout { get; set; }
@@ -29,32 +24,28 @@ namespace Xamarin.Forms.Platform.iOS
                public ItemsViewController(TItemsView itemsView, ItemsViewLayout layout) : base(layout)
                {
                        ItemsView = itemsView;
-                       ItemsSource = CreateItemsViewSource();
-
-                       UpdateLayout(layout);
+                       ItemsViewLayout = layout;
                }
 
-               public void UpdateLayout(ItemsViewLayout layout)
+               public void UpdateLayout(ItemsViewLayout newLayout)
                {
-                       ItemsViewLayout = layout;
-                       ItemsViewLayout.GetPrototype = GetPrototype;
+                       // Ignore calls to this method if the new layout is the same as the old one
+                       if (CollectionView.CollectionViewLayout == newLayout)
+                               return;
 
-                       Delegator = CreateDelegator();
+                       ItemsViewLayout = newLayout;
+                       ItemsViewLayout.GetPrototype = GetPrototype;
 
+            Delegator = CreateDelegator();
                        CollectionView.Delegate = Delegator;
 
-                       if (CollectionView.CollectionViewLayout != ItemsViewLayout)
-                       {
-                               // We're updating from a previous layout
-
-                               // Make sure the new layout is sized properly
-                               ItemsViewLayout.ConstrainTo(CollectionView.Bounds.Size);
+                       // Make sure the new layout is sized properly
+                       ItemsViewLayout.ConstrainTo(CollectionView.Bounds.Size);
 
-                               CollectionView.SetCollectionViewLayout(ItemsViewLayout, false);
+                       CollectionView.SetCollectionViewLayout(ItemsViewLayout, false);
 
-                               // Reload the data so the currently visible cells get laid out according to the new layout
-                               CollectionView.ReloadData();
-                       }
+                       // Reload the data so the currently visible cells get laid out according to the new layout
+                       CollectionView.ReloadData();
                }
 
                protected override void Dispose(bool disposing)
@@ -65,8 +56,13 @@ namespace Xamarin.Forms.Platform.iOS
                        if (disposing)
                        {
                                ItemsSource?.Dispose();
+
                                _emptyUIView?.Dispose();
                                _emptyUIView = null;
+
+                               _backgroundUIView?.Dispose();
+                               _backgroundUIView = null;
+
                                _emptyViewFormsElement = null;
                        }
 
@@ -94,11 +90,9 @@ namespace Xamarin.Forms.Platform.iOS
 
                public override nint GetItemsCount(UICollectionView collectionView, nint section)
                {
-                       var count = ItemsSource.ItemCountInGroup(section);
-
                        CheckForEmptySource();
 
-                       return count;
+                       return ItemsSource.ItemCountInGroup(section);
                }
 
                void CheckForEmptySource()
@@ -124,7 +118,24 @@ namespace Xamarin.Forms.Platform.iOS
                public override void ViewDidLoad()
                {
                        base.ViewDidLoad();
-                       AutomaticallyAdjustsScrollViewInsets = false;
+
+                       ItemsSource = CreateItemsViewSource();
+                       ItemsViewLayout.GetPrototype = GetPrototype;
+
+                       Delegator = CreateDelegator();
+                       CollectionView.Delegate = Delegator;
+
+                       if (!Forms.IsiOS11OrNewer)
+                               AutomaticallyAdjustsScrollViewInsets = false;
+                       else
+                       {
+                               // We set this property to keep iOS from trying to be helpful about insetting all the 
+                               // 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
+                               CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
+                       }
+
                        RegisterViewTypes();
                }
 
@@ -256,8 +267,7 @@ namespace Xamarin.Forms.Platform.iOS
                {
                        CollectionView.RegisterClassForCell(typeof(HorizontalDefaultCell), HorizontalDefaultCell.ReuseId);
                        CollectionView.RegisterClassForCell(typeof(VerticalDefaultCell), VerticalDefaultCell.ReuseId);
-                       CollectionView.RegisterClassForCell(typeof(HorizontalCell),
-                               HorizontalCell.ReuseId);
+                       CollectionView.RegisterClassForCell(typeof(HorizontalCell), HorizontalCell.ReuseId);
                        CollectionView.RegisterClassForCell(typeof(VerticalCell), VerticalCell.ReuseId);
                }
 
@@ -280,38 +290,7 @@ namespace Xamarin.Forms.Platform.iOS
                                _emptyViewFormsElement.Layout(CollectionView.Frame.ToRectangle());
                }
 
-               protected void UpdateSubview(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
-               {
-                       uiView?.RemoveFromSuperview();
-
-                       if (formsElement != null)
-                       {
-                               ItemsView.RemoveLogicalChild(formsElement);
-                               formsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
-                       }
-
-                       UpdateView(view, viewTemplate, ref uiView, ref formsElement);
-
-                       if (uiView != null)
-                       {
-                               CollectionView.AddSubview(uiView);
-                       }
-
-                       if (formsElement != null)
-                               ItemsView.AddLogicalChild(formsElement);
-
-                       if (formsElement != null)
-                       {
-                               RemeasureLayout(formsElement);
-                               formsElement.MeasureInvalidated += OnFormsElementMeasureInvalidated;
-                       }
-                       else if (uiView != null)
-                       {
-                               uiView.SizeToFit();
-                       }
-               }
-
-               void RemeasureLayout(VisualElement formsElement)
+               protected void RemeasureLayout(VisualElement formsElement)
                {
                        if (IsHorizontal)
                        {
@@ -325,7 +304,7 @@ namespace Xamarin.Forms.Platform.iOS
                        }
                }
 
-               void OnFormsElementMeasureInvalidated(object sender, EventArgs e)
+               protected void OnFormsElementMeasureInvalidated(object sender, EventArgs e)
                {
                        if (sender is VisualElement formsElement)
                        {
@@ -346,16 +325,16 @@ namespace Xamarin.Forms.Platform.iOS
                                if (formsElement != null)
                                        Platform.GetRenderer(formsElement)?.DisposeRendererAndChildren();
 
+                               uiView?.Dispose();
                                uiView = null;
+
                                formsElement = null;
                        }
                        else
                        {
                                // Create the native renderer for the view, and keep the actual Forms element (if any)
                                // around for updating the layout later
-                               var (NativeView, FormsElement) = TemplateHelpers.RealizeView(view, viewTemplate, ItemsView);
-                               uiView = NativeView;
-                               formsElement = FormsElement;
+                               (uiView, formsElement) = TemplateHelpers.RealizeView(view, viewTemplate, ItemsView);
                        }
                }
 
@@ -372,7 +351,6 @@ namespace Xamarin.Forms.Platform.iOS
                                // Replace any current background with the EmptyView. This will also set the native empty view's frame
                                // to match the UICollectionView's frame
                                CollectionView.BackgroundView = _emptyUIView;
-                               _currentBackgroundIsEmptyView = true;
 
                                if (_emptyViewFormsElement != null)
                                {
@@ -385,6 +363,8 @@ namespace Xamarin.Forms.Platform.iOS
                                        // the Forms layout for its content
                                        _emptyViewFormsElement.Layout(_emptyUIView.Frame.ToRectangle());
                                }
+
+                               _currentBackgroundIsEmptyView = true;
                        }
                        else
                        {
index da58ed1..97bf144 100644 (file)
@@ -95,14 +95,6 @@ namespace Xamarin.Forms.Platform.iOS
                        UpdateLayout();
                        Controller = CreateController(newElement, _layout);
                         
-                       if (Forms.IsiOS11OrNewer)
-                       {
-                               // We set this property to keep iOS from trying to be helpful about insetting all the 
-                               // 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
-                               Controller.CollectionView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
-                       }
 
                        SetNativeControl(Controller.View);
                        Controller.CollectionView.BackgroundColor = UIColor.Clear;
index c5bef8b..0fbbe13 100644 (file)
@@ -77,6 +77,37 @@ namespace Xamarin.Forms.Platform.iOS
                        UpdateHeaderFooterPosition();
                }
 
+               internal void UpdateSubview(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
+               {
+                       uiView?.RemoveFromSuperview();
+
+                       if (formsElement != null)
+                       {
+                               ItemsView.RemoveLogicalChild(formsElement);
+                               formsElement.MeasureInvalidated -= OnFormsElementMeasureInvalidated;
+                       }
+
+                       UpdateView(view, viewTemplate, ref uiView, ref formsElement);
+
+                       if (uiView != null)
+                       {
+                               CollectionView.AddSubview(uiView);
+                       }
+
+                       if (formsElement != null)
+                               ItemsView.AddLogicalChild(formsElement);
+
+                       if (formsElement != null)
+                       {
+                               RemeasureLayout(formsElement);
+                               formsElement.MeasureInvalidated += OnFormsElementMeasureInvalidated;
+                       }
+                       else if (uiView != null)
+                       {
+                               uiView.SizeToFit();
+                       }
+               }
+
                void UpdateHeaderFooterPosition()
                {
                        if (IsHorizontal)