diff --git a/Ooui.Forms/Renderers/ListViewRenderer.cs b/Ooui.Forms/Renderers/ListViewRenderer.cs index 98cf5a3..069c264 100644 --- a/Ooui.Forms/Renderers/ListViewRenderer.cs +++ b/Ooui.Forms/Renderers/ListViewRenderer.cs @@ -11,7 +11,17 @@ namespace Ooui.Forms.Renderers { public class ListViewRenderer : ViewRenderer { + const int DefaultRowHeight = 44; private bool _disposed; + IVisualElementRenderer _prototype; + + int _rowHeight; + + public int RowHeight + { + get => _rowHeight; + set => _rowHeight = value; + } public ListViewRenderer () { @@ -32,6 +42,10 @@ namespace Ooui.Forms.Renderers var list = new List (); list.Style.Overflow = "scroll"; list.Style.Padding = "0"; + // Make the list element positioned so child elements will + // be positioned relative to it. This will allow the list + // to scroll properly. + list.Style.Position = "relative"; SetNativeControl (list); } @@ -40,6 +54,8 @@ namespace Ooui.Forms.Renderers templatedItems.CollectionChanged += OnCollectionChanged; e.NewElement.ScrollToRequested += ListView_ScrollToRequested; + UpdateRowHeight(); + UpdateItems (); UpdateBackgroundColor (); } @@ -121,11 +137,22 @@ namespace Ooui.Forms.Renderers } else { var i = 0; + double offset = 0; foreach (var item in items) { var li = listItems[i]; + var nativeCell = items[i]; var children = li.Children; var rv = children.Count > 0 ? children[0] as CellElement : null; var cell = GetCell (item, rv); + var height = CalculateHeightForCell(nativeCell); + li.Style.Height = height; + var viewCell = (ViewCell)cell.Cell; + if (viewCell != null && viewCell.View != null) + { + var rect = new Rectangle(0, offset, Element.Width, height); + Layout.LayoutChildIntoBoundingRegion(viewCell.View, rect); + } + offset += height; if (rv == null) { li.AppendChild (cell); } @@ -161,6 +188,56 @@ namespace Ooui.Forms.Renderers } } + void UpdateRowHeight() + { + var rowHeight = Element.RowHeight; + if (Element.HasUnevenRows && rowHeight == -1) + RowHeight = -1; + else + RowHeight = rowHeight <= 0 ? DefaultRowHeight : rowHeight; + } + + internal double CalculateHeightForCell(Cell cell) + { + if (!Element.HasUnevenRows) + { + return RowHeight; + } + else + { + var viewCell = cell as ViewCell; + if (viewCell != null && viewCell.View != null) + { + var target = viewCell.View; + if (_prototype == null) + _prototype = Platform.CreateRenderer(target); + else + _prototype.SetElement(target); + + Platform.SetRenderer(target, _prototype); + + var req = target.Measure(Element.Width, double.PositiveInfinity, MeasureFlags.IncludeMargins); + + target.ClearValue(Platform.RendererProperty); + foreach (Xamarin.Forms.Element descendant in target.Descendants()) + { + IVisualElementRenderer renderer = Platform.GetRenderer(descendant as VisualElement); + + // Clear renderer from descendent; this will not happen in Dispose as normal because we need to + // unhook the Element from the renderer before disposing it. + descendant.ClearValue(Platform.RendererProperty); + renderer?.Dispose(); + renderer = null; + } + + var height = req.Request.Height; + return height > 1 ? height : DefaultRowHeight; + } + var renderHeight = cell.RenderHeight; + return renderHeight > 0 ? renderHeight : DefaultRowHeight; + } + } + void UpdateBackgroundColor () { if (Control == null)