借助listView实现parallaxListView

本文介绍了一种在Android中实现视差滚动效果的方法。通过自定义ParallaxListView类,可以在列表滚动时改变顶部ImageView的高度,产生视差效果。文章提供了完整的代码实现及关键方法overScrollBy的解释。

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

实现效果如下:


代码:

关键方法: overScrollBy  当列表被滑动到两端尽头的时候被调用。

public class ParallaxListView extends ListView {

    private ImageView parallaxImageView;
    private int maxHeight;
    private int originH;

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

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

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

    // 允许从外部传递视差效果的控件进来
    public void setParallaxImageView(ImageView parallaxImageView) {
        this.parallaxImageView = parallaxImageView;

        Drawable drawable = parallaxImageView.getDrawable();
        maxHeight = drawable.getIntrinsicHeight();// 获取图片的最大高度

        originH = parallaxImageView.getHeight();// 获取图片的起始高度
        System.out.println("ParallaxListView.setParallaxImageView,originH=" + originH);
    }


    @Override
    // 当列表被滑动到两端尽头的时候被调用
    // deltaY 两次滑动间的变化大小
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
                                   int scrollY, int scrollRangeX, int scrollRangeY,
                                   int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {

        System.out.println("deltaY=" + deltaY + ";scrollY=" + scrollY + ";scrollRangeY=" + scrollRangeY + ";maxOverScrollY=" + maxOverScrollY + ";isTouchEvent=" + isTouchEvent);

        if (deltaY < 0 && isTouchEvent) {
            int newHeight = parallaxImageView.getHeight() + Math.abs(deltaY / 2);
            if (newHeight < maxHeight) {
                parallaxImageView.getLayoutParams().height = newHeight;
                parallaxImageView.requestLayout();
            }
        }

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                // 将图片从当前高度弹回最初的高度
                final int currentH = parallaxImageView.getHeight();

                // 动态生成一个值的变化.依据fraction动态生成 [0,100]范围的值。
                ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator value) {
                        System.out.println("ParallaxListView.onAnimationUpdate,time=" + value.getCurrentPlayTime() + ";Fraction=" + value.getAnimatedFraction() + ";value=" + value.getAnimatedValue());

                        int newHeight = evaluate(value.getAnimatedFraction(), currentH, originH);
                        parallaxImageView.getLayoutParams().height = newHeight;
                        parallaxImageView.requestLayout();
                    }
                });
                animator.setDuration(200);
                animator.setInterpolator(new OvershootInterpolator(4));
                animator.start();
                break;

            default:
                break;
        }

        return super.onTouchEvent(ev);// 一定要使用super来返回,因为列表的滚动要由ListView处理
    }

    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int) (startInt + fraction * (endValue - startInt));
    }
}


当头部完成填充,可以正确获取imageView的高度时,把imageView设置给listView

 header = View.inflate(this, R.layout.header, null);
        parallaxImageView = (ImageView) header.findViewById(R.id.iv_header);

        // 当布局完成之后才能获取到控件高度
        header.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                header.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                System.out.println("MainActivity.onGlobalLayout,");

                listView.setParallaxImageView(parallaxImageView);// 设置要被视差效果处理的控件
            }
        });

        listView = (ParallaxListView) findViewById(R.id.listview);
        listView.addHeaderView(header);// 将视差内容设置列表头部











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值