利用 CollapsingToolbarLayout 完成联动的动画效果

最近项目中需要实现个动画效果,研究了下这里做下简单的分享.

效果图如下:

最初的想法是自己去利用 Android 的嵌套滚动机制,去实现上面的嵌套滚动效果.但最后为了开发效率直接利用了 CollapsingToolbarLayout 和 CoordinatorLayout 的效果. 实现效果的原理十分简单,监听 CollapsingToolbarLayout 收缩和扩展的距离,换算成你想要的一个范围比如移动的距离,缩放的比例.

部分源码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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.xf.mylab.activity.CollapsingToolbarLayoutTestActivity">

    <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.wswy.chechengwang.view.activity.SubscriptionDetailActivity">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/subscription_head">

            <android.support.design.widget.CollapsingToolbarLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">


                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/toolbar_height"
                    app:layout_collapseMode="pin">


                    <ImageView
                        android:id="@+id/back"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:src="@drawable/ic_white_left_arrow" />

                </android.support.v7.widget.Toolbar>

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


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


        <android.support.v4.widget.NestedScrollView
            android:id="@+id/subscription_show"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="夏洛克的猫"
                android:textSize="30sp" />
        </android.support.v4.widget.NestedScrollView>


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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/subscription_head"
        android:gravity="center"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/iv_head"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_default_subscription" />

        <TextView
            android:id="@+id/subscription_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="夏洛克的猫"
            android:textColor="@color/white"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/subscribe"
            android:layout_width="75dp"
            android:layout_height="24dp"
            android:layout_marginTop="8dp"
            android:button="@null"
            android:checked="false"
            android:gravity="center"
            android:text="订阅"
            android:textColor="@color/white" />
    </LinearLayout>
</FrameLayout>
public class CollapsingToolbarLayoutTestActivity extends AppCompatActivity {

    private float mSelfHeight = 0;//用以判断是否得到正确的宽高值
    private float mTitleScale;
    private float mSubScribeScale;
    private float mSubScribeScaleX;
    private float mHeadImgScale;

    @Bind(R.id.iv_head)
    ImageView mHeadImage;
    @Bind(R.id.subscription_title)
    TextView mSubscriptionTitle;
    @Bind(R.id.subscribe)
    TextView mSubscribe;
    @Bind(R.id.app_bar)
    AppBarLayout mAppBar;
    @Bind(R.id.toolbar)
    Toolbar mToolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_collapsing_toolbar_layout_test);
        ButterKnife.bind(this);

        final float screenW = getResources().getDisplayMetrics().widthPixels;
        final float toolbarHeight = getResources().getDimension(R.dimen.toolbar_height);
        final float initHeight = getResources().getDimension(R.dimen.subscription_head);
        mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (mSelfHeight == 0) {
                    mSelfHeight = mSubscriptionTitle.getHeight();
                    float distanceTitle = mSubscriptionTitle.getTop() + (mSelfHeight - toolbarHeight) / 2.0f;
                    float distanceSubscribe = mSubscribe.getY() + (mSubscribe.getHeight() - toolbarHeight) / 2.0f;
                    float distanceHeadImg = mHeadImage.getY() + (mHeadImage.getHeight() - toolbarHeight) / 2.0f;
                    float distanceSubscribeX = screenW / 2.0f - (mSubscribe.getWidth() / 2.0f + getResources().getDimension(R.dimen.normal_space));
                    mTitleScale = distanceTitle / (initHeight - toolbarHeight);
                    mSubScribeScale = distanceSubscribe / (initHeight - toolbarHeight);
                    mHeadImgScale = distanceHeadImg / (initHeight - toolbarHeight);
                    mSubScribeScaleX = distanceSubscribeX / (initHeight - toolbarHeight);
                }
                float scale = 1.0f - (-verticalOffset) / (initHeight - toolbarHeight);
                mHeadImage.setScaleX(scale);
                mHeadImage.setScaleY(scale);
                mHeadImage.setTranslationY(mHeadImgScale * verticalOffset);
                mSubscriptionTitle.setTranslationY(mTitleScale * verticalOffset);
                mSubscribe.setTranslationY(mSubScribeScale * verticalOffset);
                mSubscribe.setTranslationX(-mSubScribeScaleX * verticalOffset);
            }
        });
    }
}

代码其实没啥可说的,主要是一些距离的计算,主要就是顶在最上方时,文字都到了居中的位置.大家在图中画出开始和结束的位置,都能计算出来.

有一点提一下,最初我是把布局嵌入到 CollapsingToolbarLayout 中去的,但是由于 CollapsingToolbarLayout 自身的收缩和扩展改变了自身高度,会影响里面的 View 的位置,如果按照静态的起始和结束位置计算,加上自身高度对 View 布局的影响,这就复杂了,我没有细研究.采用了一个笨拙的方式,用 FrameLayout 把布局给抽取到顶部,不让他们受到 CollapsingToolbarLayout 的影响.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开发之途

Android 仿360悬浮球与加速球

65280
来自专栏知识分享

3-系统方案A(Activity界面跳转,携带数据,显示曲线界面)

https://www.cnblogs.com/yangfengwu/p/9970387.html

10920
来自专栏向治洪

android自定义view实现progressbar的效果

一键清理是很多Launcher都会带有的功能,其效果也比较美观。实现方式也许有很多中,其中常见的是使用图片drawable来完成的,具体可以参考这篇文章:模仿实...

29950
来自专栏向治洪

android放大镜效果实现

概述 我相信很多用过英语应用的同学都看多一个放大镜的效果,就是选中一段文字后,会有一个放大镜,这个究竟怎么实现的呢,我们今天来分析分析。 ? 源码分析 publ...

34580
来自专栏封碎

Android放大镜的实现 博客分类: Android Android

快三个月了没写博客了,因为工作调动,很多经验、心得都没有时间记录下来。现在时间稍微充裕了点,我会尽量抽时间将之前想写而没写的东西补上。进入正题。     ...

31910
来自专栏林冠宏的技术文章

实现一个网易云音乐的 BottomSheetDialog

作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:htt...

46670
来自专栏Android干货

安卓开发_慕课网_百度地图_实现方向传感器

32360
来自专栏Android知识点总结

2--安卓多媒体之Bitmap操作全解析

12120
来自专栏Android知识点总结

D3-Android 自定义控件绘图之柱状图

30220
来自专栏林冠宏的技术文章

android 之 ListView 里面嵌套 GridView 遇到的问题及其解决方法。

我们直接入主题。所有问题例子请参照下图 ? 1,怎样使图片具有点击事件? 答:      解决方法:      在你的BaseAdapter里面不要设置下面这三...

27050

扫码关注云+社区

领取腾讯云代金券