How to use Android scroller

Time:2021-8-9

This example shares the usage of Android scroller for your reference. The specific contents are as follows

1. Scrollto and scrollby

The view class defines two methods for scrolling view content: scrollto and scrollby:


/**
 * Set the scrolled position of your view. This will cause a call to
 * {@link #onScrollChanged(int, int, int, int)} and the view will be
 * invalidated.
 * @param x the x position to scroll to
 * @param y the y position to scroll to
 */
public void scrollTo(int x, int y) {
    if (mScrollX != x || mScrollY != y) {
        int oldX = mScrollX;
        int oldY = mScrollY;
        mScrollX = x;
        mScrollY = y;
        invalidateParentCaches();
        onScrollChanged(mScrollX, mScrollY, oldX, oldY);
        if (!awakenScrollBars()) {
            postInvalidateOnAnimation();
        }
    }
}

/**
 * Move the scrolled position of your view. This will cause a call to
 * {@link #onScrollChanged(int, int, int, int)} and the view will be
 * invalidated.
 * @param x the amount of pixels to scroll by horizontally
 * @param y the amount of pixels to scroll by vertically
 */
public void scrollBy(int x, int y) {
    scrollTo(mScrollX + x, mScrollY + y);
}

You can see that the X and Y parameters passed in by scrollby are actually the increment of the scrolling distance in the X and Y directions. Finally, the scrollto method is called. The scrollto method performs some refresh and notification operations. The most important thing is to assign values to mscollx and mscolly.

In the draw method of view, we can see the following code:


int sx = 0;
int sy = 0;
if (!drawingWithRenderNode) {
    computeScroll();
    sx = mScrollX;
    sy = mScrollY;
}

...

if (offsetForScroll) {
    canvas.translate(mLeft - sx, mTop - sy);
}

In other words, mscrollx and mscrolly are finally used for content rendering, and neither mleft nor MTop itself has changed due to scrollto. Scrollto works on the contents of the view, not the view itself.

2、 computeScroll

In the excerpt of the draw method in the View above, we saw that the computeScroll method was invoked before the value of mScrollX and mScrollY was selected. The computescroll method is declared as follows:


/**
 * Called by a parent to request that a child update its values for mScrollX
 * and mScrollY if necessary. This will typically be done if the child is
 * animating a scroll using a {@link android.widget.Scroller Scroller}
 * object.
 */
public void computeScroll() {
}

According to the comments, the typical usage of computescroll is to use it in combination with scroller to realize the scrolling animation of content / byte points.

3. Use of scroller

In fact, the scroller does not directly operate the scrolling of the view, but calculates the distance in the current X and Y directions according to the settings. General usage steps of scroller:

1. When initializing the scroller, you can specify the interpolator. If not, the default viscousfluidinterpolator is used
2. Call the scroller #startscroll method to start continuously calculating the scrolling in the X and Y directions over a period of time
3. Notify view refresh
4. In view#computescroll, the real scrolling operation is realized through scrollto
5. Notify view refresh

Before scrolling is completed, 4 and 5 will continue to cycle until scroller. Computescrolloffset() returns false.

class ScrollableLinearLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
    private val scroller = Scroller(context, BounceInterpolator())

    override fun computeScroll() {
        if(scroller.computeScrollOffset()) {
            //Where the scrolling operation is really realized
            scrollTo(scroller.currX, scroller.currY)

            //Refresh
            invalidate()
        }
    }

    fun scroll() {
        //Call the scroller's startscroll
        if(scrollX == 0) {
            scroller.startScroll(scrollX, scrollY, /*dx*/ -500, /*dy*/ 0, /*duration*/ 300)
        } else {
            scroller.startScroll(scrollX, scrollY, 500, 0, 300)
        }

        //Refresh
        invalidate()
    }

}

XML layout:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".scroller.activity.ScrollerSampleActivity">

    <com.sahooz.customviewdemo.scroller.view.ScrollableLinearLayout
        android:id="@+id/sll"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:background="#FFAAAA">

        <Button
            android:id="@+id/btnScroll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Scroll" />

    </com.sahooz.customviewdemo.scroller.view.ScrollableLinearLayout>

</LinearLayout>

Activity


class ScrollerSampleActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_scroller_sample)

        val btnScroll = findViewById<Button>(R.id.btnScroll)
        btnScroll.setOnClickListener {
            findViewById<ScrollableLinearLayout>(R.id.sll).scroll()
        }
    }
}

Operation results:

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.