Analysis of scrollBy() and scrollTo() of View source code

scrollBy() source code:

/**
 * 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);
}

scrollTo() source code:

/**
 * 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();
        }
    }
}

Ok, let’s analyze the source code below:

First, a brief introduction:

scrollBy --- continue to move the content of the view on the existing basis

scrollTo---Move the content of a view to the specified position

Then, drill down to:

The scrollBy method actually calls the scrollTo() method. Add mScrollX to the first pass of scrollBy

Parameter x, add mScrollY to the second parameter of scrollBy, and then call scrollTo.

mScrollX and mScrollY are two variables defined in View, which respectively represent the content of View relative to View itself.

Offsets in the horizontal and vertical directions.

scrollTo method, first we look at this line of code

if(mScrollX != x || mScrollY != y)

We can see that if this judgment is met, the scrollTo method does nothing. why should there be

What about this judgment? The reason is: if the coordinates of the moving point this time are the same as last time, then there is no need to move.

look next,

int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;

This is to use two local variables to save the previous mScrollX and mScrollY, and then assign new values ​​to mScrollX and mScrollY. Let’s look again,

invalidateParentCaches();

This is used to indicate that this view's parent should clear its cache,

Look again,

onScrollChanged(mScrollX, mScrollY, oldX, oldY);

The onScrollChanged method is called, and onScrollChange is called back in the method, source code:

mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);

Finally executed,

postInvalidateOnAnimation();

This method will notify View to redraw, so enter draw()

We know that one step in draw() is: draw decorations, such as scroll bars.

Scrollbars is caused by scroll, so let's look at the specific implementation of this step:

public void onDrawForeground(Canvas canvas) {
    onDrawScrollIndicators(canvas);
    onDrawScrollBars(canvas);
    ...
}

onDrawScrollBars(canvas) draws the horizontal and vertical scrollBar respectively, and will eventually be called

invalidate method.

The source code of this method is as follows:

public void invalidate(Rect dirty) {
    final int scrollX = mScrollX;
    final int scrollY = mScrollY;
    invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
            dirty.right - scrollX, dirty.bottom - scrollY, true, false);
}

Let's follow up and see,

void invalidateInternal(int l, int t, int r, int b, 
        boolean invalidateCache, boolean fullInvalidate) {
    ...
    final Rect damage = ai.mTmpInvalRect;
    damage.set(l, t, r, b);
    p.invalidateChild(this, damage);
    ...
}

We found that all child controls are redrawn here. When redrawing, the left and top of the Rect minus mScrollX, and the right and bottom minus mScrollY.

So we can also understand why when scrollX is positive, move to the left.

Guess you like

Origin blog.csdn.net/zdj_Develop/article/details/119444301