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; } }