仿QQ空间下拉头部缩放

本文介绍了如何使用ParallaxListView自定义滚动视图,通过设置缩放级别实现在不同滚动位置时动态改变ImageView的大小,实现了响应式的视觉效果。文章详细解释了关键代码实现及动画效果的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Activity代码:

public class MainActivity extends Activity {

    private ParallaxListView pListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        View headerView = View.inflate(this, R.layout.header_view, null);
        ImageView ivBackground = (ImageView) headerView.findViewById(R.id.ivBackground);
        pListView = (ParallaxListView) findViewById(R.id.listView);
        pListView.addHeaderView(headerView);

        pListView.setParallaxImageView(ivBackground);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, new String[] { "星期一  上班", "星期二  打豆豆","星期三  看星星", "星期四    学习", "星期五 放假", "星期六  拍拖", "星期天  看电影","...." });

        pListView.setAdapter(adapter);
    }
//在view加载完成时设定缩放级别
    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
        if (hasWindowFocus) {
            pListView.setViewsBounds(2);
        }

    }
}

主页面布局(main_activity.xml):

<?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" >

<ke.qq.tzparallaxlistview.ParallaxListView 
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    />
</LinearLayout>

头部布局(header_view.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" >

    <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:contentDescription="@string/app_name"
        android:scaleType="centerCrop"
        android:src="@drawable/header" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="20dp"
        android:contentDescription="@string/app_name"
        android:paddingBottom="20dp"
        android:src="@drawable/lf" />

</RelativeLayout>

关键部分->自定义ListView:ParallaxListView

public class ParallaxListView extends ListView {

    protected static final String TAG = ParallaxListView.class.getName();

    private ImageView mImageView;
    // 定义ImageView的最大可拉伸的高度
    private int mDrawableMaxHeight = -1;
    // 定义ImageView初始加载的高度
    private int mImageViewHeight = -1;
    // 定义ImageView的默认高度
    private int mDefaultImageViewHeight = 0;

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

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

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

    public void setParallaxImageView(ImageView iv) {
        mImageView = iv;
        mImageView.setScaleType(ScaleType.CENTER_CROP);
    }

    // 设置缩放级别---控制图片的最大拉伸高度
    // 在界面加载完毕的时候调用
    public void setViewsBounds(double zoomRatio) {
        // mDrawableMaxHeight=zoomRatio*mDefaultImageViewHeight;
        if (mDrawableMaxHeight == -1) {

            mImageViewHeight = mImageView.getHeight();
            if (mImageViewHeight < 0) {

                mImageViewHeight = mDefaultImageViewHeight;
            }
        }
    }

    /**
     * 初始化
     * 
     * @param context
     */
    private void init(Context context) {
        setVerticalScrollBarEnabled(false);
        mDefaultImageViewHeight = 449;

    }


    //内部滑动时调用
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        // 监听listView的滑动
        super.onScrollChanged(l, t, oldl, oldt);
        // 如何控制图片见效的高度?---监听listView的头部滑出去的距离
        View header = (View) mImageView.getParent();

        // 得到头部划出去的距离----<0
        if (header.getTop() < 0 && mImageView.getHeight() > mImageViewHeight) {

            mImageView.getLayoutParams().height = Math.max(
                    mImageView.getHeight() - Math.abs(header.getTop()), mDefaultImageViewHeight);
            header.layout(header.getLeft(), 0, header.getRight(), header.getHeight());

            // 调整ImageView所在容器的高度
            mImageView.requestLayout();

        }
    }


    //在划出屏幕时调用
    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
            int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,
            boolean isTouchEvent) {

        // 当listView,ScrollView滑动过头的时候回调的方法
        // 不断地控制ImageView的高度
        boolean isCollapse = resizeOverScrollby(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
                scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

        return isCollapse ? true : super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

    /**
     * 处理listView,ScrollView滑动过头
     * @param deltaX
     * @param deltaY
     * @param scrollX
     * @param scrollY
     * @param scrollRangeX
     * @param scrollRangeY
     * @param maxOverScrollX
     * @param maxOverScrollY
     * @param isTouchEvent
     * @return
     */
    private boolean resizeOverScrollby(int deltaX, int deltaY, int scrollX, int scrollY,
            int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,
            boolean isTouchEvent) {
        if (deltaY < 0) {
            mImageView.getLayoutParams().height = Math.max(
                    mImageView.getHeight() + Math.abs(deltaY), mDefaultImageViewHeight);
            // 重新调整ImageView的宽高
            mImageView.requestLayout();
        } else {

            if (mImageView.getHeight() > mDefaultImageViewHeight)
                mImageView.getLayoutParams().height = mImageView.getHeight() - Math.abs(deltaY);
            // 重新调整ImageView的宽高
            mImageView.requestLayout();
        }

        return true;
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        //松开手时,展示动画效果
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            ResetAnimation anim = new ResetAnimation(mImageView, mDefaultImageViewHeight);

            anim.setDuration(500);
            mImageView.startAnimation(anim);
        }

        return super.onTouchEvent(ev);
    }

    //自定义动画效果
    public class ResetAnimation extends Animation {

        private ImageView mView;
        // private int targetHeight;
        private int originalHeith;
        private int extraHeight;

        public ResetAnimation(ImageView mView, int targetHeight) {
            // 图片动画地减小高度
            this.mView = mView;
            // this.targetHeight = targetHeight;
            this.originalHeith = mView.getHeight();

            extraHeight = originalHeith - targetHeight;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);

            //interpolatedTime的值为0.0~1.0f
            mView.getLayoutParams().height = (int) (originalHeith - extraHeight * interpolatedTime);
            mView.requestLayout();
        }
    }

}

demo链接

效果图:
效果图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值