Material Design 交互设计在Android上的应用,Design Support Library 是在2015年
Google官方发布的一个全新兼容函数库,它使得开发这可以在Android2.1(API
7)及以上的设备中实现交互设计的效果。这个函数库提供了一些了的控件,主要包括:Snackbar
、NavigationView、FloatingActionButton、TextInputLayout、TabLayout、CollapsingToolbarLayout、AppBarLayout、CoordinatorLayout
Android UI Material Design交互设计(一)–BottomNavigationView底部菜单
Android UI Material Design交互设计(二)–Toolbar的基本使用与样式修改
Android UI Material Design交互设计(三)–SnackBar 详解
Android UI Material Design交互设计(四)–AppBarLayout 与Toolbar结合
Android UI Material Design交互设计(五)–CollapsingToolbarLayout 折叠布局
在使用Design Support Library之前,首先需要添加如下依赖
implementation 'com.android.support:design:28.0.0'
惯例先上效果图: 看中间的浮动按钮
怎么实现呢?
第一步:布局中的根布局为CoordinatorLayout
第二步:给listview 或者 NestedScrollView 等滑动的控件或者其父控件加上
app:layout_behavior="@string/appbar_scrolling_view_behavior"属性,让
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_overlapTop="30dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
。。。。。。
第三步:给FloatingActionButton浮动按钮添加自定义Behavior
app:layout_behavior=“com.goodboy.mile.Behavior.ScaleBehavior”
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:id="@+id/float_action_button"
android:layout_gravity="center"
app:srcCompat="@android:drawable/ic_dialog_email"
app:layout_behavior="com.goodboy.mile.Behavior.ScaleBehavior"/>
ScaleBehavior是自定义Behavior,继承自CoordinatorLayout.Behavior。
CoordinatorLayout的强大就源于Behavior,Behavior可以让CoordinatorLayout与其子控件实现各种炫酷的交互效果。下面开始撸代码,看看怎么实现自定义Behavior。
代码如下:
public class ScaleBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {
private FastOutLinearInInterpolator mFastOutLinearInInterpolator = new FastOutLinearInInterpolator();
private LinearOutSlowInInterpolator mLinearOutSlowInInterpolator = new LinearOutSlowInInterpolator();
public ScaleBehavior() {
}
public ScaleBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
private boolean isRunning;
//重写嵌套滑动开始
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
//重写嵌套滑动进行中 来监听CoordinatorLayout子view的滑动事件,我们可以在这里判断浮动按钮的消失与出现
@Override
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
Log.d("ScaleBehavior","dyConsumed:"+dyConsumed);
if (dyConsumed > 0 && !isRunning && child.getVisibility() == View.VISIBLE){//向下滑动,缩放隐藏控件
scaleHide(child);
}else if (dyConsumed < 0 && !isRunning && child.getVisibility() == View.INVISIBLE){//向上滑动缩放显示控件
scaleShow(child);
}
}
//浮动按钮显示动画
private void scaleShow(V child) {
Log.d("ScaleBehavior","scale behavior scaleShow");
child.setVisibility(View.VISIBLE);
ViewCompat.animate(child)
.scaleX(1)
.scaleY(1)
.setDuration(500)
.setInterpolator(mLinearOutSlowInInterpolator)
.setListener(new ViewPropertyAnimatorListenerAdapter(){
@Override
public void onAnimationStart(View view) {
super.onAnimationStart(view);
isRunning = true;
}
@Override
public void onAnimationEnd(View view) {
super.onAnimationEnd(view);
isRunning = false;
}
@Override
public void onAnimationCancel(View view) {
super.onAnimationCancel(view);
isRunning = false;
}
});
}
//浮动按钮隐藏动画
private void scaleHide(final V child) {
Log.d("ScaleBehavior","scale behavior scaleHide");
ViewCompat.animate(child)
.scaleX(0)
.scaleY(0)
.setDuration(500)
.setInterpolator(mFastOutLinearInInterpolator)
.setListener(new ViewPropertyAnimatorListenerAdapter(){
@Override
public void onAnimationStart(View view) {
super.onAnimationStart(view);
isRunning = true;
}
@Override
public void onAnimationEnd(View view) {
super.onAnimationEnd(view);
isRunning = false;
child.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationCancel(View view) {
super.onAnimationCancel(view);
isRunning = false;
}
});
}
}
⚠️ 注意我们自定义Behavior时候注意重写的几个方法:
onStartNestedScroll() :嵌套滑动开始,开始滑动的时候调用一次,手松开的时候调用一次返回true代表获取滑动事件,其他的scroll事件就会被触发
onNestedScroll():嵌套滑动进行中
onNestedScrollAccepted():接受到触摸事件的时候调用
onStopNestedScroll():嵌套滑动结束
onNestedPreScroll():嵌套滑动前
onNestedFling() : Fling是“猛扔”的意思 就是快速滑动,手指已经离开屏幕来,但是还有惯性滑动的时候调用。
onNestedPreFling():要监听的子View快速滑动前调用
onInterceptTouchEvent():是否拦截触摸事件
onTouchEvent():处理触摸事件
layoutDependsOn:重写这个方法来确定依赖关系,上面例子的NestedScrollView与浮动按钮就是依赖关系,该方法返回为true就会调用onDependentViewChanged方法
onDependentViewChanged():当被依赖的View状态改变时回调
onDependentViewRemoved():当被依赖的View移除时回调
onLayoutChild:字面意思,绘制子布局时候调用
onMeasureChild():测量使用Behavior的View尺寸
⚠️我们可以通过重写以上方法来实现各种炫酷的交互特效。