谷歌新推出的support design包真的是个不错的东西,它能让大家十分轻松的实现MD风格的APP,具体关于这个包的使用,很多大牛都有写过文章,我这里推荐一篇:http://blog.csdn.net/eclipsexys/article/details/46349721
这个包中我觉得最关键的一个组件就是CoordinatorLayout,而CoordinatorLayout要配合behaviour来使用才会有好的效果。behaviour具体的作用就是用来控制CoordinatorLayout中一个子控件的行为,比如一个RecyclerView底部有一个FloatingActionButton,当滑动的时候,这个FloatingActionButton要适当的出现和消失,这就要靠behaviour来控制了。下面是谷歌官方的文档,大家可以参考一下,其实还挺简单的,对照着英文应该都能看懂。
https://developer.android.com/reference/android/support/design/widget/CoordinatorLayout.Behavior.html
下面我就上一个我自定义的behaviour,是关于前面提到的FloatingActionButton的出现和消失的。具体使用方法就是在XML中定义。
<android.support.design.widget.FloatingActionButton
android:id="@+id/FAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
app:borderWidth="0dp"
app:layout_anchor="@id/main_content"
app:layout_anchorGravity="bottom|right"
app:layout_scrollFlags="scroll|enterAlways"
app:layout_behavior="com.example.administrator.behaviourtest.FloatingActionButtonBehaviour"/>
最后一行的
app:layout_behavior="com.example.administrator.behaviourtest.FloatingActionButtonBehaviour"
就是具体的代码了。
下面是JAVA代码:
package com.example.administrator.behaviourtest;
import android.animation.Animator;
import android.content.Context;
import android.os.Build;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
/**
* Created by Administrator on 2015/8/21.
*/
public class FloatingActionButtonBehaviour extends CoordinatorLayout.Behavior<View> {
private static final android.view.animation.Interpolator INTERPOLATOR =
new FastOutSlowInInterpolator();
private boolean mIsAnimatingOut = false;
private int mDySinceDirectionChange;
public FloatingActionButtonBehaviour(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) != 0;
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
if (dy > 0 && mDySinceDirectionChange < 0
|| dy < 0 && mDySinceDirectionChange > 0) {
// We detected a direction change- cancel existing animations and reset our cumulative delta Y
child.animate().cancel();
mDySinceDirectionChange = 0;
}
mDySinceDirectionChange += dy;
System.out.println("onNestedPreScroll");
if (mDySinceDirectionChange > child.getHeight() && child.getVisibility() == View.VISIBLE) {
animateOut(child);
} else if (mDySinceDirectionChange < 0 && child.getVisibility() == View.GONE) {
animateIn(child);
}
}
// Same animation that FloatingActionButton.Behavior uses to
// hide the FAB when the AppBarLayout exits
private void animateOut(final View button) {
if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).scaleX(0.0F).scaleY(0.0F).alpha(0.0F)
.setInterpolator(INTERPOLATOR).withLayer()
.setListener(new ViewPropertyAnimatorListener() {
public void onAnimationStart(View view) {
FloatingActionButtonBehaviour.this.mIsAnimatingOut = true;
}
public void onAnimationCancel(View view) {
FloatingActionButtonBehaviour.this.mIsAnimatingOut = false;
}
public void onAnimationEnd(View view) {
FloatingActionButtonBehaviour.this.mIsAnimatingOut = false;
view.setVisibility(View.GONE);
}
}).start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out);
anim.setInterpolator(INTERPOLATOR);
anim.setDuration(200L);
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
FloatingActionButtonBehaviour.this.mIsAnimatingOut = true;
}
public void onAnimationEnd(Animation animation) {
FloatingActionButtonBehaviour.this.mIsAnimatingOut = false;
button.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(final Animation animation) {
}
});
button.startAnimation(anim);
}
}
// Same animation that FloatingActionButton.Behavior
// uses to show the FAB when the AppBarLayout enters
private void animateIn(View button) {
button.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= 14) {
ViewCompat.animate(button).scaleX(1.0F).scaleY(1.0F).alpha(1.0F)
.setInterpolator(INTERPOLATOR).withLayer().setListener(null)
.start();
} else {
Animation anim = AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in);
anim.setDuration(200L);
anim.setInterpolator(INTERPOLATOR);
button.startAnimation(anim);
}
}
}
其中onStartNestedScroll是用来告诉behaviour要检测哪个方向的滑动,这里我传的是竖直方向的。
最重要的一个方法onNestedPreScroll,是用来控制滑动之后的事件的,这里我就简单的写了一下,判断y轴滑动的距离来控制button的出现和消失。
大家可以照着写一下,其实还是很简单的,但是可以实现很多不同的功能。