1. 程式人生 > >Android自定義View-----TitleHead隨列表拖動漸變---TitleHeadRecyclerView

Android自定義View-----TitleHead隨列表拖動漸變---TitleHeadRecyclerView

    仿照網易的有道詞典的專欄詳情的上拉下來效果。

特點

  1. 繼承RecyclerView,重寫onTouchEvent()事件,根據不同情況執行不同的操作。
  2. 使用LayoutParams改變View引數,實現View的大小改變。
  3. 使用setX()方法,改變View的座標,實現View的移動動畫。
  4. 可把RecyclerView替換為其他型別的View,如ScrollerView、ListView等。
  5. 除了TitleHead的大小改變動畫,還可以擴充套件不同的動畫效果,如字型漸變、圖片移動、圖片縮放等動畫。

實現思路
  1. 實現TitleHead隨著手指移動進行高度縮放的效果,需要攔截RecyclerView的滑動事件,由於RecyclerView的滑動操作是在onTouchEvent()方法中實現的,所以通過繼承RecyclerView,重寫onTouchEvent()方法,根據TitleHead的高度判斷,是執行RecyclerView的滑動操作(呼叫父類的onTouchEvent()),還是執行TitleHead的高度縮放,這樣相當於模擬事件攔截機制。
  2. 除了實現TitleHead的高度縮放,還可以新增不同的動畫效果,如移動動畫,漸變動畫等,這時抽象出動畫執行介面,有Activity實現動畫,然後把實現物件傳到TitleHeadRecyclerView,執行動畫。

模擬事件攔截機制

手指下滑時

TitleHeadRecyclerView的onTouchEvent()中,當RecyclerView最頂端處於可見,且TitleHead的高度小於最大高度時,執行TitleHead的高度縮放動畫。否則執行super.onTouchEvent()。

手指上滑時
TitleHeadRecyclerView的onTouchEvent()方法中,當TitleHead的高度小於最大的高度,並且大於最小的高度(原始高度)時,執行TitleHead的高度縮放動畫,否則執行super.onTouchEvent()。



效果如下


用法

### xml如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android";
    android:layout_width="match_parent"
    android:layout_height="match_parent">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:id="@+id/rl_title_recyclerview_head">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="i am the head title"
                android:textSize="20sp"
                android:id="@+id/tv_title_recyclerview_head_title"
                android:gravity="center"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_title_recyclerview_title_one"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="20dp"
                android:text="i am the test textview one"
                android:textSize="15sp"
                android:visibility="gone"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_title_recyclerview_title_two"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:layout_marginBottom="40dp"
                android:text="i am the test textview two"
                android:textSize="15sp"
                android:visibility="gone"/>
        </RelativeLayout>
        <com.ligf.titleheadrecyclerview.TouchListenerRecyclerView
            android:id="@+id/recyclerview_title_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/rl_title_recyclerview_head">
        </com.ligf.titleheadrecyclerview.TouchListenerRecyclerView>
</RelativeLayout>

### activity實現高度縮放動畫介面

@Override
    public void onTitleLengthIncrease(float offset) {
        //手指下滑操作
        //注意:offset都要強制轉換為int型(為了保證得到的變化值都是一樣的)
        //mTitleHeadView高度隨手指下滑而增大
        mTitleHeadLayoutParams = mTitleHeadView.getLayoutParams();
        mTitleHeadLayoutParams.height = mTitleHeadLayoutParams.height + (int)offset;
        mTitleHeadView.setLayoutParams(mTitleHeadLayoutParams);
        Log.i(TAG, "onTitleLengthIncrease mTitleHeadLayoutParams.height:" + mTitleHeadLayoutParams.height);
        //mTitleHeadTV隨手指的下滑慢慢移動到佈局的中間
        //mTitleHeadTV的x方向的位移與mTitleHeadView在y方向的增大成比例,比例值就是x方向需要移動的總位移/y方向需要增大的總大小
        float delX = (mScreenWidth / 2 - (mTitleHeadTV.getWidth() / 2 + mHeadTitleTextInitX));
        float xOffset = delX / (600 - mHeadTitleInitHeight) * (int)offset;
        mTitleHeadTV.setX(mTitleHeadTV.getX() + xOffset);
        totalXoffset = totalXoffset + xOffset;
        totaloffset = totaloffset + (int)offset;
        Log.i(TAG, "onTitleLengthIncrease total totalXoffset:" + totalXoffset);
        Log.i(TAG, "onTitleLengthIncrease total totaloffset:" + totaloffset);
        //重新整理佈局
        mTitleHeadView.invalidate();
    }
    @Override
    public void onTitleLengthDecrease(float offset) {
        //手指上滑操作
        //注意:offset都要強制轉換為int型
        //mTitleHeadView高度隨手指上滑而減小
        mTitleHeadLayoutParams = mTitleHeadView.getLayoutParams();
        mTitleHeadLayoutParams.height = mTitleHeadLayoutParams.height + (int)offset;
        mTitleHeadView.setLayoutParams(mTitleHeadLayoutParams);
        //mTitleHeadTV隨手指的上滑慢慢從佈局中間移動到原始的地方
        //mTitleHeadTV的x方向的位移與mTitleHeadView在y方向的減小成比例,比例值就是x方向需要移動的總位移/y方向需要減小的總大小
        float delX = (mScreenWidth / 2 - (mTitleHeadTV.getWidth() / 2 + mHeadTitleTextInitX));
        float xOffset = delX / (600 - mHeadTitleInitHeight) * (int)offset;
        mTitleHeadTV.setX(mTitleHeadTV.getX() + xOffset);
        //重新整理佈局
        mTitleHeadView.invalidate();
    }

歡迎喜歡的朋友star一下!謝謝!