Skip to content

Commit 0047ca2

Browse files
authored
Resize internal content container when ScrollView content is resized (#16385)
* Resize internal content container when ScrollView content is resized Fixes #14257 * Fix constructor
1 parent 56e676a commit 0047ca2

File tree

4 files changed

+170
-63
lines changed

4 files changed

+170
-63
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Microsoft.Maui.Controls;
2+
3+
namespace Maui.Controls.Sample.Issues
4+
{
5+
[Issue(IssueTracker.Github, 14257, "VerticalStackLayout inside Scrollview: Button at the bottom not clickable on IOS", PlatformAffected.iOS)]
6+
public class Issue14257 : TestContentPage
7+
{
8+
protected override void Init()
9+
{
10+
var scrollView = new ScrollView();
11+
var layout = new VerticalStackLayout() { Margin = new Microsoft.Maui.Thickness(10, 40) };
12+
13+
var description = new Label { Text = "Tap the Resize button; this will force the Test button off the screen. Then tap the Test button; if a Label with the text \"Success\" appears, the test has passed." };
14+
15+
var resizeButton = new Button() { Text = "Resize", AutomationId = "Resize" };
16+
var layoutContent = new Label() { Text = "Content", HeightRequest = 50 };
17+
var testButton = new Button() { Text = "Test", AutomationId = "Test" };
18+
var resultLabel = new Label() { AutomationId = "Result" };
19+
20+
layout.Add(description);
21+
layout.Add(resizeButton);
22+
layout.Add(layoutContent);
23+
layout.Add(resultLabel);
24+
layout.Add(testButton);
25+
26+
scrollView.Content = layout;
27+
Content = scrollView;
28+
29+
resizeButton.Clicked += (sender, args) => {
30+
// Resize the ScrollView content so the test button will be off the screen
31+
// If the bug is present, this will make the button untappable
32+
layoutContent.HeightRequest = 1000;
33+
};
34+
35+
// Show the Success label if the button is tapped, so we can verify the bug is not present
36+
testButton.Clicked += (sender, args) => { resultLabel.Text = "Success"; };
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.Maui.Appium;
2+
using NUnit.Framework;
3+
4+
namespace Microsoft.Maui.AppiumTests.Issues
5+
{
6+
public class Issue14257 : _IssuesUITest
7+
{
8+
public Issue14257(TestDevice device) : base(device) { }
9+
10+
public override string Issue => "VerticalStackLayout inside Scrollview: Button at the bottom not clickable on IOS";
11+
12+
[Test]
13+
public void ResizeScrollViewAndTapButtonTest()
14+
{
15+
// Tapping the Resize button will change the height of the ScrollView content
16+
App.Tap("Resize");
17+
18+
// Scroll down to the Test button. When the bug is present, the button cannot be tapped.
19+
App.ScrollDownTo("Test");
20+
App.Tap("Test");
21+
22+
// If we can successfully tap the button, the Success label will be displayed
23+
Assert.IsTrue(App.WaitForTextToBePresentInElement("Result", "Success"));
24+
}
25+
}
26+
}

src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs

+12-40
Original file line numberDiff line numberDiff line change
@@ -188,36 +188,6 @@ static void InsertContentView(UIScrollView platformScrollView, IScrollView scrol
188188
platformScrollView.AddSubview(contentContainer);
189189
}
190190

191-
static Size MeasureScrollViewContent(double widthConstraint, double heightConstraint, Func<double, double, Size> internalMeasure, UIScrollView platformScrollView, IScrollView scrollView)
192-
{
193-
var presentedContent = scrollView.PresentedContent;
194-
if (presentedContent == null)
195-
{
196-
return Size.Zero;
197-
}
198-
199-
var scrollViewBounds = platformScrollView.Bounds;
200-
var padding = scrollView.Padding;
201-
202-
if (widthConstraint == 0)
203-
{
204-
widthConstraint = scrollViewBounds.Width;
205-
}
206-
207-
if (heightConstraint == 0)
208-
{
209-
heightConstraint = scrollViewBounds.Height;
210-
}
211-
212-
// Account for the ScrollView Padding before measuring the content
213-
widthConstraint = AccountForPadding(widthConstraint, padding.HorizontalThickness);
214-
heightConstraint = AccountForPadding(heightConstraint, padding.VerticalThickness);
215-
216-
var result = internalMeasure.Invoke(widthConstraint, heightConstraint);
217-
218-
return result.AdjustForFill(new Rect(0, 0, widthConstraint, heightConstraint), presentedContent);
219-
}
220-
221191
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
222192
{
223193
var virtualView = VirtualView;
@@ -338,6 +308,16 @@ Size ICrossPlatformLayout.CrossPlatformArrange(Rect bounds)
338308
{
339309
var scrollView = VirtualView;
340310
var platformScrollView = PlatformView;
311+
312+
var contentSize = scrollView.CrossPlatformArrange(bounds);
313+
314+
// The UIScrollView's bounds are available, so we can use them to make sure the ContentSize makes sense
315+
// for the ScrollView orientation
316+
var viewportBounds = platformScrollView.Bounds;
317+
var viewportHeight = viewportBounds.Height;
318+
var viewportWidth = viewportBounds.Width;
319+
SetContentSizeForOrientation(platformScrollView, viewportWidth, viewportHeight, scrollView.Orientation, contentSize);
320+
341321
var container = GetContentView(platformScrollView);
342322

343323
if (container?.Superview is UIScrollView uiScrollView)
@@ -347,23 +327,15 @@ Size ICrossPlatformLayout.CrossPlatformArrange(Rect bounds)
347327
// container. (Everything will look correct if they do, but hit testing won't work properly.)
348328

349329
var scrollViewBounds = uiScrollView.Bounds;
350-
var containerBounds = container.Bounds;
330+
var containerBounds = contentSize;
351331

352332
container.Bounds = new CGRect(0, 0,
353333
Math.Max(containerBounds.Width, scrollViewBounds.Width),
354334
Math.Max(containerBounds.Height, scrollViewBounds.Height));
335+
355336
container.Center = new CGPoint(container.Bounds.GetMidX(), container.Bounds.GetMidY());
356337
}
357338

358-
var contentSize = scrollView.CrossPlatformArrange(bounds);
359-
360-
// The UIScrollView's bounds are available, so we can use them to make sure the ContentSize makes sense
361-
// for the ScrollView orientation
362-
var viewportBounds = platformScrollView.Bounds;
363-
var viewportHeight = viewportBounds.Height;
364-
var viewportWidth = viewportBounds.Width;
365-
SetContentSizeForOrientation(platformScrollView, viewportWidth, viewportHeight, scrollView.Orientation, contentSize);
366-
367339
return contentSize;
368340
}
369341

0 commit comments

Comments
 (0)