/** * Interaction behavior plugin for child views of {@link CoordinatorLayout}. * * <p>A Behavior implements one or more interactions that a user can take on a child view. * These interactions may include drags, swipes, flings, or any other gestures.</p> * * @param <V> The View type that this Behavior operates on */ publicstaticabstractclassBehavior<VextendsView> {
/** * Behavior designed for use with {@link FloatingActionButton} instances. It's main function * is to move {@link FloatingActionButton} views so that any displayed {@link Snackbar}s do * not cover them. */ publicstaticclassBehaviorextendsCoordinatorLayout.Behavior<FloatingActionButton> { // We only support the FAB <> Snackbar shift movement on Honeycomb and above. This is // because we can use view translation properties which greatly simplifies the code. privatestaticfinalboolean SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11;
@Override publicbooleanlayoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency){ // We're dependent on all SnackbarLayouts (if enabled) return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout; } ... ... @Override publicbooleanonDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency){ if (dependency instanceof Snackbar.SnackbarLayout) { updateFabTranslationForSnackbar(parent, child, dependency); } elseif (dependency instanceof AppBarLayout) { // If we're depending on an AppBarLayout we will show/hide it automatically // if the FAB is anchored to the AppBarLayout updateFabVisibility(parent, (AppBarLayout) dependency, child); } returnfalse; }
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param directTargetChild the child view of the CoordinatorLayout that either is or * contains the target of the nested scroll operation * @param target the descendant view of the CoordinatorLayout initiating the nested scroll * @param nestedScrollAxes the axes that this nested scroll applies to. See * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, * {@link ViewCompat#SCROLL_AXIS_VERTICAL} 滑动时是横轴和纵轴 * @returntrueif the Behavior wishes to accept this nested scroll * * @see NestedScrollingParent#onStartNestedScroll(View, View, int) */ publicbooleanonStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes){ returnfalse; }
onNestedPreScroll
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param target the descendant view of the CoordinatorLayout performing the nested scroll * @param dx the raw horizontal number of pixels that the user attempted to scroll * @param dy the raw vertical number of pixels that the user attempted to scroll * @param consumed out parameter. consumed[0] should be set to the distance of dx that * was consumed, consumed[1] should be set to the distance of dy that * was consumed * * @see NestedScrollingParent#onNestedPreScroll(View, int, int, int[]) */ publicvoidonNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed){ // Do nothing }
onNestedFling
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param target the descendant view of the CoordinatorLayout performing the nested scroll * @param velocityX horizontal velocity of the attempted fling * @param velocityY vertical velocity of the attempted fling * @param consumed trueif the nested child view consumed the fling * @returntrueif the Behavior consumed the fling * * @see NestedScrollingParent#onNestedFling(View, float, float, boolean) */ publicbooleanonNestedFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, float velocityY, boolean consumed){ returnfalse; }
onNestedScroll
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param target the descendant view of the CoordinatorLayout performing the nested scroll * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation * @param dyConsumed vertical pixels consumed by the target's own scrolling operation * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling * operation, but requested by the user * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation, * but requested by the user * * @see NestedScrollingParent#onNestedScroll(View, int, int, int, int) */ publicvoidonNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed){ // Do nothing }
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB child.hide(); } elseif (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB child.show(); } } }
//初始条件 @Override publicbooleanonStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View directTargetChild, final View target, finalint nestedScrollAxes){ //垂直滚动 return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); }
@Override publicvoidonNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child, final View target, finalint dxConsumed, finalint dyConsumed, finalint dxUnconsumed, finalint dyUnconsumed){ super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) { // User scrolled down and the FAB is currently visible -> hide the FAB animateOut(child); } elseif (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) { // User scrolled up and the FAB is currently not visible -> show the FAB animateIn(child); } }
// Same animation that FloatingActionButton.Behavior uses to hide the FAB when the AppBarLayout exits privatevoidanimateOut(final FloatingActionButton button){ if (Build.VERSION.SDK_INT >= 14) { //withLayer()使动画中的某些操作变得更顺畅,加速渲染,API 14以后 ViewCompat.animate(button).translationY(button.getHeight() + getMarginBottom(button)).setInterpolator(INTERPOLATOR).withLayer() .setListener(new ViewPropertyAnimatorListener() { publicvoidonAnimationStart(View view){ ScrollAwareFABBehavior.this.mIsAnimatingOut = true; }
// Same animation that FloatingActionButton.Behavior uses to show the FAB when the AppBarLayout enters privatevoidanimateIn(FloatingActionButton button){ button.setVisibility(View.VISIBLE); if (Build.VERSION.SDK_INT >= 14) { ViewCompat.animate(button).translationY(0) .setInterpolator(INTERPOLATOR).withLayer().setListener(null) .start(); } else {
} }
privateintgetMarginBottom(View v){ int marginBottom = 0; final ViewGroup.LayoutParams layoutParams = v.getLayoutParams(); if (layoutParams instanceof ViewGroup.MarginLayoutParams) { marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin; } return marginBottom; }