Source code
package android.support.design.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.R;
import android.support.design.widget.CoordinatorLayout.DefaultBehavior;
import android.support.v4.os.ParcelableCompat;
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
import android.support.v4.view.OnApplyWindowInsetsListener;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.BaseSavedState;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@DefaultBehavior(Behavior.class)
public class AppBarLayout extends LinearLayout {
private static final int INVALID_SCROLL_RANGE = -1;
private static final int PENDING_ACTION_ANIMATE_ENABLED = 4;
private static final int PENDING_ACTION_COLLAPSED = 2;
private static final int PENDING_ACTION_EXPANDED = 1;
private static final int PENDING_ACTION_NONE = 0;
private int mDownPreScrollRange;
private int mDownScrollRange;
boolean mHaveChildWithInterpolator;
private WindowInsetsCompat mLastInsets;
private final List<OnOffsetChangedListener> mListeners;
private int mPendingAction;
private float mTargetElevation;
private int mTotalScrollRange;
public static class LayoutParams extends android.widget.LinearLayout.LayoutParams {
static final int FLAG_QUICK_RETURN = 5;
static final int FLAG_SNAP = 17;
public static final int SCROLL_FLAG_ENTER_ALWAYS = 4;
public static final int SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED = 8;
public static final int SCROLL_FLAG_EXIT_UNTIL_COLLAPSED = 2;
public static final int SCROLL_FLAG_SCROLL = 1;
public static final int SCROLL_FLAG_SNAP = 16;
int mScrollFlags = 1;
Interpolator mScrollInterpolator;
@Retention(RetentionPolicy.SOURCE)
public @interface ScrollFlags {
}
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.AppBarLayout_LayoutParams);
this.mScrollFlags = a.getInt(R.styleable.AppBarLayout_LayoutParams_layout_scrollFlags, 0);
if (a.hasValue(R.styleable.AppBarLayout_LayoutParams_layout_scrollInterpolator)) {
this.mScrollInterpolator = AnimationUtils.loadInterpolator(c, a.getResourceId(R.styleable.AppBarLayout_LayoutParams_layout_scrollInterpolator, 0));
}
a.recycle();
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(int width, int height, float weight) {
super(width, height, weight);
}
public LayoutParams(android.view.ViewGroup.LayoutParams p) {
super(p);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(android.widget.LinearLayout.LayoutParams source) {
super(source);
}
public LayoutParams(LayoutParams source) {
super(source);
this.mScrollFlags = source.mScrollFlags;
this.mScrollInterpolator = source.mScrollInterpolator;
}
public void setScrollFlags(int flags) {
this.mScrollFlags = flags;
}
public int getScrollFlags() {
return this.mScrollFlags;
}
public void setScrollInterpolator(Interpolator interpolator) {
this.mScrollInterpolator = interpolator;
}
public Interpolator getScrollInterpolator() {
return this.mScrollInterpolator;
}
}
public interface OnOffsetChangedListener {
void onOffsetChanged(AppBarLayout appBarLayout, int i);
}
public static class Behavior extends HeaderBehavior<AppBarLayout> {
private static final int INVALID_POSITION = -1;
private ValueAnimatorCompat mAnimator;
private WeakReference<View> mLastNestedScrollingChildRef;
private int mOffsetDelta;
private int mOffsetToChildIndexOnLayout = -1;
private boolean mOffsetToChildIndexOnLayoutIsMinHeight;
private float mOffsetToChildIndexOnLayoutPerc;
private DragCallback mOnDragCallback;
private boolean mSkipNestedPreScroll;
private boolean mWasFlung;
public static abstract class DragCallback {
public abstract boolean canDrag(@NonNull AppBarLayout appBarLayout);
}
protected static class SavedState extends BaseSavedState {
public static final Creator<SavedState> CREATOR = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
public SavedState createFromParcel(Parcel source, ClassLoader loader) {
return new SavedState(source, loader);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
});
boolean firstVisibileChildAtMinimumHeight;
float firstVisibileChildPercentageShown;
int firstVisibleChildIndex;
public SavedState(Parcel source, ClassLoader loader) {
super(source);
this.firstVisibleChildIndex = source.readInt();
this.firstVisibileChildPercentageShown = source.readFloat();
this.firstVisibileChildAtMinimumHeight = source.readByte() != (byte) 0;
}
public SavedState(Parcelable superState) {
super(superState);
}
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(this.firstVisibleChildIndex);
dest.writeFloat(this.firstVisibileChildPercentageShown);
dest.writeByte((byte) (this.firstVisibileChildAtMinimumHeight ? 1 : 0));
}
}
public /* bridge */ /* synthetic */ int getLeftAndRightOffset() {
return super.getLeftAndRightOffset();
}
public /* bridge */ /* synthetic */ int getTopAndBottomOffset() {
return super.getTopAndBottomOffset();
}
public /* bridge */ /* synthetic */ boolean setLeftAndRightOffset(int x0) {
return super.setLeftAndRightOffset(x0);
}
public /* bridge */ /* synthetic */ boolean setTopAndBottomOffset(int x0) {
return super.setTopAndBottomOffset(x0);
}
public Behavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
boolean started = (nestedScrollAxes & 2) != 0 && child.hasScrollableChildren() && parent.getHeight() - directTargetChild.getHeight() <= child.getHeight();
if (started && this.mAnimator != null) {
this.mAnimator.cancel();
}
this.mLastNestedScrollingChildRef = null;
return started;
}
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) {
if (dy != 0 && !this.mSkipNestedPreScroll) {
int min;
int max;
if (dy < 0) {
min = -child.getTotalScrollRange();
max = min + child.getDownNestedPreScrollRange();
} else {
min = -child.getUpNestedPreScrollRange();
max = 0;
}
consumed[1] = scroll(coordinatorLayout, child, dy, min, max);
}
}
public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
if (dyUnconsumed < 0) {
scroll(coordinatorLayout, child, dyUnconsumed, -child.getDownNestedScrollRange(), 0);
this.mSkipNestedPreScroll = true;
return;
}
this.mSkipNestedPreScroll = false;
}
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, View target) {
if (!this.mWasFlung) {
snapToChildIfNeeded(coordinatorLayout, abl);
}
this.mSkipNestedPreScroll = false;
this.mWasFlung = false;
this.mLastNestedScrollingChildRef = new WeakReference(target);
}
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
boolean flung = false;
if (!consumed) {
flung = fling(coordinatorLayout, child, -child.getTotalScrollRange(), 0, -velocityY);
} else if (velocityY < 0.0f) {
targetScroll = (-child.getTotalScrollRange()) + child.getDownNestedPreScrollRange();
if (getTopBottomOffsetForScrollingSibling() < targetScroll) {
animateOffsetTo(coordinatorLayout, child, targetScroll);
flung = true;
}
} else {
targetScroll = -child.getUpNestedPreScrollRange();
if (getTopBottomOffsetForScrollingSibling() > targetScroll) {
animateOffsetTo(coordinatorLayout, child, targetScroll);
flung = true;
}
}
this.mWasFlung = flung;
return flung;
}
public void setDragCallback(@Nullable DragCallback callback) {
this.mOnDragCallback = callback;
}
private void animateOffsetTo(final CoordinatorLayout coordinatorLayout, final AppBarLayout child, int offset) {
if (this.mAnimator == null) {
this.mAnimator = ViewUtils.createAnimator();
this.mAnimator.setInterpolator(AnimationUtils.DECELERATE_INTERPOLATOR);
this.mAnimator.setUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimatorCompat animator) {
Behavior.this.setHeaderTopBottomOffset(coordinatorLayout, child, animator.getAnimatedIntValue());
}
});
} else {
this.mAnimator.cancel();
}
this.mAnimator.setIntValues(getTopBottomOffsetForScrollingSibling(), offset);
this.mAnimator.start();
}
private View getChildOnOffset(AppBarLayout abl, int offset) {
int count = abl.getChildCount();
for (int i = 0; i < count; i++) {
View child = abl.getChildAt(i);
if (child.getTop() <= (-offset) && child.getBottom() >= (-offset)) {
return child;
}
}
return null;
}
private void snapToChildIfNeeded(CoordinatorLayout coordinatorLayout, AppBarLayout abl) {
int offset = getTopBottomOffsetForScrollingSibling();
View offsetChild = getChildOnOffset(abl, offset);
if (offsetChild != null && (((LayoutParams) offsetChild.getLayoutParams()).getScrollFlags() & 17) == 17) {
int childTop = -offsetChild.getTop();
int childBottom = -offsetChild.getBottom();
if (offset >= (childBottom + childTop) / 2) {
childBottom = childTop;
}
animateOffsetTo(coordinatorLayout, abl, childBottom);
}
}
public boolean onLayoutChild(CoordinatorLayout parent, AppBarLayout abl, int layoutDirection) {
boolean handled = super.onLayoutChild(parent, abl, layoutDirection);
int pendingAction = abl.getPendingAction();
int offset;
if (pendingAction != 0) {
boolean animate = (pendingAction & 4) != 0;
if ((pendingAction & 2) != 0) {
offset = -abl.getUpNestedPreScrollRange();
if (animate) {
animateOffsetTo(parent, abl, offset);
} else {
setHeaderTopBottomOffset(parent, abl, offset);
}
} else if ((pendingAction & 1) != 0) {
if (animate) {
animateOffsetTo(parent, abl, 0);
} else {
setHeaderTopBottomOffset(parent, abl, 0);
}
}
} else if (this.mOffsetToChildIndexOnLayout >= 0) {
View child = abl.getChildAt(this.mOffsetToChildIndexOnLayout);
offset = -child.getBottom();
if (this.mOffsetToChildIndexOnLayoutIsMinHeight) {
offset += ViewCompat.getMinimumHeight(child);
} else {
offset += Math.round(((float) child.getHeight()) * this.mOffsetToChildIndexOnLayoutPerc);
}
setTopAndBottomOffset(offset);
}
abl.resetPendingAction();
this.mOffsetToChildIndexOnLayout = -1;
dispatchOffsetUpdates(abl);
return handled;
}
boolean canDragView(AppBarLayout view) {
if (this.mOnDragCallback != null) {
return this.mOnDragCallback.canDrag(view);
}
if (this.mLastNestedScrollingChildRef == null) {
return true;
}
View scrollingView = (View) this.mLastNestedScrollingChildRef.get();
if (scrollingView == null || !scrollingView.isShown() || ViewCompat.canScrollVertically(scrollingView, -1)) {
return false;
}
return true;
}
int getMaxDragOffset(AppBarLayout view) {
return -view.getDownNestedScrollRange();
}
int getScrollRangeForDragFling(AppBarLayout view) {
return view.getTotalScrollRange();
}
int setHeaderTopBottomOffset(CoordinatorLayout coordinatorLayout, AppBarLayout header, int newOffset, int minOffset, int maxOffset) {
int curOffset = getTopBottomOffsetForScrollingSibling();
int consumed = 0;
if (minOffset != 0 && curOffset >= minOffset && curOffset <= maxOffset) {
newOffset = MathUtils.constrain(newOffset, minOffset, maxOffset);
AppBarLayout appBarLayout = header;
if (curOffset != newOffset) {
int interpolatedOffset;
if (appBarLayout.hasChildWithInterpolator()) {
interpolatedOffset = interpolateOffset(appBarLayout, newOffset);
} else {
interpolatedOffset = newOffset;
}
boolean offsetChanged = setTopAndBottomOffset(interpolatedOffset);
consumed = curOffset - newOffset;
this.mOffsetDelta = newOffset - interpolatedOffset;
if (!offsetChanged && appBarLayout.hasChildWithInterpolator()) {
coordinatorLayout.dispatchDependentViewsChanged(appBarLayout);
}
dispatchOffsetUpdates(appBarLayout);
}
}
return consumed;
}
private void dispatchOffsetUpdates(AppBarLayout layout) {
List<OnOffsetChangedListener> listeners = layout.mListeners;
int z = listeners.size();
for (int i = 0; i < z; i++) {
OnOffsetChangedListener listener = (OnOffsetChangedListener) listeners.get(i);
if (listener != null) {
listener.onOffsetChanged(layout, getTopAndBottomOffset());
}
}
}
private int interpolateOffset(AppBarLayout layout, int offset) {
int absOffset = Math.abs(offset);
int i = 0;
int z = layout.getChildCount();
while (i < z) {
View child = layout.getChildAt(i);
LayoutParams childLp = (LayoutParams) child.getLayoutParams();
Interpolator interpolator = childLp.getScrollInterpolator();
if (absOffset < child.getTop() || absOffset > child.getBottom()) {
i++;
} else if (interpolator == null) {
return offset;
} else {
int childScrollableHeight = 0;
int flags = childLp.getScrollFlags();
if ((flags & 1) != 0) {
childScrollableHeight = 0 + ((child.getHeight() + childLp.topMargin) + childLp.bottomMargin);
if ((flags & 2) != 0) {
childScrollableHeight -= ViewCompat.getMinimumHeight(child);
}
}
if (ViewCompat.getFitsSystemWindows(child)) {
childScrollableHeight -= layout.getTopInset();
}
if (childScrollableHeight <= 0) {
return offset;
}
return Integer.signum(offset) * (child.getTop() + Math.round(((float) childScrollableHeight) * interpolator.getInterpolation(((float) (absOffset - child.getTop())) / ((float) childScrollableHeight))));
}
}
return offset;
}
int getTopBottomOffsetForScrollingSibling() {
return getTopAndBottomOffset() + this.mOffsetDelta;
}
public Parcelable onSaveInstanceState(CoordinatorLayout parent, AppBarLayout appBarLayout) {
Parcelable superState = super.onSaveInstanceState(parent, appBarLayout);
int offset = getTopAndBottomOffset();
int i = 0;
int count = appBarLayout.getChildCount();
while (i < count) {
View child = appBarLayout.getChildAt(i);
int visBottom = child.getBottom() + offset;
if (child.getTop() + offset > 0 || visBottom < 0) {
i++;
} else {
SavedState ss = new SavedState(superState);
ss.firstVisibleChildIndex = i;
ss.firstVisibileChildAtMinimumHeight = visBottom == ViewCompat.getMinimumHeight(child);
ss.firstVisibileChildPercentageShown = ((float) visBottom) / ((float) child.getHeight());
return ss;
}
}
return superState;
}
public void onRestoreInstanceState(CoordinatorLayout parent, AppBarLayout appBarLayout, Parcelable state) {
if (state instanceof SavedState) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(parent, appBarLayout, ss.getSuperState());
this.mOffsetToChildIndexOnLayout = ss.firstVisibleChildIndex;
this.mOffsetToChildIndexOnLayoutPerc = ss.firstVisibileChildPercentageShown;
this.mOffsetToChildIndexOnLayoutIsMinHeight = ss.firstVisibileChildAtMinimumHeight;
return;
}
super.onRestoreInstanceState(parent, appBarLayout, state);
this.mOffsetToChildIndexOnLayout = -1;
}
}
public static class ScrollingViewBehavior extends HeaderScrollingViewBehavior {
private int mOverlayTop;
public /* bridge */ /* synthetic */ int getLeftAndRightOffset() {
return super.getLeftAndRightOffset();
}
public /* bridge */ /* synthetic */ int getTopAndBottomOffset() {
return super.getTopAndBottomOffset();
}
public /* bridge */ /* synthetic */ boolean onMeasureChild(CoordinatorLayout x0, View x1, int x2, int x3, int x4, int x5) {
return super.onMeasureChild(x0, x1, x2, x3, x4, x5);
}
public /* bridge */ /* synthetic */ boolean setLeftAndRightOffset(int x0) {
return super.setLeftAndRightOffset(x0);
}
public /* bridge */ /* synthetic */ boolean setTopAndBottomOffset(int x0) {
return super.setTopAndBottomOffset(x0);
}
public ScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrollingViewBehavior_Params);
this.mOverlayTop = a.getDimensionPixelSize(R.styleable.ScrollingViewBehavior_Params_behavior_overlapTop, 0);
a.recycle();
}
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof AppBarLayout;
}
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
super.onLayoutChild(parent, child, layoutDirection);
List<View> dependencies = parent.getDependencies(child);
int i = 0;
int z = dependencies.size();
while (i < z && !updateOffset(parent, child, (View) dependencies.get(i))) {
i++;
}
return true;
}
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
updateOffset(parent, child, dependency);
return false;
}
private boolean updateOffset(CoordinatorLayout parent, View child, View dependency) {
android.support.design.widget.CoordinatorLayout.Behavior behavior = ((android.support.design.widget.CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
if (!(behavior instanceof Behavior)) {
return false;
}
int offset = ((Behavior) behavior).getTopBottomOffsetForScrollingSibling();
setTopAndBottomOffset((dependency.getHeight() + offset) - getOverlapForOffset(dependency, offset));
return true;
}
private int getOverlapForOffset(View dependency, int offset) {
if (this.mOverlayTop != 0 && (dependency instanceof AppBarLayout)) {
AppBarLayout abl = (AppBarLayout) dependency;
int totalScrollRange = abl.getTotalScrollRange();
int preScrollDown = abl.getDownNestedPreScrollRange();
if (preScrollDown != 0 && totalScrollRange + offset <= preScrollDown) {
return 0;
}
int availScrollRange = totalScrollRange - preScrollDown;
if (availScrollRange != 0) {
return MathUtils.constrain(Math.round((1.0f + (((float) offset) / ((float) availScrollRange))) * ((float) this.mOverlayTop)), 0, this.mOverlayTop);
}
}
return this.mOverlayTop;
}
public void setOverlayTop(int overlayTop) {
this.mOverlayTop = overlayTop;
}
public int getOverlayTop() {
return this.mOverlayTop;
}
View findFirstDependency(List<View> views) {
int z = views.size();
for (int i = 0; i < z; i++) {
View view = (View) views.get(i);
if (view instanceof AppBarLayout) {
return view;
}
}
return null;
}
int getScrollRange(View v) {
if (v instanceof AppBarLayout) {
return ((AppBarLayout) v).getTotalScrollRange();
}
return super.getScrollRange(v);
}
}
public AppBarLayout(Context context) {
this(context, null);
}
public AppBarLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.mTotalScrollRange = -1;
this.mDownPreScrollRange = -1;
this.mDownScrollRange = -1;
this.mPendingAction = 0;
setOrientation(1);
ThemeUtils.checkAppCompatTheme(context);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppBarLayout, 0, R.style.Widget_Design_AppBarLayout);
this.mTargetElevation = (float) a.getDimensionPixelSize(R.styleable.AppBarLayout_elevation, 0);
setBackgroundDrawable(a.getDrawable(R.styleable.AppBarLayout_android_background));
if (a.hasValue(R.styleable.AppBarLayout_expanded)) {
setExpanded(a.getBoolean(R.styleable.AppBarLayout_expanded, false));
}
a.recycle();
ViewUtils.setBoundsViewOutlineProvider(this);
this.mListeners = new ArrayList();
ViewCompat.setElevation(this, this.mTargetElevation);
ViewCompat.setOnApplyWindowInsetsListener(this, new OnApplyWindowInsetsListener() {
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
AppBarLayout.this.setWindowInsets(insets);
return insets.consumeSystemWindowInsets();
}
});
}
public void addOnOffsetChangedListener(OnOffsetChangedListener listener) {
if (listener != null && !this.mListeners.contains(listener)) {
this.mListeners.add(listener);
}
}
public void removeOnOffsetChangedListener(OnOffsetChangedListener listener) {
if (listener != null) {
this.mListeners.remove(listener);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
invalidateScrollRanges();
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
invalidateScrollRanges();
this.mHaveChildWithInterpolator = false;
int z = getChildCount();
for (int i = 0; i < z; i++) {
if (((LayoutParams) getChildAt(i).getLayoutParams()).getScrollInterpolator() != null) {
this.mHaveChildWithInterpolator = true;
return;
}
}
}
private void invalidateScrollRanges() {
this.mTotalScrollRange = -1;
this.mDownPreScrollRange = -1;
this.mDownScrollRange = -1;
}
public void setOrientation(int orientation) {
if (orientation != 1) {
throw new IllegalArgumentException("AppBarLayout is always vertical and does not support horizontal orientation");
}
super.setOrientation(orientation);
}
public void setExpanded(boolean expanded) {
setExpanded(expanded, ViewCompat.isLaidOut(this));
}
public void setExpanded(boolean expanded, boolean animate) {
this.mPendingAction = (animate ? 4 : 0) | (expanded ? 1 : 2);
requestLayout();
}
protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(-1, -2);
}
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
protected LayoutParams generateLayoutParams(android.view.ViewGroup.LayoutParams p) {
if (p instanceof android.widget.LinearLayout.LayoutParams) {
return new LayoutParams((android.widget.LinearLayout.LayoutParams) p);
}
if (p instanceof MarginLayoutParams) {
return new LayoutParams((MarginLayoutParams) p);
}
return new LayoutParams(p);
}
private boolean hasChildWithInterpolator() {
return this.mHaveChildWithInterpolator;
}
public final int getTotalScrollRange() {
if (this.mTotalScrollRange != -1) {
return this.mTotalScrollRange;
}
int range = 0;
int z = getChildCount();
for (int i = 0; i < z; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childHeight = child.getMeasuredHeight();
int flags = lp.mScrollFlags;
if ((flags & 1) == 0) {
break;
}
range += (lp.topMargin + childHeight) + lp.bottomMargin;
if ((flags & 2) != 0) {
range -= ViewCompat.getMinimumHeight(child);
break;
}
}
int max = Math.max(0, range - getTopInset());
this.mTotalScrollRange = max;
return max;
}
private boolean hasScrollableChildren() {
return getTotalScrollRange() != 0;
}
private int getUpNestedPreScrollRange() {
return getTotalScrollRange();
}
private int getDownNestedPreScrollRange() {
if (this.mDownPreScrollRange != -1) {
return this.mDownPreScrollRange;
}
int range = 0;
for (int i = getChildCount() - 1; i >= 0; i--) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childHeight = child.getMeasuredHeight();
int flags = lp.mScrollFlags;
if ((flags & 5) == 5) {
range += lp.topMargin + lp.bottomMargin;
if ((flags & 8) != 0) {
range += ViewCompat.getMinimumHeight(child);
} else {
range += childHeight;
}
} else if (range > 0) {
break;
}
}
this.mDownPreScrollRange = range;
return range;
}
private int getDownNestedScrollRange() {
if (this.mDownScrollRange != -1) {
return this.mDownScrollRange;
}
int range = 0;
int z = getChildCount();
for (int i = 0; i < z; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childHeight = child.getMeasuredHeight() + (lp.topMargin + lp.bottomMargin);
int flags = lp.mScrollFlags;
if ((flags & 1) == 0) {
break;
}
range += childHeight;
if ((flags & 2) != 0) {
range -= ViewCompat.getMinimumHeight(child) + getTopInset();
break;
}
}
int max = Math.max(0, range);
this.mDownScrollRange = max;
return max;
}
final int getMinimumHeightForVisibleOverlappingContent() {
int topInset;
if (this.mLastInsets != null) {
topInset = this.mLastInsets.getSystemWindowInsetTop();
} else {
topInset = 0;
}
int minHeight = ViewCompat.getMinimumHeight(this);
if (minHeight != 0) {
return (minHeight * 2) + topInset;
}
int childCount = getChildCount();
if (childCount >= 1) {
return (ViewCompat.getMinimumHeight(getChildAt(childCount - 1)) * 2) + topInset;
}
return 0;
}
public void setTargetElevation(float elevation) {
this.mTargetElevation = elevation;
}
public float getTargetElevation() {
return this.mTargetElevation;
}
private int getPendingAction() {
return this.mPendingAction;
}
private void resetPendingAction() {
this.mPendingAction = 0;
}
private int getTopInset() {
return this.mLastInsets != null ? this.mLastInsets.getSystemWindowInsetTop() : 0;
}
private void setWindowInsets(WindowInsetsCompat insets) {
this.mTotalScrollRange = -1;
this.mLastInsets = insets;
int i = 0;
int z = getChildCount();
while (i < z) {
insets = ViewCompat.dispatchApplyWindowInsets(getChildAt(i), insets);
if (!insets.isConsumed()) {
i++;
} else {
return;
}
}
}
}