$ show rubensousa/GravitySnapHelper
GravitySnapHelper is a mature Android library that extends LinearSnapHelper to snap RecyclerView items to an edge (START, END, TOP, BOTTOM) or CENTER. It provides configurable fling distance limits, scroll speed, snap-to-padding support, and a snap listener. The library also includes GravitySnapRecyclerView, a drop-in RecyclerView subclass that wires up the snap helper with XML attributes, and OrientationAwareRecyclerView to resolve nested RecyclerView touch conflicts. The sample app demonstrates various configurations including horizontal and vertical snapping, decoration-aware snapping, and pager-like behavior. The code is clean, well-documented, and makes effective use of Android's RecyclerView API. It has a strong following (nearly 5000 stars) and receives active maintenance.
The LLM identified 3 files worth highlighting for reuse:
Core class extending LinearSnapHelper with configurable edge/center snapping. Implements custom distance calculations for START/END/TOP/BOTTOM/CENTER gravities, fling distance limiting via setMaxFlingSizeFraction or setMaxFlingDistance, scroll speed control, snap-to-padding support, and a SnapListener interface. Uses Scroller for controlled fling and LinearSmoothScroller for smooth scroll-to-position. Handles RTL layout correctly. This is the primary reusable component and demonstrates deep understanding of RecyclerView's snap mechanics.
A RecyclerView subclass that integrates GravitySnapHelper with XML attribute configuration (snapGravity, snapEnabled, snapLastItem, snapToPadding, etc.). Overrides smoothScrollToPosition/scrollToPosition to delegate to the snap helper when snapping is enabled. Provides convenience methods like snapToNextPosition, snapToPreviousPosition, and getCurrentSnappedPosition. Demonstrates a pattern for wrapping complex behavior into a reusable, declarative custom view.
A RecyclerView subclass that resolves nested scroll conflicts by only intercepting touch events that align with the LayoutManager's orientation (horizontal vs vertical). This prevents scenarios where parent and child RecyclerViews compete for scroll events. Implements a clean pattern for disallowing intercept when the movement direction does not match the layout orientation, improving UX in nested RecyclerView setups.