Android ListView頭部視差控件

Android ListView頭部視差控件

效果展示

代碼實現

靜態佈局,爲ListView增加頭部的View


     mListView = (ParallaxListView) findViewById(R.id.listview);
        mHeadView = View.inflate(this, R.layout.head, null);            //異步解析xml中的佈局
        mListView.addHeaderView(mHeadView);

自定義ListView,重寫overScrollBy方法

overScrollBy方法會在ListView滑動到頂部和底部時會調用。
獲取頭部控件的大小需要在佈局解析完成後才能知道,否則得到的將是0,
通過設置監聽器mHeadView.getViewTreeObserver().addOnGlobalLayoutListener,
當佈局文件解析完成後,會調用此監聽器中的回調方法,這是就可以將頭部控件傳入自定義的ListView中了

    public class ParallaxListView extends ListView {

    public ParallaxListView(Context context) {
        super(context);
    }

    public ParallaxListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ParallaxListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private ImageView parallaxImageView;
    private int maxHeight;
    private int originalHeight;

    public void setParallaxImageView(ImageView parallaxImageView) {
        this.parallaxImageView = parallaxImageView;
        originalHeight = parallaxImageView.getHeight();

        //獲得imagview上圖片的原始高度,即爲imageview的最高度
        maxHeight = parallaxImageView.getDrawable().getIntrinsicHeight();

    }


    /**
     * 當ListView被滑動到頂部和底部時會調用此方法
     *
     * @param deltaY         y方向滑動的距離。 正:底部到頭;負:頂部到頭
     * @param maxOverScrollY 到頭後,最大可滾動的範圍
     * @param isTouchEvent   是否是觸摸滑動。true:手指拖動到頭;false:慣性滑動到頭。
     * @return
     */
    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        if (deltaY < 0 && isTouchEvent) {
            int newHeight = parallaxImageView.getHeight() - deltaY / 3;     //新的高度增加與手指拖動的距離不成正比,
            //達到拖動吃力的效果
            if (newHeight > maxHeight) newHeight = maxHeight;
            if (parallaxImageView != null) {
                parallaxImageView.getLayoutParams().height = newHeight;
                parallaxImageView.requestLayout();                              //當完成高度設置後,需要調用重新佈局方法
            }
        }

        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

    }
    }

MainActivity

    final ImageView parallaxImageView = (ImageView) mHeadView.findViewById(R.id.imageView);
        //當從xml中加載完成後,才能知道imageview的長高
        mHeadView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()      {
            @SuppressLint("NewApi")
            @Override
            public void onGlobalLayout() {
                mListView.setParallaxImageView(parallaxImageView);
                mHeadView.getViewTreeObserver().removeOnGlobalLayoutListener(this);  //取消當前的觀察者
            }
        });
        mAdapter = new MyAdapter(this, R.layout.list_item, lists);
        mListView.setAdapter(mAdapter);

設置動畫

當手指擡起時,希望頭部View可以慢慢地回到原來的大小。
爲達到此目的,可以先自定義Animation  ,在構造方法中傳入需要動畫效果的View,覆寫applyTransformation方法,
該方法會傳入interpolatedTime參數,表示當前動畫進行的時間百分比,據此可以設置每一幀View的屬性,達到動畫的效果。

    public class ResetHeightAnimation extends Animation {

    int mOriginalHeight, mTargetHeight;
    int totalValue;
    View mView;

    public ResetHeightAnimation(View view, int targetHeight) {
        super();
        mTargetHeight = targetHeight;
        mView = view;
        mOriginalHeight = mView.getHeight();
        totalValue = mTargetHeight - mOriginalHeight;

        setDuration(400);
        setInterpolator(new OvershootInterpolator()); //設置加速器
    }

    /**
     * @param interpolatedTime 標示動畫執行的精度或者百分比
     *                         範圍在0~1,對於每一個進度,我都可以在此方法中爲制定的view設置屬性,
     *                         達到動畫額效果
     */
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        int newHeight = (int) (mOriginalHeight + totalValue * interpolatedTime);
        mView.getLayoutParams().height = newHeight;
        mView.requestLayout();

    }
}

完整代碼

github

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章