[Android] Fixed issue refreshing CollectionView using ScrollView inside DataTemplate...
authorJavier Suárez Ruiz <javiersuarezruiz@hotmail.com>
Tue, 29 Oct 2019 11:31:39 +0000 (12:31 +0100)
committerRui Marinho <me@ruimarinho.net>
Tue, 29 Oct 2019 11:31:39 +0000 (11:31 +0000)
* Fixed issue 8198 - ScrollView at CollectionView at RefreshView always leads to Pull-To-Refresh

* Added instructions to the Issue8198

* Added support for WebView on Android to align functionality with iOS

* Added more RefreshView Core Gallery samples

* Updated new samples

* Updated instructions text

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8198.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml [new file with mode: 0644]
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCollectionViewGallery.xaml
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshListViewGallery.xaml
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshViewGallery.cs
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml [new file with mode: 0644]
Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
Xamarin.Forms.Platform.Android/Renderers/RefreshViewRenderer.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8198.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue8198.cs
new file mode 100644 (file)
index 0000000..5c8e9e1
--- /dev/null
@@ -0,0 +1,114 @@
+using System;
+using System.Threading.Tasks;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+#if UITEST
+using Xamarin.Forms.Core.UITests;
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+#if UITEST
+       [Category(UITestCategories.RefreshView)]
+#endif
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Github, 8198, "ScrollView at CollectionView at RefreshView always leads to Pull-To-Refresh", PlatformAffected.Android)]
+       public class Issue8198 : TestContentPage
+       {
+               RefreshView _refreshView;
+               Command _refreshCommand;
+  
+               protected override void Init()
+               {
+                       Title = "Issue 8198";
+
+                       var layout = new StackLayout();
+
+                       var instructions = new Label
+                       {
+                               BackgroundColor = Color.Black,
+                               TextColor = Color.White,
+                               Text = "Scroll the CollectionView to end, lift finger off screen, and then try to scroll up again. If the Refresh Indicator does not appear until it reaches the top, the test has passed."
+                       };
+
+                       _refreshCommand = new Command(async (parameter) =>
+                       {
+                               if (!_refreshView.IsRefreshing)
+                               {
+                                       throw new Exception("IsRefreshing should be true when command executes");
+                               }
+
+                               if (parameter != null && !(bool)parameter)
+                               {
+                                       throw new Exception("Refresh command incorrectly firing with disabled parameter");
+                               }
+
+                               await Task.Delay(2000);
+                               _refreshView.IsRefreshing = false;
+                       });
+
+                       _refreshView = new RefreshView
+                       {
+                               Command = _refreshCommand
+                       };
+
+                       var collectionView = new CollectionView
+                       {
+                               ItemTemplate = GetDataTemplate(),
+                               ItemsSource = new string[]
+                               {
+                                       "Item 1",
+                                       "Item 2",
+                                       "Item 3",
+                                       "Item 4",
+                                       "Item 5",
+                                       "item 6",
+                                       "Item 7",
+                                       "Item 8",
+                                       "Item 9",
+                                       "Item 10",
+                                       "Item 11",
+                                       "item 12",
+                                       "Item 13",
+                                       "Item 14",
+                                       "Item 15",
+                                       "Item 16",
+                                       "Item 17",
+                                       "Item 18",
+                                       "Item 19",
+                                       "Item 20"
+                               }
+                       };
+
+                       _refreshView.Content = collectionView;
+
+                       layout.Children.Add(instructions);
+                       layout.Children.Add(_refreshView);
+
+                       Content = layout;
+               }
+
+               DataTemplate GetDataTemplate()
+               {
+                       var template = new DataTemplate(() =>
+                       {
+                               var scroll = new ScrollView();
+                               var grid = new Grid();
+                               grid.RowDefinitions.Add(new RowDefinition() { Height = 40 });
+
+                               var cell = new Label();
+                               cell.SetBinding(Label.TextProperty, ".");
+                               cell.FontSize = 20;
+                               cell.BackgroundColor = Color.LightBlue;
+                               grid.Children.Add(cell, 0, 0);
+
+                               scroll.Content = grid;
+                               return scroll;
+                       });
+                       return template;
+               }
+       }
+}
\ No newline at end of file
index 8f14504..05a80a1 100644 (file)
       <DependentUpon>Issue7886.xaml</DependentUpon>
     </Compile>
     <Compile Include="$(MSBuildThisFileDirectory)Issue7898.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Issue8198.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="$(MSBuildThisFileDirectory)Bugzilla22229.xaml">
diff --git a/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml
new file mode 100644 (file)
index 0000000..30f1de4
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             mc:Ignorable="d"
+             x:Class="Xamarin.Forms.Controls.GalleryPages.RefreshViewGalleries.RefreshCarouselViewGallery"  
+             Title="CarouselView (Pull To Refresh)">
+    <ContentPage.Content>
+        <RefreshView
+            IsRefreshing="{Binding IsRefreshing}"
+            RefreshColor="Pink"
+            Command="{Binding RefreshCommand}"
+            HorizontalOptions="FillAndExpand"
+            VerticalOptions="FillAndExpand">
+            <CarouselView
+                ItemsSource="{Binding Items}">
+                <CarouselView.ItemsLayout>
+                    <LinearItemsLayout
+                        Orientation="Horizontal"
+                        SnapPointsAlignment="Center"
+                        SnapPointsType="MandatorySingle"/>
+                </CarouselView.ItemsLayout>
+                <CarouselView.ItemTemplate>
+                    <DataTemplate>
+                        <ScrollView>
+                            <Grid>
+                                <Grid.RowDefinitions>
+                                    <RowDefinition Height="*" />
+                                    <RowDefinition Height="Auto" />
+                                </Grid.RowDefinitions>
+                                <BoxView
+                                    Grid.Row="0"
+                                    Color="{Binding Color}"/>
+                                <Label
+                                    Grid.Row="1"
+                                    Text="{Binding Name}"
+                                    VerticalOptions="Center"
+                                    HeightRequest="48"/>
+                            </Grid>
+                        </ScrollView>
+                    </DataTemplate>
+                </CarouselView.ItemTemplate>
+            </CarouselView>
+        </RefreshView>
+    </ContentPage.Content>
+</ContentPage>
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshCarouselViewGallery.xaml.cs
new file mode 100644 (file)
index 0000000..ce1e8df
--- /dev/null
@@ -0,0 +1,14 @@
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls.GalleryPages.RefreshViewGalleries
+{
+       [Preserve(AllMembers = true)]
+       public partial class RefreshCarouselViewGallery : ContentPage
+       {
+               public RefreshCarouselViewGallery()
+               {
+                       InitializeComponent();
+            BindingContext = new RefreshViewModel();
+        }
+       }
+}
\ No newline at end of file
index f94bd0f..51a9f1b 100644 (file)
                 ItemsSource="{Binding Items}">
                 <CollectionView.ItemTemplate>
                      <DataTemplate>
-                        <Grid>
-                            <Grid.ColumnDefinitions>
-                                <ColumnDefinition Width="48" />
-                                <ColumnDefinition Width="*" />
-                            </Grid.ColumnDefinitions>
-                            <BoxView
-                                Grid.Column="0"
-                                Color="{Binding Color}"
-                                HeightRequest="48"/>
-                            <Label
-                                Grid.Column="1"
-                                Text="{Binding Name}"/>
-                        </Grid>
+                         <ScrollView>
+                             <Grid>
+                                 <Grid.ColumnDefinitions>
+                                    <ColumnDefinition Width="48" />
+                                    <ColumnDefinition Width="*" />
+                                 </Grid.ColumnDefinitions>
+                                 <BoxView
+                                    Grid.Column="0"
+                                    Color="{Binding Color}"
+                                    HeightRequest="48"/>
+                                 <Label
+                                    Grid.Column="1"
+                                    Text="{Binding Name}"/>
+                             </Grid>
+                        </ScrollView>
                     </DataTemplate>
                 </CollectionView.ItemTemplate>
             </CollectionView>
index b3ee912..5014c60 100644 (file)
                     <ListView.ItemTemplate>
                         <DataTemplate>
                             <ViewCell>
-                                <Grid>
-                                    <Grid.ColumnDefinitions>
-                                        <ColumnDefinition Width="48" />
-                                        <ColumnDefinition Width="*" />
-                                    </Grid.ColumnDefinitions>
-                                    <BoxView
-                                        Grid.Column="0"
-                                        Color="{Binding Color}"
-                                        HeightRequest="48"/>
-                                    <Label
-                                        Grid.Column="1"
-                                        Text="{Binding Name}"/>
-                                </Grid>
+                                <ScrollView>
+                                    <Grid>
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition Width="48" />
+                                            <ColumnDefinition Width="*" />
+                                        </Grid.ColumnDefinitions>
+                                        <BoxView
+                                            Grid.Column="0"
+                                            Color="{Binding Color}"
+                                            HeightRequest="48"/>
+                                        <Label
+                                            Grid.Column="1"
+                                            Text="{Binding Name}"/>
+                                    </Grid>
+                                </ScrollView>
                             </ViewCell>
                         </DataTemplate>
                     </ListView.ItemTemplate>
index d23f527..ac6bed1 100644 (file)
@@ -11,17 +11,39 @@ namespace Xamarin.Forms.Controls.GalleryPages.RefreshViewGalleries
                public RefreshViewGallery()
                {
                        Title = "RefreshView Gallery";
+
+                       var button = new Button
+                       {
+                               Text = "Enable CarouselView",
+                               AutomationId = "EnableCarouselView"
+                       };
+                       button.Clicked += ButtonClicked;
+
                        Content = new StackLayout
                        {
                                Children =
                                {
+                                       button,
                                        GalleryBuilder.NavButton("Refresh Layout Gallery", () => new RefreshLayoutGallery(), Navigation),
                                        GalleryBuilder.NavButton("Refresh ScrollView Gallery", () => new RefreshScrollViewGallery(), Navigation),
                                        GalleryBuilder.NavButton("Refresh ListView Gallery", () => new RefreshListViewGallery(), Navigation),
-                                       GalleryBuilder.NavButton("Refresh CollectionView Gallery", () => new RefreshCollectionViewGallery(), Navigation)
+                                       GalleryBuilder.NavButton("Refresh CollectionView Gallery", () => new RefreshCollectionViewGallery(), Navigation),
+                                       GalleryBuilder.NavButton("Refresh CarouselView Gallery", () => new RefreshCarouselViewGallery(), Navigation),
+                                       GalleryBuilder.NavButton("Refresh WebView Gallery", () => new RefreshWebViewGallery(), Navigation)
                                }
                        };
                }
+
+               void ButtonClicked(object sender, System.EventArgs e)
+               {
+                       var button = sender as Button;
+
+                       button.Text = "CarouselView Enabled!";
+                       button.TextColor = Color.Black;
+                       button.IsEnabled = false;
+
+                       Device.SetFlags(new[] { ExperimentalFlags.CarouselViewExperimental });
+               }
        }
 
        [Preserve(AllMembers = true)]
diff --git a/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml b/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml
new file mode 100644 (file)
index 0000000..aa8259c
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             mc:Ignorable="d"
+             x:Class="Xamarin.Forms.Controls.GalleryPages.RefreshViewGalleries.RefreshWebViewGallery"
+             Title="WebView (Pull To Refresh)">
+    <ContentPage.Content>
+        <RefreshView
+            IsRefreshing="{Binding IsRefreshing}"
+            Command="{Binding RefreshCommand}"
+            HorizontalOptions="FillAndExpand"
+            VerticalOptions="FillAndExpand">
+            <WebView
+                Source="{Binding Url}"/>
+        </RefreshView>
+    </ContentPage.Content>
+</ContentPage>
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/RefreshViewGalleries/RefreshWebViewGallery.xaml.cs
new file mode 100644 (file)
index 0000000..5d9bce7
--- /dev/null
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Input;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls.GalleryPages.RefreshViewGalleries
+{
+       [Preserve(AllMembers = true)]
+       public partial class RefreshWebViewGallery : ContentPage
+       {
+               public RefreshWebViewGallery()
+               {
+                       InitializeComponent();
+                       BindingContext = new RefreshWebViewGalleryViewModel();
+               }
+       }
+
+       [Preserve(AllMembers = true)]
+       public class RefreshWebViewGalleryViewModel : BindableObject
+       {
+               const int RefreshDuration = 2;
+
+               readonly Random _random;
+               bool _isRefresing;
+               string _url;
+
+               public RefreshWebViewGalleryViewModel()
+               {
+                       _random = new Random();
+                       LoadUrl();
+               }
+
+               public bool IsRefreshing
+               {
+                       get { return _isRefresing; }
+                       set
+                       {
+                               _isRefresing = value;
+                               OnPropertyChanged();
+                       }
+               }
+
+               public string Url
+               {
+                       get { return _url; }
+                       set
+                       {
+                               _url = value;
+                               OnPropertyChanged();
+                       }
+               }
+
+               public ICommand RefreshCommand => new Command(ExecuteRefresh);
+
+               void LoadUrl()
+               {
+                       var urls = new List<string> { "https://dotnet.microsoft.com/apps/xamarin", "https://devblogs.microsoft.com/xamarin/" };
+                       int index = _random.Next(urls.Count);
+                       Url = urls[index];
+               }
+
+               void ExecuteRefresh()
+               {
+                       IsRefreshing = true;
+
+                       Device.StartTimer(TimeSpan.FromSeconds(RefreshDuration), () =>
+                       {
+                               LoadUrl();
+
+                               IsRefreshing = false;
+
+                               return false;
+                       });
+               }
+       }
+}
\ No newline at end of file
index 5e81105..38e427e 100644 (file)
     <EmbeddedResource Update="GalleryPages\MapWithItemsSourceGallery.xaml">
       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
     </EmbeddedResource>
+    <EmbeddedResource Update="GalleryPages\RefreshViewGalleries\RefreshCarouselViewGallery.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+    <EmbeddedResource Update="GalleryPages\RefreshViewGalleries\RefreshWebViewGallery.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
     <EmbeddedResource Update="GalleryPages\TitleView.xaml">
       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
     </EmbeddedResource>
index 88c7af9..2487ee3 100644 (file)
@@ -9,6 +9,7 @@ using Android.Views;
 using Android.Widget;
 using Xamarin.Forms.Internals;
 using AView = Android.Views.View;
+using AWebView = Android.Webkit.WebView;
 
 namespace Xamarin.Forms.Platform.Android
 {
@@ -170,13 +171,13 @@ namespace Xamarin.Forms.Platform.Android
                        }
 
                        if(view is RecyclerView recyclerView)
-                               return recyclerView.ScrollY < 0;
-
-                       if (view is global::Android.Widget.ScrollView scrollview)
-                               return scrollview.ScrollY < 0;
+                               return recyclerView.ComputeVerticalScrollOffset() > 0;
 
                        if (view is NestedScrollView nestedScrollView)
-                               return nestedScrollView.ScrollY < 0;
+                               return nestedScrollView.ComputeVerticalScrollOffset() > 0;
+
+                       if (view is AWebView webView)
+                               return webView.ScrollY > 0;
 
                        return true;
                }