Fix ScrollTo on Mac (#4983) * fixes #3319
authorSanya Andreichuk <sanya2371@gmail.com>
Wed, 13 Feb 2019 13:39:52 +0000 (15:39 +0200)
committerRui Marinho <me@ruimarinho.net>
Wed, 13 Feb 2019 13:39:52 +0000 (13:39 +0000)
* Fix github issue #3319

Fix  #3319 [MAC] ScrollTo method is not working in Xamarin.Forms for mac platform

* Update Issue3318.cs

Fix Issue3318 UITest.

* Fix github issue #3319

Fix  #3319 [MAC] ScrollTo method is not working in Xamarin.Forms for mac platform

* Update Issue3318.cs

Fix Issue3318 UITest.

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3318.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Platform.MacOS/Renderers/ListViewRenderer.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3318.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue3318.cs
new file mode 100644 (file)
index 0000000..e7dbd41
--- /dev/null
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Text;
+using System.Threading.Tasks;
+using System.Linq;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.Forms.Core.UITests;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Github, 3318, "[MAC] ScrollTo method is not working in Xamarin.Forms for mac platform", PlatformAffected.macOS)]
+
+       public class Issue3318 : TestContentPage
+       {
+               protected override void Init()
+               {
+                       var stackLayout = new StackLayout();
+
+                       var list = Enumerable.Range(0, 40).Select(c => $"Item {c}").ToArray();
+                       var listview = new ListView { ItemsSource = list };
+
+                       var swShouldAnimate = new Switch();
+                       var lblShouldAnimate = new Label { Text = "Should Animate?" };
+
+                       var btnMakeVisible = new Button { Text = "Make Visible" };
+                       btnMakeVisible.Clicked += (s, e) =>
+                       {
+                               listview.ScrollTo(list[19], ScrollToPosition.MakeVisible, swShouldAnimate.IsToggled);
+                       };
+
+                       var btnCenter = new Button { Text = "Center" };
+                       btnCenter.Clicked += (s, e) =>
+                       {
+                               listview.ScrollTo(list[19], ScrollToPosition.Center, swShouldAnimate.IsToggled);
+                       };
+
+                       var btnStart = new Button { Text = "Start" };
+                       btnStart.Clicked += (s, e) =>
+                       {
+                               listview.ScrollTo(list[19], ScrollToPosition.Start, swShouldAnimate.IsToggled);
+                       };
+
+                       var btnEnd = new Button { Text = "End" };
+                       btnEnd.Clicked += (s, e) =>
+                       {
+                               listview.ScrollTo(list[19], ScrollToPosition.End, swShouldAnimate.IsToggled);
+                       };
+
+                       stackLayout.Children.Add(btnMakeVisible);
+                       stackLayout.Children.Add(btnCenter);
+                       stackLayout.Children.Add(btnStart);
+                       stackLayout.Children.Add(btnEnd);
+
+                       var shouldAnimateContainer = new StackLayout { Orientation = StackOrientation.Horizontal };
+                       shouldAnimateContainer.Children.Add(swShouldAnimate);
+                       shouldAnimateContainer.Children.Add(lblShouldAnimate);
+
+                       stackLayout.Children.Add(shouldAnimateContainer);
+                       stackLayout.Children.Add(listview);
+
+                       Content = stackLayout;
+               }
+
+
+#if UITEST
+               [Test]
+               public void Issue3318Test()
+               {
+                       RunningApp.WaitForElement (q => q.Marked ("End"));
+                       RunningApp.Tap (q => q.Marked ("End"));
+                       RunningApp.WaitForElement (q => q.Marked ("Item 19"));
+                       RunningApp.Back ();
+               }
+#endif
+       }
+}
index 3cec17e..b5dbd35 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)Issue3622.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue4138.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue4314.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Issue3318.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
index 4f74d5c..8658002 100644 (file)
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Collections.Specialized;
 using System.ComponentModel;
 using System.Linq;
@@ -346,9 +347,66 @@ namespace Xamarin.Forms.Platform.MacOS
                {
                }
 
-               //TODO: Implement ScrollTo
                void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
                {
+                       var templatedItems = TemplatedItemsView.TemplatedItems;
+                       var scrollArgs = (ITemplatedItemsListScrollToRequestedEventArgs)e;
+
+                       var row = templatedItems?.GetGlobalIndexOfItem(scrollArgs.Item) ?? -1;
+                       if (row == -1)
+                               return;
+
+                       var rowRect = _table.RectForRow(row);
+                       var rowHeight = rowRect.Height;
+                       var clipView = _table.Superview as NSClipView;
+                       var clipViewHeight = clipView.Frame.Height;
+                       var scrollToPosition = e.Position;
+
+                       if (scrollToPosition == ScrollToPosition.MakeVisible)
+                       {
+                               var topVisibleY = clipView.Bounds.Y;
+                               var bottomVisibleY = clipView.Bounds.Y + clipViewHeight - rowHeight;
+
+                               if (topVisibleY > rowRect.Y)
+                               {
+                                       scrollToPosition = ScrollToPosition.Start;
+                               }
+                               else if (bottomVisibleY < rowRect.Y)
+                               {
+                                       scrollToPosition = ScrollToPosition.End;
+                               }
+                               else
+                               {
+                                       return;
+                               }
+                       }
+
+                       nfloat y = 0;
+                       var scrollOrigin = rowRect.Location;
+
+                       if (scrollToPosition == ScrollToPosition.Center)
+                       {
+                               y = (scrollOrigin.Y - clipViewHeight / 2) + rowHeight / 2;
+                       }
+                       else if (scrollToPosition == ScrollToPosition.End)
+                       {
+                               y = scrollOrigin.Y - clipViewHeight + rowHeight;
+                       }
+                       else
+                       {
+                               y = scrollOrigin.Y;
+                       }
+
+                       scrollOrigin.Y = y;
+
+                       if (e.ShouldAnimate)
+                       {
+                               ((NSView)clipView.Animator).SetBoundsOrigin(scrollOrigin);
+                       }
+                       else
+                       {
+                               clipView.SetBoundsOrigin(scrollOrigin);
+                       }
                }
 
                //TODO: Implement Footer