Skip to content

DirectionalDeciders

Beka Westberg edited this page Dec 23, 2019 · 1 revision

A DirectionalDecider is a function used to decide which movement direction the layout should scroll in to find a view with a given adapter index.

A DirectionalDecider is used by functions like smoothScrollToPosition.

To set the DirectionDecider used by the smoothScrollToPosition function, simply assign a function to the smoothScrollDirectionDecider property of the layout manager.

Built-in DirectionDeciders

This library provides three built-in DirectionDeciders estimateShortestRoute, addViewsAtAnchorEdge and addViewsAtOptAnchorEdge.

estimateShortestRoute

The estimateShortestRoute DirectionDecider is the default DirectionDecider. If you do not overwrite the smoothScrollToPosition property, this is the decider that will be used.

It returns the movement direction it thinks will make the view appear with the least amount of scrolling. This function assumes that all of the views are the same width, so if some views are larger or smaller than others, it may not be accurate.

addViewsAtAnchorEdge

This DirectionDecider returns the movement direction associated with adding views at the anchor edge. So when the target view appears, it will be aligned with the anchor edge.

The anchor edge is the edge where the view with the 0 adapter index was initially laid out. For example, in a default vertical layout, the anchor edge would be the top. In a reversed vertical layout, the anchor edge would be the bottom.

addViewsAtOptAnchorEdge

This DirectionalDecider returns the movement direction associated with adding views at the edge opposite the anchor edge. So when the target view appears, it will be aligned with the edge opposite the anchor edge.

For an explanation of what the anchor edge is see addViewsAtAnchorEdge.

Creating a custom directional decider

Sometimes these built-in functions don't cover the needs of your app. Luckily! You can write a custom direction decider for those occations.

Signature

A DirectionalDecider has the followign function signature:

(adapterIndex: Int,
 layoutManager: LoopingLayoutManager,
 itemCount: Int) -> Int

It takes in the target adapter index (Int) the layout manager (LoopingLayoutManager) that will be moving, and the item count (Int), which is the current number of items in the adapter. The it returns an int representing the direction the view should scroll in (either LoopingLayoutManager.TOWARDS_TOP_LEFT or LoopingLayoutManager.TOWARDS_BOTTOM_RIGHT).

Basics

How you want to write your directional decider is highly dependent on what you want to achieve. But there are a few recommendations that should work in most cases.

Use math

As opposed to when you're creating a ViewPicker when you're creating a directional decider you have access to the itemCount parameter. This should allow basically all calculations to be done efficiently with math.

Useful functions

  • layoutManager.topLeftIndex this tells you the adapter index of the view at the top/left edge of the layout.

  • layoutManager.bottomRightIndex this tells you the adapter index of the view at bottom/right edge of the layout.

    • layoutManager.convertAdapterDirToMovementDir(direction) converts an adapter direction (TOWARDS_HIGHER_INDICES or TOWARDS_LOWER_INDICES) to a movement direction (TOWARDS_TOP_LEFT or TOWARDS_BOTTOM_RIGHT). This can be useful when determining which direction to loop in.

    See directional conversion for more information.

Example: addViewsAtAnchorEdge

This example shows you just how simple a directional decider can be.

It is written in Kotlin with code comments explaining what is happening.

fun addViewsAtAnchorEdge(
        adapterIndex: Int,
        layoutManager: LoopingLayoutManager,
        itemCount: Int
): Int {
    // The LoopingLayoutManager.TOWARDS_LOWER_INDICES property describes the direction
    // where we move towards views with lower adapter indices (i.e state.itemCount-1 -> 0).
    // We then convert that to a movement direction, so that the layout manager knows
    // how to smooth scroll so that we move in that adapter direction.
    return layoutManager.convertAdapterDirToMovementDir(
        LoopingLayoutManager.TOWARDS_LOWER_INDICES)
}

See directional conversion for more information about converting between movement directions and adapter directions.

Clone this wiki locally