From 2fddd083e98998d12494e05d3916fef57d03af6e Mon Sep 17 00:00:00 2001 From: Pavel Yakovlev Date: Thu, 6 Jun 2019 06:55:17 -0700 Subject: [PATCH] [Android] fixes ListView pull-to-refresh gesture in non-data areas (#5417) fixes #5268 * [Android] fixes ListView pull-to-refresh gesture in non-data areas * refactoring * addressing comments --- .../Issue5268.xaml | 27 ++++++++++ .../Issue5268.xaml.cs | 42 ++++++++++++++++ .../Xamarin.Forms.Controls.Issues.Shared.projitems | 10 ++++ .../Renderers/ListViewRenderer.cs | 57 +++++++++++++++++++++- 4 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml create mode 100644 Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml.cs diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml new file mode 100644 index 0000000..1767193 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml.cs new file mode 100644 index 0000000..22b1650 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5268.xaml.cs @@ -0,0 +1,42 @@ +#if APP +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Input; +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Github, 5268, "ListView with PullToRefresh enabled gestures conflict", PlatformAffected.Android)] + public partial class Issue5268 : ContentPage + { + [Preserve(AllMembers = true)] + public class SrcItem + { + public string Val { get; set; } + } + + string GenerateLongString() => string.Join(" \n", Enumerable.Range(0, 50).Select(i => $"{Sources.Count} item")); + + public ObservableCollection Sources { get; } + public ICommand Command { get; } + + public Issue5268() + { + InitializeComponent(); + Sources = new ObservableCollection(); + Command = new Command(AddData); + Sources.Add(new SrcItem { Val = GenerateLongString() }); + MyListView.BindingContext = this; + } + + void AddData() + { + IsBusy = true; + Sources.Add(new SrcItem { Val = GenerateLongString() }); + IsBusy = false; + } + } +} +#endif \ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index d996581..22a7b12 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -434,6 +434,10 @@ Issue5003.xaml Code + + Issue5268.xaml + Code + @@ -1119,4 +1123,10 @@ MSBuild:Compile + + + Designer + MSBuild:Compile + + \ No newline at end of file diff --git a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs index 58450bf..b8ed391 100644 --- a/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs +++ b/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs @@ -9,6 +9,7 @@ using Xamarin.Forms.Internals; using System; using Xamarin.Forms.PlatformConfiguration.AndroidSpecific; using Android.Widget; +using Android.Runtime; namespace Xamarin.Forms.Platform.Android { @@ -102,6 +103,9 @@ namespace Xamarin.Forms.Platform.Android return new Size(40, 40); } + protected virtual SwipeRefreshLayout CreateNativePullToRefresh(Context context) + => new SwipeRefreshLayoutWithFixedNestedScrolling(context); + protected override void OnAttachedToWindow() { base.OnAttachedToWindow(); @@ -154,9 +158,9 @@ namespace Xamarin.Forms.Platform.Android nativeListView = CreateNativeControl(); if (Forms.IsLollipopOrNewer) nativeListView.NestedScrollingEnabled = true; - _refresh = new SwipeRefreshLayout(ctx); + _refresh = CreateNativePullToRefresh(ctx); _refresh.SetOnRefreshListener(this); - _refresh.AddView(nativeListView, LayoutParams.MatchParent); + _refresh.AddView(nativeListView, new LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent)); SetNativeControl(nativeListView, _refresh); _headerView = new Container(ctx); @@ -523,5 +527,54 @@ namespace Xamarin.Forms.Platform.Android SetMeasuredDimension(widthSpec, heightSpec); } } + + class SwipeRefreshLayoutWithFixedNestedScrolling : SwipeRefreshLayout + { + float _touchSlop; + float _initialDownY; + bool _nestedScrollAccepted; + bool _nestedScrollCalled; + + public SwipeRefreshLayoutWithFixedNestedScrolling(Context ctx) : base(ctx) + { + _touchSlop = ViewConfiguration.Get(ctx).ScaledTouchSlop; + } + + public override bool OnInterceptTouchEvent(MotionEvent ev) + { + if (ev.Action == MotionEventActions.Down) + _initialDownY = ev.GetAxisValue(Axis.Y); + + var isBeingDragged = base.OnInterceptTouchEvent(ev); + + if (!isBeingDragged && ev.Action == MotionEventActions.Move && _nestedScrollAccepted && !_nestedScrollCalled) + { + var y = ev.GetAxisValue(Axis.Y); + var dy = (y - _initialDownY) / 2; + isBeingDragged = dy > _touchSlop; + } + + return isBeingDragged; + } + + public override void OnNestedScrollAccepted(AView child, AView target, [GeneratedEnum] ScrollAxis axes) + { + base.OnNestedScrollAccepted(child, target, axes); + _nestedScrollAccepted = true; + _nestedScrollCalled = false; + } + + public override void OnStopNestedScroll(AView child) + { + base.OnStopNestedScroll(child); + _nestedScrollAccepted = false; + } + + public override void OnNestedScroll(AView target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) + { + base.OnNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); + _nestedScrollCalled = true; + } + } } } -- 2.7.4