欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-30 22:17:47
...

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

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


前言

情不知何起,一往情深~

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

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

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


效果查看

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


实现方式一

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

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

赞赏

如果本文对各位老铁有所帮助,不妨赞助LZ喝点东西,一分也是爱~

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