Skip to content

Commit

Permalink
Ensure the iOS ScrollView content container is at least the ScrollVie…
Browse files Browse the repository at this point in the history
…w size (#8451)

Co-authored-by: Shane Neuville <[email protected]>
  • Loading branch information
2 people authored and mattleibow committed Jul 4, 2022
1 parent 4fe9d92 commit ea8e7d2
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ Size IContentView.CrossPlatformArrange(Rect bounds)
// Normally we'd just want the content to be arranged within the ContentView's Frame,
// but ScrollView content might be larger than the ScrollView itself (for obvious reasons)
// So in each dimension, we assume the larger of the two values.
bounds.Width = Math.Max(Frame.Width, presentedContent.DesiredSize.Width + padding.HorizontalThickness);
bounds.Height = Math.Max(Frame.Height, presentedContent.DesiredSize.Height + padding.VerticalThickness);
bounds.Width = Math.Max(bounds.Width, presentedContent.DesiredSize.Width + padding.HorizontalThickness);
bounds.Height = Math.Max(bounds.Height, presentedContent.DesiredSize.Height + padding.VerticalThickness);

this.ArrangeContent(bounds);
}
Expand Down
42 changes: 31 additions & 11 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using CoreGraphics;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Layouts;
using ObjCRuntime;
using UIKit;
using Size = Microsoft.Maui.Graphics.Size;

namespace Microsoft.Maui.Handlers
{
Expand Down Expand Up @@ -56,13 +58,6 @@ public static void MapContent(IScrollViewHandler handler, IScrollView scrollView
public static void MapContentSize(IScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.UpdateContentSize(scrollView.ContentSize);

if (GetContentView(handler.PlatformView) is ContentView currentContentContainer)
{
var rect = new Rect(Point.Zero, scrollView.ContentSize);
currentContentContainer.Center = new CGPoint(rect.Center.X, rect.Center.Y);
currentContentContainer.Bounds = new CGRect(currentContentContainer.Bounds.X, currentContentContainer.Bounds.Y, rect.Width, rect.Height);
}
}

public static void MapIsEnabled(IScrollViewHandler handler, IScrollView scrollView)
Expand Down Expand Up @@ -131,6 +126,7 @@ static void UpdateContentView(IScrollView scrollView, IScrollViewHandler handler
{
currentContentContainer.ClearSubviews();
currentContentContainer.AddSubview(nativeContent);
currentContentContainer.View = scrollView.PresentedContent;
}
}
else
Expand All @@ -148,16 +144,41 @@ static void InsertContentView(UIScrollView platformScrollView, IScrollView scrol

var contentContainer = new ContentView()
{
View = scrollView.PresentedContent,
CrossPlatformMeasure = ConstrainToScrollView(scrollView.CrossPlatformMeasure, platformScrollView, scrollView),
CrossPlatformArrange = scrollView.CrossPlatformArrange,
Tag = ContentPanelTag
};

contentContainer.CrossPlatformArrange = ArrangeScrollViewContent(scrollView.CrossPlatformArrange, contentContainer);

platformScrollView.ClearSubviews();
contentContainer.AddSubview(platformContent);
platformScrollView.AddSubview(contentContainer);
}

static Func<Rect, Size> ArrangeScrollViewContent(Func<Rect, Size> internalArrange, ContentView container)
{
return (rect) =>
{
if (container.Superview is UIScrollView scrollView)
{
// Ensure the container is at least the size of the UIScrollView itself, so that the
// cross-platform layout logic makes sense and the contents don't arrange out side the
// container. (Everything will look correct if they do, but hit testing won't work properly.)

var scrollViewBounds = scrollView.Bounds;
var containerBounds = container.Bounds;

container.Bounds = new CGRect(0, 0,
Math.Max(containerBounds.Width, scrollViewBounds.Width),
Math.Max(containerBounds.Height, scrollViewBounds.Height));
container.Center = new CGPoint(container.Bounds.GetMidX(), container.Bounds.GetMidY());
}

return internalArrange(rect);
};
}

static Func<double, double, Size> ConstrainToScrollView(Func<double, double, Size> internalMeasure, UIScrollView platformScrollView, IScrollView scrollView)
{
return (widthConstraint, heightConstraint) =>
Expand All @@ -176,20 +197,19 @@ static Size MeasureScrollViewContent(double widthConstraint, double heightConstr

if (widthConstraint == 0)
{
widthConstraint = platformScrollView.Frame.Width;
widthConstraint = platformScrollView.Bounds.Width;
}

if (heightConstraint == 0)
{
heightConstraint = platformScrollView.Frame.Height;
heightConstraint = platformScrollView.Bounds.Height;
}

widthConstraint -= scrollView.Padding.HorizontalThickness;
heightConstraint -= scrollView.Padding.VerticalThickness;

var result = internalMeasure.Invoke(widthConstraint, heightConstraint);

// If the presented content has LayoutAlignment Fill, we'll need to adjust the measurement to account for that
return result.AdjustForFill(new Rect(0, 0, widthConstraint, heightConstraint), presentedContent);
}
}
Expand Down

0 comments on commit ea8e7d2

Please sign in to comment.