Android 自定義view:實現ListView下拉的視差特效
一、概述:
現在流型的APP如微信朋友圈,QQ空間,微博個人展示都有視差特效的影子。
如圖:下拉圖片會產生圖片拉昇的效果,放手後圖片有彈回到原處:
那我們如何實現呢?
1)重寫ListView控制元件:
2)重寫裡面的overScrollBy方法
3)在鬆手後執行值動畫
二、具體實現:
1.建立ParallaListView 自定義ListView
public class ParallaListView extends ListView {
private static final String TAG = "tag";
public ParallaListView (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ParallaListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ParallaListView(Context context) {
this(context, null);
}
}
2)新增到佈局裡:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.android.imooc.paralla.ParallaListView
android:id ="@+id/lv_paralla"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.android.imooc.paralla.ParallaListView>
</LinearLayout>
3)生成主頁,填充資料:
public class ParallaActivity extends Activity {
private ParallaListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_paralla);
initViews();
}
private void initViews() {
mListView = (ParallaListView) findViewById(R.id.lv_paralla);
mListView.setAdapter(new ArrayAdapter<String>(ParallaActivity.this, android.R.layout.simple_list_item_1, Cheeses.NAMES));
}
}
4)建立頭佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv_header"
android:scaleType="centerCrop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/parallax_img" />
</LinearLayout>
圖片設成scaleType=”centerCrop”模式
其它模式說明:
5)在主頁裡找到頭佈局並新增到listview裡
View mHeader = LayoutInflater.from(this).inflate(R.layout.view_paralla_header, null);
mListView = (ParallaListView) findViewById(R.id.lv_paralla);
mListView.addHeaderView(mHeader);
三、功能實現:
1.現在基本能看到效果了,但我們必須要拖動圖片,這就要實現這個方法overScrollBy
因為拖動是Y軸方向,所以只要列印Y軸方向的各個引數就好了
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
Logger.i(TAG, "deltaY="+deltaY + " scrollX="+scrollX+ " scrollRangeY="+scrollRangeY + " maxOverScrollY=" +maxOverScrollY + " isTouchEvent=" +isTouchEvent);
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY,
isTouchEvent);
}
得到資料下拉:deltaY=-3 scrollX=0 scrollRangeY=0 maxOverScrollY=0 isTouchEvent=true
得到資料上拉:deltaY=4 scrollX=0 scrollRangeY=0 maxOverScrollY=0 isTouchEvent=true
2.如果是下拉,我們把值賦給header,但我們如何獲得高度呢?
1)在主頁裡初始化圖片,然後設定到parallaListView裡
ImageView iv = (ImageView) findViewById(R.id.iv_head);
mListView.setParallaImage(iv);
2)在parallaListView建立方法setParallaImage
public void setParallaImage(ImageView iv) {
mImageView = iv;
//在這個方法裡獲得高度
int height = iv.getHeight();
int measureHeight = iv.getMeasuredHeight();
int instrinsicHeight = iv.getDrawable().getIntrinsicHeight();
Logger.i(TAG, "height="+height + " measureHeight="+measureHeight+ " instrinsicHeight="+instrinsicHeight );
}
得到結果:height=0 measureHeight=0 instrinsicHeight=732
為什麼會如此:因為此時的圖片還沒有初始化
那我們如何得到高度呢?
記得有個方法叫做iv.getViewTreeObserver(),那我們就在這個方法的監聽事件裡得到高度
iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//當佈局填充完成後,此方法會被呼叫
mListView.setParallaImage(iv);
//移除監聽
iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
此時得到的高度height=240 measureHeight=240 instrinsicHeight=732
3)把值賦給圖片就能實現拉伸的效果了
if (isTouchEvent && deltaY < 0) {
mHeight += Math.abs(deltaY);
if (mHeight <= mBitmapHeight) {
mImageView.getLayoutParams().height = mHeight;
mImageView.requestLayout();
}
}
3.鬆手後圖片回彈,這個功能在onTouchEvent裡實現:
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
final int startHeight = mImageView.getHeight();
final int endHeight = mBitmapHeight;
//值動畫
//valueAnim(startHeight, endHeight);
//豎直移動動畫
ResetAnimation anim = new ResetAnimation(mImageView, startHeight, endHeight);
anim.setInterpolator(new OvershootInterpolator());
startAnimation(anim);
break;
default:
break;
}
return super.onTouchEvent(ev);
}
4、動畫實現:
/**
* @描述 使用平移動畫實現下拉圖片後彈射回去
* @專案名稱 App_imooc
* @包名 com.android.imooc.paralla
* @類名 ResetAnimation
* @author chenlin
* @date 2016年5月29日 下午12:27:00
* @version 1.0
*/
public class ResetAnimation extends Animation {
private ImageView mImageView;
private int mStartHeight;
private int mEndHeight;
public ResetAnimation(ImageView imageView, int startHeight, int endHeight) {
this.mImageView = imageView;
this.mStartHeight = startHeight;
this.mEndHeight = endHeight;
setDuration(500);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
int newHeight = (int) (ValueUtil.evalute(interpolatedTime, mStartHeight, mEndHeight) + 0.5f);
mImageView.getLayoutParams().height = newHeight;
mImageView.requestLayout();
super.applyTransformation(interpolatedTime, t);
}
}
四、原始碼下載:
———————————————————————
(java 架構師全套教程,共760G, 讓你從零到架構師,每月輕鬆拿3萬)
有需求者請進站檢視,非誠勿擾
https://item.taobao.com/item.htm?spm=686.1000925.0.0.4a155084hc8wek&id=555888526201
01.高階架構師四十二個階段高
02.Java高階系統培訓架構課程148課時
03.Java高階網際網路架構師課程
04.Java網際網路架構Netty、Nio、Mina等-視訊教程
05.Java高階架構設計2016整理-視訊教程
06.架構師基礎、高階片
07.Java架構師必修linux運維繫列課程
08.Java高階系統培訓架構課程116課時
(送:hadoop系列教程,java設計模式與資料結構, Spring Cloud微服務, SpringBoot入門)
——————————————————————–