StackLayoutManager
StackLayoutManager is a lightweight and highly-customizable layout manager for RecyclerView which lays out views by using a TimeInterpolator
object. This makes the views travel along the path that the interpolator provides, thus allowing us to create sophisticated transitions. Additionally, it supports setting a custom view transformation callback, which allows more elaborate transitions to be made through direct access to all transformation properties a view can have.
Demo app
You can download the demo APK from here
Installation
StackLayoutManager is a single Kotlin file, so you just need to copy the StackLayoutManager.kt
file to your project and change the package
declaration. That's it!
Showcase
Interpolators
Default | DenseStackInterpolator.kt |
LinearInterpolator |
---|---|---|
OvershootingInterpolator.kt |
ReverseStackInterpolator.kt |
CappedLinearInterpolator.kt |
Transformers
Setup
StackLayoutManager constructor doesn't require any parameters, so you can just use it directly like this
recyclerView.layoutManager = StackLayoutManager()
By default, StackLayoutManager will layout views horizontally and will center the first item (position == 0
). If you want to change either of those, or change other parameters, the constructor has a few optional, named parameters which you can set to customize your experience. Those parameters are:
Parameter | Type | Default | Description |
---|---|---|---|
horizontalLayout |
Boolean | true |
whether views should be laid out horizontally or vertically |
centerFirstItem |
Boolean | true |
whether the first item (with position == 0 ) should be centered. In some instances, specially when using Log interpolators, setting this to false will position the first child off-screen which could be confusing to users |
scrollMultiplier |
Float | 1.2f |
the number of items (as float, where each item is equal to 1f ) that should be scrolled in one swipe. Setting higher values will cause stuttering because of float rounding. It is recommended that you set this to 1.2f |
maxViews |
Int | 6 |
the maximum number of views that the RecyclerView should have. Higher values require more resources and might cause lag in some cases. It may be necessary to increase this number when using layout interpolators that create stacking effects, such as the case with DenseStackInterpolator.kt . It is recommended that you set this to anything between 6 and 10 |
layoutInterpolator |
TimeInterpolator | LogDecelerateInterpolator |
the interpolator which will be used to layout views. Any type of interpolator is accepted, such as LinearInterpolator() , FastOutSlowInInterpolator() , or the ones shown in the demo app. The interpolation typically starts from x, y = 0f, 0f and ends at x, y = 1f, 1f , but that is not always the case, as demonstrated in DenseStackInterpolator.kt . StackLayoutManager itself comes with only one interpolator, so you might need to copy one of the provided interpolators from the demo app or make your own interpolator. Check out the showcase section to see some of the provided interpolators |
viewTransformer |
((x: Float, view: View, stackLayoutManager: StackLayoutManager) -> Unit?)? |
ElevationTransformer |
supply a higher-order function that takes Float, View, StackLayoutManager and returns Unit (void). This is used to set a callback which allows the caller to have direct access to a view after it has been laid out by the layout manager. By using this, you will be able to apply additional transforms to the view, including the stock transforms such as rotation, scale, elevation; as well as any custom attribute of a custom view. The descriptions of the function parameters are as follows:
|
Public functions
Function | Description |
---|---|
scrollToPosition |
scroll to position with more control over the animation compared to the method provided by the default layout manager. Using this function, you can pass a float value as the target position, which translates to "target position + extra distance". You can also pass named parameters for more control. Those include: animated ; duration which is applicable when animated is true ; and endRunnable which is executed after the scroll has ended |
forceRemeasureInNextLayout |
notify the layout manager that the dimensions of the views have changed. By default, the layout manager measures only one child and then assumes the same dimensions for the rest of the views. Calling this method will remeasure that one standard view |
findFirstVisibleItemPosition , findFirstCompletelyVisibleItemPosition , findLastVisibleItemPosition , and findLastCompletelyVisibleItemPosition |
return the corresponding position of view as described in the function's name |
stopScrolling |
helper method to force stop scroll animator. This does not stop the scroll initiated by user input (e.g., fling) |
peek |
a helpful function that can be used to nudge or guide the user to the correct scrolling direction, or to inform the user that there are some views that are off-screen |
snap |
as the name suggests, this will cause the layout manager to snap to the next or previous view depending on the current scroll fraction |
Credits
The demo app uses assets from:
- SVGBackgrounds
- Simone Hutsch @ Unsplash
- WishforgeGames @ IconFinder
- RoyyanWijaya @ IconFinder
License
MIT
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.