Joel Anderson Joel Anderson - 1 month ago 30
Android Question

Xamarin android C# ScrollView OnScrollChanged event

In Xamarin Android how can we extend the ScrollView in order to use the protected OnScrollChanged event?

Specifically,
How do we extend the ScrollView to allow an EventHandler to be registered to the OnScrollChanged event?
What other methods of ScrollView need to be implemented in a class that extends ScrollView?

Reasons:

The Android ScrollView does not have a way to listen for a scroll event.
There have been various questions regarding how to extend ScrollView in native Android Java, however, there is not a question and answer addressing how to apply this to Xamarin.

Answer

In order to extend ScrollView in this way we should implement 3 constructors

public UsefulScrollView(Context context)
public UsefulScrollView(Context context, IAttributeSet attrs)
public UsefulScrollView(Context context, IAttributeSet attrs, int defStyle)

We also need to override the OnDraw method

protected override void OnDraw(Android.Graphics.Canvas canvas)

To achieve the functionality of an event that we can respond to when the user scrolls we need to override the OnScrollChanged method.

protected override void OnScrollChanged(int l, int t, int oldl, int oldt)

There are multiple ways to allow event listening and handling, but in order to be consistent with Xamarin we can add a public EventHandler property to our class.

public EventHandler<T> ScrollEventHandler { get; set; }

We will want to pass along the values from OnScrollChanged to the EventHandler, so let's extend EventArgs

public class UsefulScrollEventArgs : EventArgs{
    public int l { get; set; }
    public int t { get; set; }
    public int oldl { get; set; }
    public int oldt { get; set; }
}

Finally, don't forget to initialize our handler in each of our constructors

ScrollEventHandler = (object sender, UsefulScrollEventArgs e) => {};

Put it all together and it might look something like this

Extended EventArgs class

public class UsefulScrollEventArgs : EventArgs{
    public int l { get; set; }
    public int t { get; set; }
    public int oldl { get; set; }
    public int oldt { get; set; }
}

Extended ScrollView class

public class UsefulScrollView : ScrollView
{
    public EventHandler<UsefulScrollEventArgs> ScrollEventHandler { get; set; }
    public UsefulScrollView (Context context)
    : base(context)
    {
        ScrollEventHandler = (object sender, UsefulScrollEventArgs e) => {};
    }
    public UsefulScrollView (Context context, IAttributeSet attrs)
    : base(context, attrs) {
        ScrollEventHandler = (object sender, UsefulScrollEventArgs e) => {};

    }
    public UsefulScrollView(Context context, IAttributeSet attrs, int defStyle)
    : base(context, attrs, defStyle) {
        ScrollEventHandler = (object sender, UsefulScrollEventArgs e) => {};

    }
    protected override void OnScrollChanged(int l, int t, int oldl, int oldt)
    {
        ScrollEventHandler (this, 
                   new UsefulScrollEventArgs ()
                   {l=l,t=t,oldl=oldl,oldt=oldt});
        base.OnScrollChanged (l, t, oldl, oldt);
    }
    protected override void OnDraw(Android.Graphics.Canvas canvas)
    {

    }
}

This Q&A was helpful in figuring this problem out: Scrollview listener is not working in Xamarin for Android?

Comments