1. 程式人生 > >Android 自定義view:實現ListView下拉的視差特效

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入門)
——————————————————————–