public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
        {
            base.OnScrolled(recyclerView, dx, dy);

            // TODO: These offsets will be incorrect upon row size or count change.
            // They are currently provided in place of LayoutManager's default offset calculation
            // because it does not report accurate values in the presence of uneven rows.
            // See https://stackoverflow.com/questions/27507715/android-how-to-get-the-current-x-offset-of-recyclerview
            _horizontalOffset += dx;
            _verticalOffset   += dy;

            var(First, Center, Last) = GetVisibleItemsIndex(recyclerView);
            var itemsViewScrolledEventArgs = new ItemsViewScrolledEventArgs
            {
                HorizontalDelta       = recyclerView.FromPixels(dx),
                VerticalDelta         = recyclerView.FromPixels(dy),
                HorizontalOffset      = recyclerView.FromPixels(_horizontalOffset),
                VerticalOffset        = recyclerView.FromPixels(_verticalOffset),
                FirstVisibleItemIndex = First,
                CenterItemIndex       = Center,
                LastVisibleItemIndex  = Last
            };

            _itemsView.SendScrolled(itemsViewScrolledEventArgs);

            // Don't send RemainingItemsThresholdReached event for non-linear layout managers
            // This can also happen if a layout pass has not happened yet
            if (Last == -1)
            {
                return;
            }

            switch (_itemsView.RemainingItemsThreshold)
            {
            case -1:
                return;

            case 0:
                if (Last == ItemsViewAdapter.ItemCount - 1)
                {
                    _itemsView.SendRemainingItemsThresholdReached();
                }
                break;

            default:
                if (ItemsViewAdapter.ItemCount - 1 - Last <= _itemsView.RemainingItemsThreshold)
                {
                    _itemsView.SendRemainingItemsThresholdReached();
                }
                break;
            }
        }