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
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With