Temporarily Disabling LinearSmoothScroller During OnScrolled

Nathan Sokalski 4,126 Reputation points
2021-05-14T19:05:21.69+00:00

I use the following OnScrollListener to synchronize the scrolling of several RecyclerView(s):

public class RoundScrollEvent : RecyclerView.OnScrollListener
{
    public static int ScrollY;
    public override void OnScrolled(RecyclerView rv, int dx, int dy)
    {
        if (dy == 0) { return; }
        base.OnScrolled(rv, dx, dy);
        RoundScrollEvent.ScrollY += dy;

        RecyclerView rvScores;
        RecyclerView rvRoundNumbers;

        if (rv.Id == Resource.Id.rvRoundNumbers)
        {
            rvRoundNumbers = rv;
            rvScores = ((GridLayout)rv.Parent).FindViewById<RecyclerView>(Resource.Id.rvScores);
        }
        else
        {
            rvScores = rv.Parent as RecyclerView;
            rvRoundNumbers = ((GridLayout)rvScores.Parent).FindViewById<RecyclerView>(Resource.Id.rvRoundNumbers);
        }

        rvRoundNumbers.ClearOnScrollListeners();
        for (int playerindex = 0; playerindex < rvScores.ChildCount; playerindex++)
        { (rvScores.GetChildViewHolder(rvScores.GetChildAt(playerindex)) as ScoresViewHolder).rvPoints.ClearOnScrollListeners(); }

        ((LinearLayoutManager)rvRoundNumbers.GetLayoutManager()).ScrollToPositionWithOffset(0, -RoundScrollEvent.ScrollY);
        for (int playerindex = 0; playerindex < rvScores.ChildCount; playerindex++)
        { ((LinearLayoutManager)(rvScores.GetChildViewHolder(rvScores.GetChildAt(playerindex)) as ScoresViewHolder).rvPoints.GetLayoutManager()).ScrollToPositionWithOffset(0, -RoundScrollEvent.ScrollY); }

        rvRoundNumbers.AddOnScrollListener(new RoundScrollEvent());
        for (int playerindex = 0; playerindex < rvScores.ChildCount; playerindex++)
        { (rvScores.GetChildViewHolder(rvScores.GetChildAt(playerindex)) as ScoresViewHolder).rvPoints.AddOnScrollListener(new RoundScrollEvent()); }
    }
}

I also have the following LinearSmoothScroller:

public class RoundSmoothScroller : LinearSmoothScroller
{
    public RoundSmoothScroller(Context context) : base(context) { }

    public override int CalculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference)
    {
        if (this.TargetPosition == 0) { return base.CalculateDtToFit(viewStart, viewEnd, boxStart, boxEnd, LinearSmoothScroller.SnapToStart); }
        else if (this.TargetPosition == 1) { return base.CalculateDtToFit((int)(viewStart - 27 * Application.Context.Resources.DisplayMetrics.Density), viewEnd, boxStart, boxEnd, LinearSmoothScroller.SnapToStart); }
        else if (this.TargetPosition == MainActivity.Players[MainActivity.CurrentPlayerIndex].Scores.Count) { return base.CalculateDtToFit((int)(viewStart - (((MainActivity)Xamarin.Essentials.Platform.CurrentActivity).Cumulative ? 27 : 54) * Application.Context.Resources.DisplayMetrics.Density), (int)(viewStart + 81 * Application.Context.Resources.DisplayMetrics.Density), boxStart, boxEnd, LinearSmoothScroller.SnapToAny); }
        else { return base.CalculateDtToFit((int)(viewStart - (((MainActivity)Xamarin.Essentials.Platform.CurrentActivity).Cumulative ? 27 : 54) * Application.Context.Resources.DisplayMetrics.Density), (int)(viewStart + (((MainActivity)Xamarin.Essentials.Platform.CurrentActivity).Cumulative ? 81 : 108) * Application.Context.Resources.DisplayMetrics.Density), boxStart, boxEnd, LinearSmoothScroller.SnapToAny); }
    }
}

However, depending on previous scrolling & what is currently visible, the LinearSmoothScroller is sometimes called while the user is doing normal scrolling and prevents the user from scrolling. What I need to do is prevent the LinearSmoothScroller from being called when the user does normal scrolling so that it is only called when I scrolled programmatically using StartSmoothScroll. How can I do this? Thanks.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,325 questions
0 comments No comments
{count} votes

Accepted answer
  1. JarvanZhang 23,951 Reputation points
    2021-05-17T06:25:41.147+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    What I need to do is prevent the LinearSmoothScroller from being called when the user does normal scrolling so that it is only called when I scrolled programmatically using StartSmoothScroll

    There is no specific event to identify the type of activity, so we cannot prevent the OnScrolled being called. However, it's available to skip the function code of the event. For this function, you could just store a bool property using preference to distinguish the two cases.

       public class MainActivity : AppCompatActivity  
       {  
           public static bool IsCodeScrolling;  
       }  
    

    Detet the scrolling type in OnScrolled event.

       public class RoundScrollEvent : RecyclerView.OnScrollListener  
       {  
           public override void OnScrolled(RecyclerView rv, int dx, int dy)  
           {  
               var statusValue = Preferences.Get("IsCodeScrolling", false);  
               if (!statusValue)  
               {  
                   return;  
               }  
               ...  
               Preferences.Set("IsCodeScrolling", false);//set the value to false before leaving the event  
           }  
       }  
    

    Best Regards,

    Jarvan Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

0 additional answers

Sort by: Most helpful