NotBoringActionBar项目的思路解析

NotBoringActionBar项目的思路解析

       NotBoringActionBar项目实现方式十分巧妙。
       从外表上看,ListView向上滚动时,ListView的头部会缩小,logo图标从中间不断缩小移向标题栏的左上角,并且标题栏逐渐显示出来。

<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=".NoBoringActionBarActivity">
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white" />
    <FrameLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="@dimen/header_height">
        <com.flavienlaurent.notboringactionbar.KenBurnsView
            android:id="@+id/header_picture"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/picture0" />
        <ImageView
            android:id="@+id/header_logo"
            android:layout_width="@dimen/header_logo_size"
            android:layout_height="@dimen/header_logo_size"
            android:layout_gravity="center"
            android:src="@drawable/ic_header_logo" />
    </FrameLayout>
</FrameLayout>

       布局文件中的FragmentLayout实际上就是我们看到的背景图片和Logo图标的区域。它们与ListView是重叠在一起的。那么问题来了,重叠在一起?那为什么ListView的内容不会被遮盖,或者背景图片和Logo图标的区域被遮盖呢?
       源码中,ListView实际上被设置了ListView头部,看Activity文件中的setupListView方法,其中有以下代码段:

        mPlaceHolderView = getLayoutInflater().inflate(R.layout.view_header_placeholder, mListView, false);
        mListView.addHeaderView(mPlaceHolderView);

       ListView被添加了ListView头部,并且ListView头部的高度与“背景图片和Logo图标的区域”的高度是一样的,这就是为什么ListView和“背景图片和Logo图标的区域”不会互相遮挡的原因。
       不过等等,这样的话,屏幕一上滑或下滑,“背景图片和Logo图标的区域”会一直不动,ListView则会滚动,那这不乱套了吗?
       同样看Activity文件中的setupListView方法,其中设置了ListView的滑动监听:

mHeader.setTranslationY(Math.max(-scrollY, mMinHeaderTranslation));

       只要一滑动,“背景图片和Logo图标的区域”就会通过setTranslationY方法设置高度,这样看起来就像它会随着屏幕上滑而上滑,并且最终固定在标题栏的高度大小。
       说到标题栏,实际上,它一直都在,只是刚开始它被设置为透明的。逐渐显示出来的效果实际上是标题栏文本(前景)的逐渐显示,Activity文件中的setupActionBar方法:

    private void setupActionBar() {
        ActionBar actionBar = getActionBar();
        //设置标题栏透明
        actionBar.setIcon(R.drawable.ic_transparent);
        //getActionBarTitleView().setAlpha(0f);
    }

       那么它是怎样随着屏幕上滑逐渐显示出来的呢?秘密还在在ListView的滑动监听中:

setTitleAlpha(clamp(5.0F * ratio - 4.0F, 0.0F, 1.0F));

       setTitleAlpha方法不断改变标题栏文本的透明度,这就出现了标题栏逐渐显示出来的效果。
       最后一点,当屏幕上滑时,Logo图标会逐渐缩小并向左上移动,实现的方法是Activity文件中的interpolate:

    private void interpolate(View view1, View view2, float interpolation) {
        //获取Logo图片的Rect
        getOnScreenRect(mRect1, view1);
        //获取view2图片的Rect
        getOnScreenRect(mRect2, view2);
        //缩放比例
        float scaleX = 1.0F + interpolation * (mRect2.width() / mRect1.width() - 1.0F);
        float scaleY = 1.0F + interpolation * (mRect2.height() / mRect1.height() - 1.0F);
        //位移比例
        float translationX = 0.5F * (interpolation * (mRect2.left + mRect2.right - mRect1.left - mRect1.right));
        float translationY = 0.5F * (interpolation * (mRect2.top + mRect2.bottom - mRect1.top - mRect1.bottom));
        //设置Logo的位移和缩放比例
        view1.setTranslationX(translationX);
        view1.setTranslationY(translationY - mHeader.getTranslationY());
        view1.setScaleX(scaleX);
        view1.setScaleY(scaleY);
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值