Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How AppBarLayout.ScrollingViewBehavior's math works?

I would watch the math flow of the offsetChildAsNeeded method in AppBarLayout.ScrollingViewBehavior on running scrolling changes.

As it is private method and private is mOffsetDelta, how can programmatically monitor them?

(It is not clear how the method uses offset too.)

private void offsetChildAsNeeded(CoordinatorLayout parent, View child, View dependency) {
    final CoordinatorLayout.Behavior behavior =
                ((CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
    if (behavior instanceof Behavior) {
        // Offset the child, pinning it to the bottom the header-dependency, maintaining
        // any vertical gap, and overlap
        final Behavior ablBehavior = (Behavior) behavior;
        final int offset = ablBehavior.getTopBottomOffsetForScrollingSibling();
        ViewCompat.offsetTopAndBottom(child, (dependency.getBottom() - child.getTop())
                + ablBehavior.mOffsetDelta
                + getVerticalLayoutGap()
                - getOverlapPixelsForOffset(dependency));
        }
    }

NOTE: are welcome and could be accepted replies also the ones that explain details on math's logic of getTopBottomOffsetForScrollingSibling(), of (dependency.getBottom() - child.getTop()), and on the content of mOffsetDelta

like image 250
GPack Avatar asked Oct 13 '16 13:10

GPack


People also ask

How do I use AppBarLayout?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.

What is AppBarLayout?

AppBarLayout is a vertical LinearLayout which implements many of the features of material designs app bar concept, namely scrolling gestures. Children should provide their desired scrolling behavior through AppBarLayout.

How do I use CoordinatorLayout?

By specifying Behaviors for child views of a CoordinatorLayout you can provide many different interactions within a single parent and those views can also interact with one another. View classes can specify a default behavior when used as a child of a CoordinatorLayout by implementing the AttachedBehavior interface.

What is a coordinator layout?

The Coordinator Layout is described as a “a super-powered FrameLayout” according to the docs. It is used to facilitate how views within your layout interact with each other. This is done by creating or assigning specific Behaviors to these views.


1 Answers

You could reverse-engineer this code, but in the end it's academic because us mere mortal (i.e. non-Google) programmers can't access the values and methods shown here. I guess they figure that the less of their library we can actually use, the fewer bug reports we'll file. Sigh.

But here's a brief explanation:

First of all that code line

    final int offset = ablBehavior.getTopBottomOffsetForScrollingSibling();

appears to be a vestigial remnant of an earlier revision, since offset is never actually used. The newer expression must be a little more accurate in more cases.

ViewCompat.offsetTopAndBottom() is not a set (absolute) operation, but an additive (relative) operation. So let's assume the normal logic and consider that this behavior essentially puts the scrolling view directly underneath the app bar layout. Typically, then, the bottom of the app bar and the top of the scrolling view have the same value. Since the app bar layout (dependency) has changed and the scrolling view (child) hasn't (yet), then

    dependency.getBottom() - child.getTop()

is the relative amount that the child's vertical offset needs to be adjusted.

If my reading of the code is correct, that mOffsetDelta in the app bar layout's behavior is only non-zero in the case that the app bar layout has an offset interpolater. Typically the app bar itself won't move in a parallax fashion, so mOffsetDelta is zero for practically all the cases we care about. getVerticalLayoutGap and getOverlapPixelsForOffset deal with layout params like overlapTop.

But it turns out that you can do most of this without those edge cases in your own behavior subclass just by doing this:

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
                                          View dependency) {
        // get the bottom of the app bar layout
        int bottom = dependency.getBottom();

        // position the top of the scrolling view there
        return setTopAndBottomOffset(bottom);
    }

I find it's a little easier to work with absolute offsets rather than relative offsets. So implementing a scrolling behavior is mostly a matter of determining where the dependent view is and where the scrolling view needs to be based on that.

like image 182
kris larson Avatar answered Oct 28 '22 09:10

kris larson