Skip to content
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
namespace Maui.Controls.Sample.Issues
{
[Issue(IssueTracker.None, 41415, "ScrollX and ScrollY values are not consistent with iOS", PlatformAffected.Android)]
[Issue(IssueTracker.None, 41415, "ScrollX and ScrollY values at the ScrollView.Scrolled event are not consistent in ScrollOrientation.Both mode", PlatformAffected.Android)]
public class Bugzilla41415 : ContentPage
{
const string ButtonId = "ClickId";
const string ButtonText = "Click Me";

float _x;
bool _didXChange, _didYChange;

public Bugzilla41415()
{
var grid = new Grid
Expand All @@ -32,8 +30,6 @@ public Bugzilla41415()

var labelx = new Label();
var labely = new Label();
var labelz = new Label();
var labela = new Label();

var scrollView = new ScrollView
{
Expand All @@ -47,25 +43,6 @@ public Bugzilla41415()
{
labelx.Text = $"x: {(int)Math.Round(args.ScrollX)}";
labely.Text = $"y: {(int)Math.Round(args.ScrollY)}";

// first and second taps
if (_x == 0)
{
if (Math.Round(args.ScrollX) != 0 && Math.Round(args.ScrollX) != 100)
_didXChange = true;
if (Math.Round(args.ScrollY) != 0 && Math.Round(args.ScrollY) != 100)
_didYChange = true;
}
else if (_x == 100)
{
if (Math.Round(args.ScrollX) != _x && Math.Round(args.ScrollX) != _x + 100)
_didXChange = true;
if (Math.Round(args.ScrollY) != 100)
_didYChange = true;
}

labelz.Text = "z: " + _didXChange.ToString();
labela.Text = "a: " + _didYChange.ToString();
};

var button = new Button { AutomationId = ButtonId, Text = ButtonText };
Expand All @@ -74,10 +51,6 @@ public Bugzilla41415()
// reset
labelx.Text = null;
labely.Text = null;
labelz.Text = null;
labela.Text = null;
_didXChange = false;
_didYChange = false;

await scrollView.ScrollToAsync(_x + 100, 100, true);
_x = 100;
Expand All @@ -86,16 +59,12 @@ public Bugzilla41415()
Grid.SetRow(button, 0);
Grid.SetRow(labelx, 1);
Grid.SetRow(labely, 2);
Grid.SetRow(labelz, 3);
Grid.SetRow(labela, 4);
Grid.SetRow(scrollView, 5);
Grid.SetRow(scrollView, 3);

Content = new Grid
{
RowDefinitions = new RowDefinitionCollection
{
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto },
Expand All @@ -106,8 +75,6 @@ public Bugzilla41415()
button,
labelx,
labely,
labelz,
labela,
scrollView,
}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_WINDOWS
// On Android ScrollY and ScrollX values are resetted, Issue: https://github.com/dotnet/maui/issues/26747
// On Windows tests are failing in CI, but not locally. Need to investigate more.
using NUnit.Framework;
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

Expand All @@ -18,7 +15,7 @@ public Bugzilla41415UITests(TestDevice device)
{
}

public override string Issue => "ScrollX and ScrollY values are not consistent with iOS";
public override string Issue => "ScrollX and ScrollY values at the ScrollView.Scrolled event are not consistent in ScrollOrientation.Both mode";

[Test]
public void Bugzilla41415Test()
Expand All @@ -28,15 +25,10 @@ public void Bugzilla41415Test()
App.WaitForElement(ButtonId);
App.WaitForElementTillPageNavigationSettled("x: 100");
App.WaitForElementTillPageNavigationSettled("y: 100");
App.WaitForElement("z: True");
App.WaitForElement("a: True");
App.Tap(ButtonId);
App.WaitForElement(ButtonId);
App.WaitForElementTillPageNavigationSettled("y: 100");
App.WaitForElement("z: True");
App.WaitForElement("a: False");
App.WaitForElementTillPageNavigationSettled("x: 200");
}
}
}
#endif
27 changes: 23 additions & 4 deletions src/Core/src/Handlers/ScrollView/ScrollViewHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,34 @@ static int AdjustSpecForAlignment(int measureSpec, Primitives.LayoutAlignment al

void ScrollChange(object? sender, AndroidX.Core.Widget.NestedScrollView.ScrollChangeEventArgs e)
{
var context = (sender as View)?.Context;
var platformView = sender as MauiScrollView;

if (context == null)
if (platformView?.Context is null)
{
return;
}

VirtualView.VerticalOffset = Context.FromPixels(e.ScrollY);
VirtualView.HorizontalOffset = Context.FromPixels(e.ScrollX);
int scrollX = e.ScrollX;
int scrollY = e.ScrollY;

if (VirtualView.Orientation == ScrollOrientation.Both)
{
if (scrollX == 0)
{
// Need to pass the native HorizontalScrollView's ScrollX position to the virtual view to resolve
// the zero scroll offset issue since the framework returns an improper ScrollX value.
scrollX = platformView.HorizontalScrollOffset;
}

if (scrollY == 0)
{
// Pass the native ScrollView's ScrollY to the virtual view to maintain the correct vertical offset.
scrollY = platformView.ScrollY;
}
}

VirtualView.HorizontalOffset = platformView.Context.FromPixels(scrollX);
VirtualView.VerticalOffset = platformView.Context.FromPixels(scrollY);
}

public static void MapContent(IScrollViewHandler handler, IScrollView scrollView)
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Platform/Android/MauiScrollView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class MauiScrollView : NestedScrollView, IScrollBarView, NestedScrollView
internal float LastY { get; set; }

internal bool ShouldSkipOnTouch;
internal int HorizontalScrollOffset => _hScrollView?.ScrollX ?? 0;

public MauiScrollView(Context context) : base(context)
{
Expand Down