上次讲了自定义Behavior的child监听dependency的状态变化,这次就接着说child监听实现了NestedScrollingChild的接口的dependency的滑动状态。 需要重写两个方法
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target,
int nestedScrollAxes) {
return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target,
int dxConsumed,
int dyConsumed,
int dxUnconsumed,
int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
先来看onStartNestedScroll,这个方法表明我们在这次滑动中关心的方向,如果是X轴,则return nestedScrollAxes == ViewCompat.SCROLL_AXIS_HORIZONTAL;若是关心Y轴方向的滑动,return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL即可。
onNestedScroll这个方法才是我们关注的重点,coordinatorLayout这个参数就不说了,child是指设置了这个Behavior的coordinatorLayout的子View,target则是前面提到的实现了NestedScrollingChild的接口的dependency。dxConsumed、dyConsumed是指x、y轴方向上target消费的像素值,简单来说,就是滚动的距离,至于后面两个参数,百度了,也看了源码的注释,还是不太明白,翻译过来字面意思就是:不被目标自身的滚动操作所消耗的垂直、水平像素,而是用户要求的(本来以为是调用scrollto之类方法产生的,试过了发现不是)。
说完这么多屁话,看个例子 先上效果图 仔细看还是和之前的有点区别,在上滑和下滑时,隐藏显示FloatingActionButton和BottomBar。
XML
<android
.support.design.widget.CoordinatorLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent">
<android
.support.design.widget.AppBarLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:theme=
"@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation=
"0dp">
<TextView
android:layout_width=
"match_parent"
android:layout_height=
"50dp"
android:gravity=
"center"
android:text=
"topBar"
app:layout_scrollFlags=
"scroll|enterAlways" />
</android
.support.design.widget.AppBarLayout>
<android
.support.v4
.widget.NestedScrollView
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scrollbars=
"none"
app:behavior_overlapTop=
"30dp"
app:layout_behavior=
"@string/appbar_scrolling_view_behavior">
<include layout=
"@layout/layout_main" />
</android
.support.v4
.widget.NestedScrollView>
<TextView
android:layout_width=
"match_parent"
android:layout_height=
"50dp"
android:layout_gravity=
"bottom"
android:background=
"@color/colorPrimary"
android:gravity=
"center"
android:text=
"bottomBar"
app:layout_behavior=
".BottomScrollBehavior" />
<android
.support.design.widget.FloatingActionButton
android:layout_width=
"50dp"
android:layout_height=
"50dp"
android:layout_gravity=
"bottom|right"
android:layout_marginBottom=
"70dp"
android:layout_marginRight=
"20dp"
android:src=
"@mipmap/ic_launcher_round"
app:elevation=
"5dp"
app:layout_behavior=
".ScrollingBehavior" />
</android
.support.design.widget.CoordinatorLayout>
也和上一篇的相似,唯一的区别就是BottomBar和FloatingActionButton的Behavior换了 再看自定义的Behavior
public class ScrollingBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
private boolean isAnimator;
public ScrollingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean
onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target,
int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target,
int dxConsumed,
int dyConsumed,
int dxUnconsumed,
int dyUnconsumed) {
if ((dyConsumed >
0 || dyUnconsumed >
0) && !isAnimator && child.getVisibility() == View.VISIBLE) {
hideAnimator(child);
}
else if ((dyConsumed <
0 || dyUnconsumed <
0) && !isAnimator && child.getVisibility() != View.VISIBLE) {
showAnimator(child);
}
}
private void showAnimator(View view) {
view.setVisibility(View.VISIBLE);
ViewCompat.animate(view)
.scaleX(
1.0f)
.scaleY(
1.0f)
.alpha(
1.0f)
.setDuration(
800)
.setListener(
new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
isAnimator =
true;
}
@Override
public void onAnimationEnd(View view) {
isAnimator =
false;
}
@Override
public void onAnimationCancel(View view) {
isAnimator =
false;
}
})
.start();
}
private void hideAnimator(View view) {
ViewCompat.animate(view)
.scaleX(
0)
.scaleY(
0)
.alpha(
0)
.setDuration(
800)
.setListener(
new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
isAnimator =
true;
}
@Override
public void onAnimationEnd(View view) {
isAnimator =
false;
view.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationCancel(View view) {
isAnimator =
false;
}
})
.start();
}
}
public class BottomScrollBehavior extends CoordinatorLayout.Behavior<View> {
private boolean isAnimator;
public BottomScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean
onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target,
int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target,
int dxConsumed,
int dyConsumed,
int dxUnconsumed,
int dyUnconsumed) {
if ((dyConsumed >
0 || dyUnconsumed >
0) && !isAnimator && child.getTranslationY() ==
0) {
hideAnimator(child);
}
else if ((dyConsumed <
0 || dyUnconsumed <
0) && !isAnimator && child.getTranslationY() == child.getHeight()) {
showAnimator(child);
}
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
private void showAnimator(View view) {
ViewCompat.animate(view)
.translationY(
0)
.setDuration(
800)
.setListener(
new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
isAnimator =
true;
}
@Override
public void onAnimationEnd(View view) {
isAnimator =
false;
}
@Override
public void onAnimationCancel(View view) {
isAnimator =
false;
}
})
.start();
}
private void hideAnimator(View view) {
ViewCompat.animate(view)
.translationY(view.getHeight())
.setDuration(
800)
.setListener(
new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
isAnimator =
true;
}
@Override
public void onAnimationEnd(View view) {
isAnimator =
false;
}
@Override
public void onAnimationCancel(View view) {
isAnimator =
false;
}
})
.start();
}
}