Skip to content

Commit 88bf3e8

Browse files
committed
Fix NaluTabBar shell page resize and VirtualScroll iOS Carousel snapping upon page resize
1 parent cebcdf5 commit 88bf3e8

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

Source/Nalu.Maui.Navigation/Platforms/Apple/NaluShellSectionWrapperController.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,15 @@ private void SelectViewController(UIViewController? oldViewController, UIViewCon
6464

6565
if (newViewController is not null)
6666
{
67-
View!.InsertSubview(newViewController.View!, 0);
67+
var childView = newViewController.View!;
68+
View!.InsertSubview(childView, 0);
69+
childView.TranslatesAutoresizingMaskIntoConstraints = false;
70+
NSLayoutConstraint.ActivateConstraints([
71+
childView.TopAnchor.ConstraintEqualTo(View.TopAnchor),
72+
childView.BottomAnchor.ConstraintEqualTo(View.BottomAnchor),
73+
childView.LeftAnchor.ConstraintEqualTo(View.LeftAnchor),
74+
childView.RightAnchor.ConstraintEqualTo(View.RightAnchor)
75+
]);
6876
}
6977

7078
if (oldViewController is not null)

Source/Nalu.Maui.VirtualScroll/Nalu.Maui.VirtualScroll.csproj

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
</Target>
5858

5959
<ItemGroup>
60-
<PackageReference Include="DynamicData" Version="9.4.1" />
6160
<PackageReference Condition="$(TargetFramework.StartsWith('net9'))" Include="Microsoft.Maui.Controls" Version="$(MauiVersion9)"/>
6261
<PackageReference Condition="$(TargetFramework.StartsWith('net10'))" Include="Microsoft.Maui.Controls" Version="$(MauiVersion10)"/>
6362
</ItemGroup>
@@ -66,12 +65,6 @@
6665
<ProjectReference Include="..\Nalu.Maui.Core\Nalu.Maui.Core.csproj" />
6766
</ItemGroup>
6867

69-
<ItemGroup>
70-
<Compile Update="Platforms\Android\VirtualScrollPlatformReuseIdManager.cs">
71-
<ExcludeFromCurrentConfiguration>true</ExcludeFromCurrentConfiguration>
72-
</Compile>
73-
</ItemGroup>
74-
7568
<ItemGroup Label="Files">
7669
<None Include="LICENSE.md" Pack="true" PackagePath="\" />
7770
</ItemGroup>

Source/Nalu.Maui.VirtualScroll/Platforms/Apple/VirtualScrollHandler.cs

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public partial class VirtualScrollHandler
2222
private VirtualScrollCollectionView? _collectionView;
2323
private VirtualScrollContainerView? _containerView;
2424
private UILongPressGestureRecognizer? _dragGestureRecognizer;
25+
private CGSize _lastBounds;
2526

2627
/// <summary>
2728
/// Gets the <see cref="UICollectionView"/> platform view.
@@ -149,8 +150,8 @@ protected override UIView CreatePlatformView()
149150
_containerView = new VirtualScrollContainerView();
150151

151152
// Subscribe to events for fading edge updates
152-
_containerView.BoundsChanged += OnFadingEdgeBoundsChanged;
153-
collectionView.ContentSizeChanged += OnFadingEdgeBoundsChanged;
153+
_containerView.BoundsChanged += OnBoundsChanged;
154+
collectionView.ContentSizeChanged += OnContentSizeChanged;
154155

155156
var containerView = _containerView;
156157
collectionView.TranslatesAutoresizingMaskIntoConstraints = false;
@@ -210,7 +211,56 @@ private static UILongPressGestureRecognizer CreateDragGestureRecognizer(IVirtual
210211
}
211212
);
212213

213-
private void OnFadingEdgeBoundsChanged(object? s, EventArgs e)
214+
private void OnBoundsChanged(object? sender, EventArgs e)
215+
{
216+
if (_collectionView is not null)
217+
{
218+
_delegate?.UpdateFadingEdge(_collectionView);
219+
220+
// Maintain carousel snap to the first page
221+
if (_collectionView.PagingEnabled && VirtualView?.ItemsLayout is { Orientation: var orientation })
222+
{
223+
var bounds = _collectionView.Bounds;
224+
var contentSize = _collectionView.ContentSize;
225+
var scrollX = _collectionView.ContentOffset.X;
226+
var scrollY = _collectionView.ContentOffset.Y;
227+
nfloat? newX = null, newY = null;
228+
229+
if (orientation == ItemsLayoutOrientation.Horizontal)
230+
{
231+
var pageWidth = bounds.Width;
232+
if (pageWidth > 0 && _lastBounds.Width > 0 && contentSize.Width > 0)
233+
{
234+
var page = Math.Round(scrollX / _lastBounds.Width);
235+
var snapX = (nfloat)(page * pageWidth);
236+
var maxX = contentSize.Width - pageWidth;
237+
newX = (nfloat)Math.Max(0, Math.Min(maxX, snapX));
238+
newY = scrollY;
239+
}
240+
}
241+
else
242+
{
243+
var pageHeight = bounds.Height;
244+
if (pageHeight > 0 && _lastBounds.Height > 0 && contentSize.Height > 0)
245+
{
246+
var page = Math.Round(scrollY / _lastBounds.Height);
247+
var snapY = (nfloat)(page * pageHeight);
248+
var maxY = contentSize.Height - pageHeight;
249+
newX = scrollX;
250+
newY = (nfloat)Math.Max(0, Math.Min(maxY, snapY));
251+
}
252+
}
253+
254+
if (newX is { } x && newY is { } y)
255+
{
256+
_collectionView.SetContentOffset(new CGPoint(x, y), false);
257+
}
258+
}
259+
260+
_lastBounds = _collectionView.Bounds.Size;
261+
}
262+
}
263+
private void OnContentSizeChanged(object? s, EventArgs e)
214264
{
215265
if (_collectionView is not null)
216266
{
@@ -243,12 +293,12 @@ protected override void DisconnectHandler(UIView platformView)
243293
// Unsubscribe from events
244294
if (_containerView is not null)
245295
{
246-
_containerView.BoundsChanged -= OnFadingEdgeBoundsChanged;
296+
_containerView.BoundsChanged -= OnBoundsChanged;
247297
}
248298

249299
if (_collectionView is not null)
250300
{
251-
_collectionView.ContentSizeChanged -= OnFadingEdgeBoundsChanged;
301+
_collectionView.ContentSizeChanged -= OnContentSizeChanged;
252302
_collectionView.DataSource = null!;
253303
_collectionView.Delegate = null!;
254304
_collectionView.RefreshControl = null;
@@ -262,6 +312,7 @@ protected override void DisconnectHandler(UIView platformView)
262312
_dragGestureRecognizer?.Dispose();
263313
_containerView?.Dispose();
264314
_containerView = null;
315+
_lastBounds = CGSize.Empty;
265316
_reuseIdManager = null;
266317

267318
base.DisconnectHandler(platformView);

0 commit comments

Comments
 (0)