[Android] ScrollView should send correct ScrollX and ScrollY (#394)

* Android should show correct ScrollX and ScrollY when scrolling in both directions

* Adding sample code to demonstrate scrolling

* Orientation fix

* ScrollTo should work for horizontal + vertical scrolling

* Get correct scroll x and y values for ScrollOrientation.Both

* Convert positions to pixels

* Adding unit test to watch out for incorrect animation positioning

* automated test

* improvements

* fixed texts
This commit is contained in:
adrianknight89 2016-12-06 06:07:29 -06:00 коммит произвёл Rui Marinho
Родитель 331a7b76db
Коммит 9dff4c1650
4 изменённых файлов: 186 добавлений и 10 удалений

Просмотреть файл

@ -0,0 +1,115 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 41415, "ScrollX and ScrollY values are not consistent with iOS", PlatformAffected.Android)]
public class Bugzilla41415 : TestContentPage
{
const string ButtonText = "Click Me";
float _x, _y;
bool _didXChange, _didYChange;
protected override void Init()
{
var grid = new Grid
{
BackgroundColor = Color.Yellow,
WidthRequest = 1000,
HeightRequest = 1000,
Children =
{
new BoxView
{
WidthRequest = 200,
HeightRequest = 200,
BackgroundColor = Color.Red,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
}
};
var labelx = new Label();
var labely = new Label();
var labelz = new Label();
var labela = new Label();
var scrollView = new ScrollView
{
Orientation = ScrollOrientation.Both,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
scrollView.Content = grid;
scrollView.Scrolled += (sender, args) =>
{
labelx.Text = $"x: {args.ScrollX}";
labely.Text = $"y: {args.ScrollY}";
// first and second taps
if (_x == 0)
{
if (args.ScrollX != 0 && args.ScrollX != 100)
_didXChange = true;
if (args.ScrollY != 0 && args.ScrollY != 100)
_didYChange = true;
}
else if (_x == 100)
{
if (args.ScrollX != _x && args.ScrollX != _x + 100)
_didXChange = true;
if (args.ScrollY != 100)
_didYChange = true;
}
labelz.Text = "z: " + _didXChange.ToString();
labela.Text = "a: " + _didYChange.ToString();
};
var button = new Button { Text = ButtonText };
button.Clicked += async (sender, e) =>
{
// reset
labelx.Text = null;
labely.Text = null;
labelz.Text = null;
labela.Text = null;
_didXChange = false;
_didYChange = false;
await scrollView.ScrollToAsync(_x + 100, _y + 100, true);
_x = 100;
};
Content = new StackLayout { Children = { button, labelx, labely, labelz, labela, scrollView } };
}
#if UITEST
[Test]
public void Bugzilla41415Test()
{
RunningApp.WaitForElement(q => q.Marked(ButtonText));
RunningApp.Tap(q => q.Marked(ButtonText));
RunningApp.WaitForElement(q => q.Marked("x: 100"));
RunningApp.WaitForElement(q => q.Marked("y: 100"));
RunningApp.WaitForElement(q => q.Marked("z: True"));
RunningApp.WaitForElement(q => q.Marked("a: True"));
RunningApp.Tap(q => q.Marked(ButtonText));
RunningApp.WaitForElement(q => q.Marked("x: 200"));
RunningApp.WaitForElement(q => q.Marked("y: 100"));
RunningApp.WaitForElement(q => q.Marked("z: True"));
RunningApp.WaitForElement(q => q.Marked("a: False"));
}
#endif
}
}

Просмотреть файл

@ -115,6 +115,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41078.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla40998.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41205.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41415.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41418.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla41424.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla42069.cs" />

Просмотреть файл

@ -453,5 +453,36 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual(100, scroll.Height);
Assert.AreEqual(100, scroll.Width);
}
[Test]
public void TestBackToBackBiDirectionalScroll()
{
var scrollView = new ScrollView
{
Orientation = ScrollOrientation.Both,
Platform = new UnitPlatform(),
Content = new Grid
{
WidthRequest = 1000,
HeightRequest = 1000
}
};
var y100Count = 0;
((IScrollViewController)scrollView).ScrollToRequested += (sender, args) =>
{
if (args.ScrollY == 100)
{
++y100Count;
}
};
scrollView.ScrollToAsync(100, 100, true);
Assert.AreEqual(y100Count, 1);
scrollView.ScrollToAsync(0, 100, true);
Assert.AreEqual(y100Count, 2);
}
}
}

Просмотреть файл

@ -202,7 +202,18 @@ namespace Xamarin.Forms.Platform.Android
internal void UpdateScrollPosition(double x, double y)
{
if (_view != null)
{
if (_view.Orientation == ScrollOrientation.Both)
{
if (x == 0)
x = Forms.Context.FromPixels(_hScrollView.ScrollX);
if (y == 0)
y = Forms.Context.FromPixels(ScrollY);
}
Controller.SetScrolledPosition(x, y);
}
}
static int GetDistance(double start, double position, double v)
@ -248,8 +259,8 @@ namespace Xamarin.Forms.Platform.Android
var x = (int)Forms.Context.ToPixels(e.ScrollX);
var y = (int)Forms.Context.ToPixels(e.ScrollY);
int currentX = _view.Orientation == ScrollOrientation.Horizontal ? _hScrollView.ScrollX : ScrollX;
int currentY = _view.Orientation == ScrollOrientation.Horizontal ? _hScrollView.ScrollY : ScrollY;
int currentX = _view.Orientation == ScrollOrientation.Horizontal || _view.Orientation == ScrollOrientation.Both ? _hScrollView.ScrollX : ScrollX;
int currentY = _view.Orientation == ScrollOrientation.Vertical || _view.Orientation == ScrollOrientation.Both ? ScrollY : _hScrollView.ScrollY;
if (e.Mode == ScrollToMode.Element)
{
Point itemPosition = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
@ -275,10 +286,19 @@ namespace Xamarin.Forms.Platform.Android
return;
}
if (_view.Orientation == ScrollOrientation.Horizontal)
_hScrollView.ScrollTo(distX, distY);
else
ScrollTo(distX, distY);
switch (_view.Orientation)
{
case ScrollOrientation.Horizontal:
_hScrollView.ScrollTo(distX, distY);
break;
case ScrollOrientation.Vertical:
ScrollTo(distX, distY);
break;
default:
_hScrollView.ScrollTo(distX, distY);
ScrollTo(distX, distY);
break;
}
};
animator.AnimationEnd += delegate
{
@ -291,10 +311,19 @@ namespace Xamarin.Forms.Platform.Android
}
else
{
if (_view.Orientation == ScrollOrientation.Horizontal)
_hScrollView.ScrollTo(x, y);
else
ScrollTo(x, y);
switch (_view.Orientation)
{
case ScrollOrientation.Horizontal:
_hScrollView.ScrollTo(x, y);
break;
case ScrollOrientation.Vertical:
ScrollTo(x, y);
break;
default:
_hScrollView.ScrollTo(x, y);
ScrollTo(x, y);
break;
}
Controller.SendScrollFinished();
}
}