Search code examples
c#xamarinxamarin.formsscrollview

How to make ScrollView's Scrolled event only respond to user actions in Xamarin.Forms?


I have a ScrollView that uses code to control automatic scrolling. I need to stop the automatic scrolling when the user inputs, but the ScrollToAsync method of the ScrollView will also trigger the Scrolled event.

   <StackLayout>
            <ScrollView Scrolled="ScrollView_Scrolled">
                <StackLayout></StackLayout>
            </ScrollView>
   </StackLayout>

Solution

  • The short answer

    You could use a flag to tell the event who is triggering the scroll event as follows

    Boolean scrolledByUser = true;
    
    private async void MyScrollView_Scrolled(object sender, ScrolledEventArgs e)
    {
      if (scrolledByUser)
      {
        // do something
      }
      else // scrolled automagically
      {
        // do something else
      }
    }
    
    private async void ScrollAutomagically(object sender, EventArgs e)
    {
      scrolledByUser = false;
      await MyScrollView.ScrollToAsync(ScrollView.X, 800, true);
      scrolledByUser = true;
    }
    

    The long answer

    Next you can find a complete sample to illustrate my suggestion.

    You start with a new blank project, and then modify App.xaml.cs to look like

    App.xaml.cs

    using Xamarin.Forms;
    
    namespace scrollviewPrompt
    {
        public partial class App : Application
        {
            public App()
            {
                InitializeComponent();
    
                MainPage = new NavigationPage(new MainPage());
            }
        }
    }
    

    then go on to modify the MainPage.xaml to include a ScrollView with lots of BoxViews vertically, one above the other:

    MainPage.xaml

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="scrollviewPrompt.MainPage">
    
        <ContentPage.ToolbarItems>
            <ToolbarItem Text="ScrollTo"
                         Clicked="ScrollAutomagically"/>
        </ContentPage.ToolbarItems>
    
        <ScrollView x:Name="MyScrollView" 
                        Scrolled="MyScrollView_Scrolled">
            <StackLayout>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
                <BoxView BackgroundColor="Red"         HeightRequest="128"/>
                <BoxView BackgroundColor="Orange"      HeightRequest="128"/>
                <BoxView BackgroundColor="Blue"      HeightRequest="128"/>
                <BoxView BackgroundColor="Green"      HeightRequest="128"/>
                <BoxView BackgroundColor="Black"      HeightRequest="128"/>
                <BoxView BackgroundColor="AliceBlue"         HeightRequest="128"/>
                <BoxView BackgroundColor="Brown"      HeightRequest="128"/>
                <BoxView BackgroundColor="Pink"      HeightRequest="128"/>
                <BoxView BackgroundColor="White"      HeightRequest="128"/>
                <BoxView BackgroundColor="Yellow"      HeightRequest="128"/>
            </StackLayout>
        </ScrollView>
    </ContentPage>
    

    and finally add the event handlers

    using System;
    using Xamarin.Forms;
    
    namespace scrollviewPrompt
    {
        public partial class MainPage : ContentPage
        {
            public MainPage()
            {
                InitializeComponent();
            }
    
            Boolean handled = false;
    
            Boolean scrolledByUser = true;
    
            private async void MyScrollView_Scrolled(object sender, ScrolledEventArgs e)
            {
                if (!handled)
                {
                    handled = true;
    
                    if (scrolledByUser)
                    {
                        await DisplayAlert("Alert", "ScrollView Scrolled by user!", "Ok");
                    }
                    else
                    {
                        await DisplayAlert("Alert", "ScrollView Scrolled automagically!", "Ok");
                    }
                    handled = false;
                }
            }
    
            private async void ScrollAutomagically(object sender, EventArgs e)
            {
                scrolledByUser = false;
                await MyScrollView.ScrollToAsync(MyScrollView.X, 800, true);
                scrolledByUser = true;
            }
        }
    }
    

    Hope this helps!