Android自定義View-----TitleHead隨列表拖動漸變---TitleHeadRecyclerView
阿新 • • 發佈:2019-02-03
仿照網易的有道詞典的專欄詳情的上拉下來效果。
特點
- 繼承RecyclerView,重寫onTouchEvent()事件,根據不同情況執行不同的操作。
- 使用LayoutParams改變View引數,實現View的大小改變。
- 使用setX()方法,改變View的座標,實現View的移動動畫。
- 可把RecyclerView替換為其他型別的View,如ScrollerView、ListView等。
- 除了TitleHead的大小改變動畫,還可以擴充套件不同的動畫效果,如字型漸變、圖片移動、圖片縮放等動畫。
實現思路
- 實現TitleHead隨著手指移動進行高度縮放的效果,需要攔截RecyclerView的滑動事件,由於RecyclerView的滑動操作是在onTouchEvent()方法中實現的,所以通過繼承RecyclerView,重寫onTouchEvent()方法,根據TitleHead的高度判斷,是執行RecyclerView的滑動操作(呼叫父類的onTouchEvent()),還是執行TitleHead的高度縮放,這樣相當於模擬事件攔截機制。
- 除了實現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一下!謝謝!