0
点赞
收藏
分享

微信扫一扫

Android Study Material Design 十三 之CoordinatorLayout交互动画


LZ-Says:相处之道,在于彼此真心相待。有人甘愿做傻子,只是懒得计较这些琐事~


前言

情不知何起,一往情深~

随着MaterialDesign深入学习,不知道小伙伴们有多少已经应用到项目中了呢?

今天,我们来说下有关CoordinatorLayout如何实现交互动画。

实现前,我们先来看一组动画,之后想想不经过CoordingatorLayout,我们该如何实现?

效果查看


Android Study Material Design 十三 之CoordinatorLayout交互动画_ide_02

实现方式一

基于上图,我们先来简单分析下,如果要我们实现,我们该如何实现呢?

1. RecycleView监听滑动事件;

2. 滑动事件中通过对用户滑动Y轴滑动偏移量进行动画开启和隐藏操作。

下面开始着手实现~

第一步: 放置布局

右下方按钮使用ImageButton实现,通过layer-list来实现高仿FloatingActionButton效果。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.materialdesignstudy.coordinatorlayout.CoordinatorLayoutActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/id_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="?attr/actionBarSize" />

<android.support.v7.widget.Toolbar
android:id="@+id/id_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />

<ImageButton
android:id="@+id/id_fab"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="16dp"
android:background="@drawable/fag_bg"
android:onClick="getUseBehavior"
android:src="@drawable/ic_love" />

</RelativeLayout>

layer-list文件如下:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!-- 首层 -->
<item>
<shape android:shape="oval">
<solid android:color="#FF00" />
</shape>
</item>

<!-- 下面阴影色 -->
<item android:bottom="2dp">
<shape android:shape="oval">
<solid android:color="#999" />
</shape>
</item>

</layer-list>

第二步: 定义接口,控制动画显示与隐藏

public interface HideScrollListener {

void onHide();

void onShow();

}

第三步: 定义滑动监听类

这块需要注意如下几点:

1. dy代表Y轴滑动偏移量,当dy值为正数时,代表向上滑动,反之则为向下滑动;

2. 由于onScrolled事件在用户滑动时进行触发,所以避免多次无效调用需要增加标识位。

具体代码如下:

public class FabScrollListener extends RecyclerView.OnScrollListener {

// 滑动偏移量小于20 不考虑
private static final int THRESHOLD = 20;

// 滑动累加
private int mDistance = 0;

private HideScrollListener mHideScrollListener;

// 是否可见
private boolean mIsVisible = true;

public FabScrollListener(HideScrollListener hideScrollListener) {
this.mHideScrollListener = hideScrollListener;
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// dy:Y轴方向滑动时偏移量
// dy 为正数时 代表向上滑动 反之 代表向下滑动
// 滑动偏移量大于设定值 并且 当前处于可见状态 隐藏
if (mDistance > THRESHOLD && mIsVisible) { // ToolBar 隐藏
mHideScrollListener.onHide();
mDistance = 0;
mIsVisible = false;
}
// 滑动偏移量小于-设定值 并且 当前处于不可见状态 显示
if (mDistance < -THRESHOLD && !mIsVisible) { // ToolBar显示
mHideScrollListener.onShow();
mDistance = 0;
mIsVisible = true;
}
if (mIsVisible && dy > 0 || (!mIsVisible && dy < 0)) {
mDistance += dy;
}
}
}

第四步: 实例化 展示效果

到此步,几乎属于很nice操作了,实现接口,重写方法,调用属性动画,一气呵成~

代码如下:

public class CoordinatorLayoutActivity extends AppCompatActivity implements HideScrollListener {

private Toolbar mToolbar;
private RecyclerView mRecyclerView;
private ImageButton mFab;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coordinator_layout);
initView();
}

private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.id_rv);
mFab = (ImageButton) findViewById(R.id.id_fab);
mToolbar = (Toolbar) findViewById(R.id.id_toolbar);
setSupportActionBar(mToolbar);
setTitle("HLQ-Blog");

mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.addOnScrollListener(new FabScrollListener(this));
List<String> sList = new ArrayList<>();
for (int i = 0; i < 50; i++) {
sList.add("Hi Every One " + i);
}
FabRecycleAdapter adapter = new FabRecycleAdapter(sList);
mRecyclerView.setAdapter(adapter);
}


@Override
public void onHide() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(30));
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mFab.getLayoutParams();
mFab.animate().translationY(mFab.getHeight() + params.bottomMargin)
.setInterpolator(new AccelerateInterpolator(3));
}

@Override
public void onShow() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
mFab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
}

public void getUseBehavior(View view) {
startActivity(new Intent(this, BehaviorActivity.class));
}

}

注:

由于我们这里使用的是属性动画,所以各位老铁应用的同时别忘记做兼容(属性动画)。

效果就不运行了,各位老帖运行吧,源码会在文末放出。

—————————–本小段为本文重点部分——————————-

CoordinatorLayout以及Behavior简述

CoordinatorLayout,遵循Material Design效果,隶属于Design包下,其主要作用为:

作为一个容器,与子View进行交互。通俗来讲就是,可以通过检测用户操作去实现不同酷炫效果。

CoordinatorLayout可与多种方式进行搭配,而今天,我们主要是通过和Behavior配合,实现文首效果。

那么Behavior又是什么鬼呢?

Behavior(行为),也就是说这里面封装好了一些用户常用行为,我们通过对用户某些行为(操作)进行相应的逻辑or效果控制即可。

下面我们基于上一个代码进行改造 。

实现方式二

第一步: 修改布局

1. 将RelativeLayout替换为CoordinatorLayout;

2. 将ImageButton替换为FloatingActionButton。

布局如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.materialdesignstudy.coordinatorlayout.behavior.BehaviorActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/id_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="?attr/actionBarSize" />

<android.support.v7.widget.Toolbar
android:id="@+id/id_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/id_fab"
android:layout_width="58dp"
android:layout_height="58dp"
android:layout_gravity="right|bottom"
android:layout_margin="16dp"
android:background="@drawable/fag_bg"
android:src="@drawable/ic_love"
app:layout_behavior="com.materialdesignstudy.coordinatorlayout.behavior.FabBehavior" />

</android.support.design.widget.CoordinatorLayout>

第二步: 定义Behavior

public class FabBehavior extends FloatingActionButton.Behavior {

private boolean visible = true;//是否可见

public FabBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
FloatingActionButton child, View directTargetChild, View target,
int nestedScrollAxes) {
// 当观察的View(RecyclerView)发生滑动的开始的时候回调的
// nestedScrollAxes:滑动关联轴, 我们现在只关心垂直的滑动。
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild,
target, nestedScrollAxes);
}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout,
FloatingActionButton child, View target, int dxConsumed,
int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed);
// 当观察的view滑动的时候回调的
//根据情况执行动画
if (dyConsumed > 0 && visible) {
//show
visible = false;
onHide(child);
} else if (dyConsumed < 0) {
//hide
visible = true;
onShow(child);
}
}

public void onHide(FloatingActionButton fab) {
ViewCompat.animate(fab).scaleX(0f).scaleY(0f).start();
}

public void onShow(FloatingActionButton fab) {
ViewCompat.animate(fab).scaleX(1f).scaleY(1f).start();
}

}

这里需要大家务必关注一点如下:

如果通过app:layout_behavior去引用我们自定义的behavior,则自定义behavior里面务必添加构造,如下:

public FabBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}

不然会抛出“Could not inflate Behavior subclass”异常~!!!

第三步: 精简Activity代码

private void initView() {
mRecyclerView = (RecyclerView) findViewById(R.id.id_rv);
mFab = (ImageButton) findViewById(R.id.id_fab);
mToolbar = (Toolbar) findViewById(R.id.id_toolbar);
setSupportActionBar(mToolbar);
setTitle("HLQ-Blog");
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
List<String> sList = new ArrayList<>();
for (int i = 0; i < 50; i++) {
sList.add("Hi Every One " + i);
}
FabRecycleAdapter adapter = new FabRecycleAdapter(sList);
mRecyclerView.setAdapter(adapter);
}

哦了,伙计们,现在鼠标轻轻一点,运行查看效果~

GitHub查看地址

​​https://github.com/HLQ-Struggle/MaterialDesignStudy​​

举报

相关推荐

0 条评论