summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs151
1 files changed, 86 insertions, 65 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
index 7fd68cc0..f6cccd54 100644
--- a/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs
@@ -25,7 +25,6 @@ namespace Xamarin.Forms.Platform.iOS
KeyboardInsetTracker _insetTracker;
RectangleF _previousFrame;
ScrollToRequestedEventArgs _requestedScroll;
- bool _shouldEstimateRowHeight = true;
FormsUITableViewController _tableViewController;
ListView ListView => Element;
@@ -212,7 +211,6 @@ namespace Xamarin.Forms.Platform.iOS
Control.SetContentOffset(offset, true);
});
}
- _shouldEstimateRowHeight = true;
var listView = e.NewElement;
@@ -366,35 +364,36 @@ namespace Xamarin.Forms.Platform.iOS
void UpdateEstimatedRowHeight()
{
- var rowHeight = Element.RowHeight;
- if (Element.HasUnevenRows && rowHeight == -1)
- {
- var source = _dataSource as UnevenListViewDataSource;
-
- // We want to make sure we reset the cached defined row heights whenever this is called.
- // Failing to do this will regress Bugzilla 43313 (strange animation when adding rows with uneven heights)
- source?.CacheDefinedRowHeights();
+ if (_estimatedRowHeight)
+ return;
- if (_shouldEstimateRowHeight && !_estimatedRowHeight)
- {
- if (source != null)
- {
- Control.EstimatedRowHeight = source.GetEstimatedRowHeight(Control);
- _estimatedRowHeight = true;
- }
- else
- {
- //We need to set a default estimated row height, because re-setting it later(when we have items on the TIL)
- //will cause the UITableView to reload, and throw an Exception
- Control.EstimatedRowHeight = DefaultRowHeight;
- }
- }
- }
- else if (!_estimatedRowHeight)
+ // if even rows OR uneven rows but user specified a row height anyway...
+ if (!Element.HasUnevenRows || Element.RowHeight != -1)
{
Control.EstimatedRowHeight = 0;
_estimatedRowHeight = true;
+ return;
}
+
+ var source = _dataSource as UnevenListViewDataSource;
+
+ // We want to make sure we reset the cached defined row heights whenever this is called.
+ // Failing to do this will regress Bugzilla 43313
+ // (strange animation when adding rows with uneven heights)
+ //source?.CacheDefinedRowHeights();
+
+ if (source == null)
+ {
+ // We need to set a default estimated row height,
+ // because re-setting it later(when we have items on the TIL)
+ // will cause the UITableView to reload, and throw an Exception
+ Control.EstimatedRowHeight = DefaultRowHeight;
+ return;
+ }
+
+ Control.EstimatedRowHeight = source.GetEstimatedRowHeight(Control);
+ _estimatedRowHeight = true;
+ return;
}
void UpdateFooter()
@@ -627,9 +626,7 @@ namespace Xamarin.Forms.Platform.iOS
{
IVisualElementRenderer _prototype;
bool _disposed;
- bool _useEstimatedRowHeight;
-
- ConcurrentDictionary<NSIndexPath, nfloat> _rowHeights = new ConcurrentDictionary<NSIndexPath, nfloat>();
+ Dictionary<object, Cell> _prototypicalCellByTypeOrDataTemplate = new Dictionary<object, Cell>();
public UnevenListViewDataSource(ListView list, FormsUITableViewController uiTableViewController) : base(list, uiTableViewController)
{
@@ -639,24 +636,6 @@ namespace Xamarin.Forms.Platform.iOS
{
}
- internal void CacheDefinedRowHeights()
- {
- Task.Run(() =>
- {
- var templatedItems = TemplatedItemsView.TemplatedItems;
-
- foreach (var cell in templatedItems)
- {
- if (_disposed)
- return;
-
- double? cellRenderHeight = cell?.RenderHeight;
- if (cellRenderHeight > 0)
- _rowHeights[cell.GetIndexPath()] = (nfloat)cellRenderHeight;
- }
- });
- }
-
internal nfloat GetEstimatedRowHeight(UITableView table)
{
if (List.RowHeight != -1)
@@ -692,22 +671,42 @@ namespace Xamarin.Forms.Platform.iOS
return CalculateHeightForCell(table, firstCell);
}
- public override nfloat EstimatedHeight(UITableView tableView, NSIndexPath indexPath)
+ internal override void InvalidatePrototypicalCellCache()
+ {
+ _prototypicalCellByTypeOrDataTemplate.Clear();
+ }
+
+ internal Cell GetPrototypicalCell(NSIndexPath indexPath)
{
- if (_useEstimatedRowHeight)
- return tableView.EstimatedRowHeight;
+ var itemTypeOrDataTemplate = default(object);
+
+ var cachingStrategy = List.CachingStrategy;
+ if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
+ itemTypeOrDataTemplate = GetDataTemplateForPath(indexPath);
+
+ else if (cachingStrategy == ListViewCachingStrategy.RecycleElementAndDataTemplate)
+ itemTypeOrDataTemplate = GetItemTypeForPath(indexPath);
+
+ else // ListViewCachingStrategy.RetainElement
+ return GetCellForPath(indexPath);
- // Note: It is *not* an optimization to first check if the array has any values.
- nfloat specifiedRowHeight;
- if (_rowHeights.TryGetValue(indexPath, out specifiedRowHeight) && specifiedRowHeight > 0)
- return specifiedRowHeight;
- return UITableView.AutomaticDimension;
+ Cell protoCell;
+ if (!_prototypicalCellByTypeOrDataTemplate.TryGetValue(itemTypeOrDataTemplate, out protoCell))
+ {
+ // cache prototypical cell by item type; Items of the same Type share
+ // the same DataTemplate (this is enforced by RecycleElementAndDataTemplate)
+ protoCell = GetCellForPath(indexPath);
+ _prototypicalCellByTypeOrDataTemplate[itemTypeOrDataTemplate] = protoCell;
+ }
+
+ var templatedItems = GetTemplatedItemsListForPath(indexPath);
+ return templatedItems.UpdateContent(protoCell, indexPath.Row);
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
- var cell = GetCellForPath(indexPath);
+ var cell = GetPrototypicalCell(indexPath);
if (List.RowHeight == -1 && cell.Height == -1 && cell is ViewCell)
return UITableView.AutomaticDimension;
@@ -745,7 +744,7 @@ namespace Xamarin.Forms.Platform.iOS
// Let the EstimatedHeight method know to use this value.
// Much more efficient than checking the value each time.
- _useEstimatedRowHeight = true;
+ //_useEstimatedRowHeight = true;
return (nfloat)req.Request.Height;
}
@@ -818,6 +817,10 @@ namespace Xamarin.Forms.Platform.iOS
get { return UIColor.Clear; }
}
+ internal virtual void InvalidatePrototypicalCellCache()
+ {
+ }
+
public override void DraggingEnded(UIScrollView scrollView, bool willDecelerate)
{
_isDragging = false;
@@ -840,13 +843,14 @@ namespace Xamarin.Forms.Platform.iOS
cell = GetCellForPath(indexPath);
nativeCell = CellTableViewCell.GetNativeCell(tableView, cell);
}
- else if (cachingStrategy == ListViewCachingStrategy.RecycleElement)
+ else if ((cachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
{
var id = TemplateIdForPath(indexPath);
nativeCell = tableView.DequeueReusableCell(ContextActionsCell.Key + id);
if (nativeCell == null)
{
cell = GetCellForPath(indexPath);
+
nativeCell = CellTableViewCell.GetNativeCell(tableView, cell, true, id.ToString());
}
else
@@ -966,7 +970,7 @@ namespace Xamarin.Forms.Platform.iOS
return;
Cell formsCell = null;
- if (List.CachingStrategy == ListViewCachingStrategy.RecycleElement)
+ if ((List.CachingStrategy & ListViewCachingStrategy.RecycleElement) != 0)
formsCell = (Cell)((INativeElementView)cell).Element;
SetCellBackgroundColor(cell, UIColor.Clear);
@@ -1035,12 +1039,32 @@ namespace Xamarin.Forms.Platform.iOS
_uiTableView.ReloadData();
}
- protected Cell GetCellForPath(NSIndexPath indexPath)
+ protected ITemplatedItemsList<Cell> GetTemplatedItemsListForPath(NSIndexPath indexPath)
{
var templatedItems = TemplatedItemsView.TemplatedItems;
if (List.IsGroupingEnabled)
- templatedItems = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedItems)[indexPath.Section];
+ templatedItems = (ITemplatedItemsList<Cell>)((IList)templatedItems)[indexPath.Section];
+ return templatedItems;
+ }
+
+ protected DataTemplate GetDataTemplateForPath(NSIndexPath indexPath)
+ {
+ var templatedList = GetTemplatedItemsListForPath(indexPath);
+ var item = templatedList.ListProxy[indexPath.Row];
+ return templatedList.SelectDataTemplate(item);
+ }
+
+ protected Type GetItemTypeForPath(NSIndexPath indexPath)
+ {
+ var templatedList = GetTemplatedItemsListForPath(indexPath);
+ var item = templatedList.ListProxy[indexPath.Row];
+ return item.GetType();
+ }
+
+ protected Cell GetCellForPath(NSIndexPath indexPath)
+ {
+ var templatedItems = GetTemplatedItemsListForPath(indexPath);
var cell = templatedItems[indexPath.Row];
return cell;
}
@@ -1086,10 +1110,7 @@ namespace Xamarin.Forms.Platform.iOS
if (selector == null)
return DefaultItemTemplateId;
- var templatedList = TemplatedItemsView.TemplatedItems;
- if (List.IsGroupingEnabled)
- templatedList = (TemplatedItemsList<ItemsView<Cell>, Cell>)((IList)templatedList)[indexPath.Section];
-
+ var templatedList = GetTemplatedItemsListForPath(indexPath);
var item = templatedList.ListProxy[indexPath.Row];
itemTemplate = selector.SelectTemplate(item, List);