From 0cc54eb70c1e9e1215f34d4f28d6677b9fd67d97 Mon Sep 17 00:00:00 2001 From: Satoshi Nakamura Date: Tue, 25 Apr 2023 17:45:22 +0900 Subject: [PATCH] fix Android addCell / iOS Scrolling --- SettingsView/Cells/CellBase.cs | 1 + .../Handlers/CellBase/CellBaseHandler.cs | 3 +- SettingsView/Platforms/Android/ModelProxy.cs | 1 + .../Platforms/iOS/Cells/CellBaseView.cs | 29 ++------ .../Platforms/iOS/Cells/CustomCellContent.cs | 67 +++++++++++++++---- .../Platforms/iOS/Cells/CustomCellView.cs | 3 +- .../Platforms/iOS/SettingsTableSource.cs | 2 +- SettingsView/SettingsModel.cs | 2 +- nuget/AzurePipelines.nuspec | 2 +- 9 files changed, 71 insertions(+), 39 deletions(-) diff --git a/SettingsView/Cells/CellBase.cs b/SettingsView/Cells/CellBase.cs index 1f4abc4..5dd8c21 100644 --- a/SettingsView/Cells/CellBase.cs +++ b/SettingsView/Cells/CellBase.cs @@ -485,6 +485,7 @@ public virtual void Reload() #elif IOS || MACCATALYST internal UIKit.UITableViewCell ReusableCell { get; set; } + internal Queue ReusableCellQueue { get; } = new Queue(); internal UIKit.UITableView TableView { get; set; } #endif diff --git a/SettingsView/Handlers/CellBase/CellBaseHandler.cs b/SettingsView/Handlers/CellBase/CellBaseHandler.cs index 7f86055..c982124 100644 --- a/SettingsView/Handlers/CellBase/CellBaseHandler.cs +++ b/SettingsView/Handlers/CellBase/CellBaseHandler.cs @@ -52,7 +52,8 @@ protected void SetUpPropertyChanged(CellBaseView nativeCell) if (parentElement != null) { parentElement.PropertyChanged += nativeCell.ParentPropertyChanged; - var section = parentElement.Model.GetSection(SettingsModel.GetPath(virtualCell).Item1); + + var section = parentElement.Model.GetSectionFromCell(virtualCell); if (section != null) { virtualCell.Section = section; diff --git a/SettingsView/Platforms/Android/ModelProxy.cs b/SettingsView/Platforms/Android/ModelProxy.cs index 61ac3c3..cb38dde 100644 --- a/SettingsView/Platforms/Android/ModelProxy.cs +++ b/SettingsView/Platforms/Android/ModelProxy.cs @@ -138,6 +138,7 @@ void AddSection(NotifyCollectionChangedEventArgs e) Cell = cell, ViewType = (ViewType)ViewTypes[cell.GetType()], }; + this.Insert(i + 1 + startIndex, rowInfo); } diff --git a/SettingsView/Platforms/iOS/Cells/CellBaseView.cs b/SettingsView/Platforms/iOS/Cells/CellBaseView.cs index 53bc264..bb9022e 100644 --- a/SettingsView/Platforms/iOS/Cells/CellBaseView.cs +++ b/SettingsView/Platforms/iOS/Cells/CellBaseView.cs @@ -347,9 +347,13 @@ internal void UpdateDescriptionText() if (CellParent.HasUnevenRows) { if (CellParent.Handler.PlatformView is AiTableView tv) - { - tv.BeginUpdates(); - tv.EndUpdates(); + { + // TODO: The following code is needed to dynamically change the cell height + // according to the contents of the Description, but it is commented out + // because it causes scrolling problems. + // The workaround is probably to do it at the timing of PropertyChanged. + //tv.BeginUpdates(); + //tv.EndUpdates(); } } } @@ -542,25 +546,6 @@ public virtual void UpdateCell(UITableView tableView = null) { if (TitleLabel is null) return; // For HotReload - - //UpdateBackgroundColor(); - //UpdateTitleText(); - //UpdateTitleColor(); - //UpdateTitleFont(); - //UpdateDescriptionText(); - //UpdateDescriptionColor(); - //UpdateDescriptionFont(); - //UpdateHintText(); - //UpdateHintTextColor(); - //UpdateHintFont(); - - ////UpdateIcon(); - //UpdateIconRadius(); - - //UpdateIsEnabled(); - //UpdateIsVisible(); - - //SetNeedsLayout(); } /// diff --git a/SettingsView/Platforms/iOS/Cells/CustomCellContent.cs b/SettingsView/Platforms/iOS/Cells/CustomCellContent.cs index 952ee31..08284b4 100644 --- a/SettingsView/Platforms/iOS/Cells/CustomCellContent.cs +++ b/SettingsView/Platforms/iOS/Cells/CustomCellContent.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Runtime.InteropServices; +using System.Threading; using AiForms.Settings.Extensions; using Microsoft.Maui; using Microsoft.Maui.Controls; @@ -42,6 +43,14 @@ protected override void Dispose(bool disposing) { _virtualCell.PropertyChanged -= CellPropertyChanged; _virtualCell.MeasureInvalidated -= OnMeasureInvalidated; + foreach (var child in CustomCellContent.ElementDescendants(_virtualCell)) + { + if (child is Layout layout) + { + layout.SizeChanged -= OnInnerLayoutSizeChanged; + } + child.MeasureInvalidated -= OnMeasureInvalidated; + } } CustomCell = null; @@ -93,7 +102,7 @@ public virtual void UpdateCell(View newCell, UITableView tableView) // If oldCell and newCell are the same if (oldCell == newCell) { - if (!CustomCell.IsForceLayout) + if (!CustomCell.IsForceLayout && Subviews.Any()) { // do nothing. return; @@ -104,6 +113,7 @@ public virtual void UpdateCell(View newCell, UITableView tableView) if (oldCell != null) { + _cts?.Cancel(); oldCell.PropertyChanged -= CellPropertyChanged; oldCell.MeasureInvalidated -= OnMeasureInvalidated; // Delete previous child element @@ -114,6 +124,10 @@ public virtual void UpdateCell(View newCell, UITableView tableView) oldCell.MeasureInvalidated -= OnMeasureInvalidated; foreach (var child in CustomCellContent.ElementDescendants(oldCell)) { + if (child is Layout layout) + { + layout.SizeChanged -= OnInnerLayoutSizeChanged; + } child.MeasureInvalidated -= OnMeasureInvalidated; } } @@ -180,26 +194,47 @@ public virtual void UpdateCell(View newCell, UITableView tableView) UpdateNativeCell(); - SetNeedsLayout(); + //SetNeedsLayout(); _virtualCell.MeasureInvalidated += OnMeasureInvalidated; foreach (var child in CustomCellContent.ElementDescendants(_virtualCell)) { + if(child is Layout layout) + { + // Also detects changes in the size of descendant layout(BindableLayout) + layout.SizeChanged += OnInnerLayoutSizeChanged; + } // Also detects changes in the size of descendant elements child.MeasureInvalidated += OnMeasureInvalidated; } + } + + private void OnInnerLayoutSizeChanged(object sender, EventArgs e) + { + LayoutDispacher(); } private void OnMeasureInvalidated(object sender, EventArgs e) + { + LayoutDispacher(); + } + + async Task ForceLayout(CancellationToken token) { - if(_tableView != null) + if(_tableView == null) { - ForceLayout(_tableView, _virtualCell.Handler as IPlatformViewHandler); + return; + } + var tableView = _tableView; + var handler = _virtualCell.Handler as IPlatformViewHandler; + + // Wait a little and execute layout processing only on the last event + await Task.Delay(100); + if (token.IsCancellationRequested) + { + return; } - } - void ForceLayout(UITableView tableView, IPlatformViewHandler handler) - { _lastFrameWidth = tableView.Frame.Width; var height = double.PositiveInfinity; @@ -229,7 +264,7 @@ void ForceLayout(UITableView tableView, IPlatformViewHandler handler) _virtualCell.Arrange(new Rect(0, 0, _lastMeasureWidth, _lastMeasureHeight)); native.SetNeedsUpdateConstraints(); - native.UpdateConstraintsIfNeeded(); + //native.UpdateConstraintsIfNeeded(); SetNeedsLayout(); tableView.BeginUpdates(); @@ -248,8 +283,8 @@ void ArrangeSubView(IPlatformViewHandler handler) _heightConstraint.Active = false; _heightConstraint.Priority = 1f; _heightConstraint?.Dispose(); - native.SetNeedsUpdateConstraints(); - native.UpdateConstraintsIfNeeded(); + //native.SetNeedsUpdateConstraints(); + //native.UpdateConstraintsIfNeeded(); } _heightConstraint = native.HeightAnchor.ConstraintEqualTo((NFloat)_lastMeasureHeight); @@ -261,8 +296,16 @@ void ArrangeSubView(IPlatformViewHandler handler) native.BottomAnchor.ConstraintEqualTo(BottomAnchor).Active = true; native.RightAnchor.ConstraintEqualTo(RightAnchor).Active = true; - native.SetNeedsUpdateConstraints(); - native.UpdateConstraintsIfNeeded(); + //native.SetNeedsUpdateConstraints(); + //native.UpdateConstraintsIfNeeded(); + } + + CancellationTokenSource _cts = new CancellationTokenSource(); + void LayoutDispacher() + { + _cts?.Cancel(); + _cts = new CancellationTokenSource(); + _ = ForceLayout(_cts.Token); } static IEnumerable ElementDescendants(Element element) diff --git a/SettingsView/Platforms/iOS/Cells/CustomCellView.cs b/SettingsView/Platforms/iOS/Cells/CustomCellView.cs index b03cb44..a4cf7be 100644 --- a/SettingsView/Platforms/iOS/Cells/CustomCellView.cs +++ b/SettingsView/Platforms/iOS/Cells/CustomCellView.cs @@ -22,7 +22,8 @@ public CustomCellView(CellBase virtualCell) : base(virtualCell) public override void UpdateConstraints() { base.UpdateConstraints(); - LayoutIfNeeded(); // let the layout immediately reflect when update constraints. + // It works fine even if disable this code. + //LayoutIfNeeded(); // let the layout immediately reflect when update constraints. } protected override void SetUpContentView() diff --git a/SettingsView/Platforms/iOS/SettingsTableSource.cs b/SettingsView/Platforms/iOS/SettingsTableSource.cs index c49c07b..17fa1f0 100644 --- a/SettingsView/Platforms/iOS/SettingsTableSource.cs +++ b/SettingsView/Platforms/iOS/SettingsTableSource.cs @@ -99,7 +99,7 @@ public override UITableViewCell GetCell(UITableView tableView, NSIndexPath index // Because the layer was hidden we need to layout the cell by hand if (cellWithContent != null) { - cellWithContent.LayoutSubviews(); + //cellWithContent.LayoutSubviews(); } return platformCell; diff --git a/SettingsView/SettingsModel.cs b/SettingsView/SettingsModel.cs index be015cc..f84ea63 100644 --- a/SettingsView/SettingsModel.cs +++ b/SettingsView/SettingsModel.cs @@ -174,7 +174,7 @@ public void OnRowSelected(CellBase cell) } - static void SetPath(CellBase item, Tuple index) + internal static void SetPath(CellBase item, Tuple index) { if (item == null) return; diff --git a/nuget/AzurePipelines.nuspec b/nuget/AzurePipelines.nuspec index f1e750b..ed43ace 100644 --- a/nuget/AzurePipelines.nuspec +++ b/nuget/AzurePipelines.nuspec @@ -15,7 +15,7 @@ There are various cells such as (LabelCell,ButtonCell,CommandCell,SwitchCell,Che -Add platform MacCatalyst +bug fixes MAUI TableView Cell Setting Configuration Option ListView UITableView RecyclerView ReOrder DragDrop en-US