快过年了,在这给大家拜个早年~~
工厂也没啥事做,也快放假了,这篇就提早发~~
前面几篇已经把主要的UI效果实现了,这篇我们说一下自定义Behavior。
我们先在acticity_main中添加一点东西:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@color/colorPrimary"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="35sp"
android:text="自定义Behavior"/>
</LinearLayout>
可以看到,添加了一个LinearLayout和一个TextView,需要注意的是,LInearLayout是CoordinatorLayout的直接子控件。
自定义Behavior,首先我们需要做的是继承CoordinatorLayout.Behavior。接着重写其中的两个方法,分别是 onStartNestedScroll 和 onNestedPreScroll。那么这两个方法具体是干什么用的呢。我们先来看一下具体的代码:
public class MyBottomBehavior extends CoordinatorLayout.Behavior {
private int totalY;
private int childHeight;
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
return (axes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
}
@Override
public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
if (totalY > 0 && dy < 0 || totalY < 0 && dy > 0){
totalY = 0;
child.animate().cancel();
return;
}
childHeight = child.getHeight();
totalY += dy;
if (child.getVisibility() == View.INVISIBLE && totalY < 0 ){
show(child);
}else if (child.getVisibility() == View.VISIBLE && totalY > childHeight){
hide(child);
Log.v("totalY",totalY+"");
}
}
private void show(final View child) {
ObjectAnimator animator = ObjectAnimator.ofFloat(child,"translationY",0);
animator.setDuration(200);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setVisibility(View.VISIBLE);
super.onAnimationEnd(animation);
}
});
animator.start();
}
private void hide(final View child) {
ObjectAnimator animator = ObjectAnimator.ofFloat(child,"translationY",child.getHeight());
animator.setDuration(200);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
child.setVisibility(View.INVISIBLE);
super.onAnimationEnd(animation);
}
});
animator.start();
}
}
我们先来看看上面说到的两个方法:
1.boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View directTargetChild, @NonNull View target, int axes, int type)
看到就蒙了,好多参数,别急,我们先说说这个方法的作用,这个方法返回的是boolean值,当返回值是false的时候就不会触发onNestedPreScroll,反之,当返回值是true时,onNestedPreScroll才会执行。那么,很明显,这个方法,我们可以用来判断滑动的方向,当滑动方向是竖直的时候,我们才返回true。再看代码中,这个方法只有一条语句 就是 return (axes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
这句代码的意思就是判断滑动方向是否是竖直方向。
2.onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type)
在这个方法中,child代表LinearLayout,dy表示当前竖直方向上的移动距离。需要注意的是。上面这两个方法,会在你滑动的时候不断调用。dy表示的并不是总的滑动距离,而是当前滑动的距离,所以我们需要一个totalY来记录,竖直方向的总滑动距离。注意,dy是有正负的,当我们向上滑(手指向上滑动)的时候dy是正值,反之,则是赋值。那么onNestedPreScroll这个方法中的第一个if判断的意思就很明显了,就是当用户切换方向的时候(用户本来是向上或向下滑动的,突然变了方向,变成向下或者向上滑动。)如果大家觉得难理解,那么,totalY是记录竖直方向滑动距离总数的。假如,我们现在向上滑动,此时dy和totalY都是大于0的(都是正数),突然,我们切换方向,向下滑动,此时totalY因为记录的是总距离,数值较大,并不会立马变成负数。但是dy记录的是一小段的距离,此时的dy是负数。那么,由此我们可以判断用户反方向滑动了。那么在这里,我们把totalY重置,并且把正在执行的动画取消掉。
剩下的,if和else if语句,则判断当前child的显示状态,以及当前的滑动距离(totalY)。来对child进行显示或者隐藏的操作。
3.这里我们只拿一个show方法来说。就是执行一段属性动画。需要注意的是,这里我们需要设置监听,在动画执行完毕的时候,设置child的Visibility。
到这,自定义的Behavior就定义好了。接着,我们要在string.xml中,定义字符串。如下:
<resources>
<string name="app_name">MaterialDesignDemo</string>
<string name="user_name">休言半纸无多重</string>
<string name="show">I wish you all I ever wanted for you, I wish you the best. 我希望你不负我的期望,愿你一切安好。</string>
<string name="my_bottom_behavior">android.lgt.materialdesigndemo.MyBottomBehavior</string>
</resources>
看最后一个字符串my_bottom_behavior ,有一点,后面需要关联对应的我们定义的Behavior类。
接着,我们在 activity_main 的LinearLayout中加上Behavior属性。如下:
<LinearLayout
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
app:layout_behavior="@string/my_bottom_behavior"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="35sp"
android:text="自定义Behavior"/>
</LinearLayout>
ok,这样,我们就完成了。接着我们来看看效果。
如上,第一张是我们打开显示的界面。第二张,是当我们向上滑动的时候LinearLayout就会隐藏,第三张,当我们向下滑动的时候LinearLayout就会显示出来。
到这,我们的自定义Behavior就搞定了。
本人菜鸟,不对之处,请各路大神指教。