仿QQ空间,百思不得姐下拉刷新图片放大

本文介绍如何在ListView中实现类似QQ空间下拉图片放大的效果,通过覆盖overScrollBy方法并在手指滑动时调整ImageView的高度来实现。同时介绍了如何在onScrollChanged和onTouchEvent方法中控制图片的放大和回弹动画。

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

1.概述


  实习生进阶到项目部分会带他们做一个百思不得姐项目,那么个人主页就有类似于QQ空间下拉图片放大的效果,趁着现在还闲就实现一下效果:
  
  这里写图片描述

2.实现 


  1. 效果分析
ScrollView和ListView都可以实现,关键要知道这个方法overScrollBy()这个方法是ListView,ScrollView滑动过头的时候调用,也可以说是当我们已经滑动到最上面然后向下拉的时候会调用。

  2. 效果实现
  2.1 覆盖overScrollBy()方法当deltaY<0的时候不断的改变图片的高度,当拉到最大的高度时开启一个放大的动画,下面请看代码:

public class ParallaxListView extends ListView {
    private ImageView mImageView;
    // 定义一个imageview的最大的拉伸的高度
    private int mDrawableMaxHeight = -1;
    // 定义ImageView 初始加载的高度
    private int mImageViewHeight = -1;
    // 默认的高度
    private int mDefaultImageViewHeight = 0;

    public ParallaxListView(Context context) {
        this(context, null);
    }

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

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

    private void init() {
        mDefaultImageViewHeight = (int) getResources().getDimension(
                R.dimen.size_default_height);
    }

    /**
     * 设置可拉伸的图片
     */
    public void setParallaxImageView(ImageView iv) {
        this.mImageView = iv;
        mImageView.setScaleType(ScaleType.CENTER_CROP);
    }

    /**
     * 设置缩放级别 -- 控制图片的最大拉伸度 在界面加载完毕的时候调用
     */
    public void setZoomRatio(double zoomRatio) {
        if (mImageViewHeight == -1) {
            mImageViewHeight = mImageView.getHeight();
            if (mImageViewHeight < 0) {
                mImageViewHeight = mDefaultImageViewHeight;
            }

            mDrawableMaxHeight = (int) (zoomRatio*mImageViewHeight);
        }
    }

    @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 true 下拉到某一个地方的时候不再往下拉
        return isCollapse ? true : super.overScrollBy(deltaX, deltaY, scrollX,
                scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,
                maxOverScrollY, isTouchEvent);
    }

    private boolean resizeOverScrollBy(int deltaX, int deltaY, int scrollX,
            int scrollY, int scrollRangeX, int scrollRangeY,
            int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        // 下拉的过程当中,不断的控制ImageView的高度
        /**
         * deltaY 是在超出滑动的时候每秒滑动的距离 (- 往上拉 +往下拉) 大小根据用户滑动的速度决定的 一般滑动50~-50
         */
        if (deltaY < 0) {
            if(mDrawableMaxHeight != -1){
                if(mImageView.getLayoutParams().height>=mDrawableMaxHeight){
                    // 当不能再往下拉的时候开启一个放大动画
                    mImageView.animate().scaleX(1.1f).scaleY(1.1f).setDuration(300).start();
                    return true;
                }
            }

            mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY;
            // 重新调整ImageView的高度
            mImageView.requestLayout();
        } else {
            // 不松开往上拉的时候应该将图片的高度不断的减小
            if (mImageView.getHeight() > mImageViewHeight) {
                mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY > mImageViewHeight ? mImageView
                        .getHeight() - deltaY
                        : mImageViewHeight;
                mImageView.requestLayout();
                return true;
            }
        }
        return false;

    }
}

2.2 当手指不松开往上滑动的时候,很大一部分想到的还是在overScrollBy()方法中写代码,但是该方法只是下拉滑动到头的时候调用,所以我们需要在onScrollChanged()里面做手脚:

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        // 监听ListView的滑动
        // 如何控制图片减小的高度?---监听listView头部划出去的距离
        View header = (View) mImageView.getParent();
        // 头部划出去的距离 ---<0
        if (header.getTop() < 0 && mImageView.getHeight() > mImageViewHeight) {// 大于初始的高度
            mImageView.getLayoutParams().height = Math.max(mImageView.getHeight()
                    + header.getTop(), mImageViewHeight);
            // 调整ImageView所在的容器的高度
            header.layout(header.getLeft(), 0, header.getRight(),
                    header.getHeight());
            // 重新调整ImageView的高度
            mImageView.requestLayout();
        }
    }

  2.3最后当手指抬起的时候,需要覆盖onTouch()方法,判断手指抬起,执行自定义继承Animator回弹的动画:

@Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            // 手指松开--让拉伸的图片动画的减少高度
            // 自定义动画
            if (mImageViewHeight - 1 < mImageView.getHeight()) {
                ResetAnimimation animation = new ResetAnimimation(mImageView,
                        mImageViewHeight);
                animation.setDuration(300);
                mImageView.startAnimation(animation);
                mImageView.animate().scaleX(1.0f).scaleY(1.0f).setDuration(350).start();
            }
        }
        return super.onTouchEvent(ev);
    }

public class ResetAnimimation extends Animation {
        int targetHeight;
        int originalHeight;
        int extraHeight;
        View mView;

        protected ResetAnimimation(View view, int targetHeight) {
            // 图片动画的减小高度
            this.mView = view;
            // 动画执行之后的高度
            this.targetHeight = targetHeight;
            // 动画执行之前的高度
            originalHeight = view.getHeight();
            // 高度差
            extraHeight = this.targetHeight - originalHeight;
        }

        @Override
        protected void applyTransformation(float interpolatedTime,Transformation t) {
            /** originalHeight ~~~~ targetHeight
             *  0ms            ~~~~ 300ms
             *  150ms ---> originalHeight - extraHeight*1/2
             *  interpolatedTime 变化比例(0.0~1.0)
             */

            int newHeight = (int) (targetHeight - extraHeight
                    * (1 - interpolatedTime));
            mView.getLayoutParams().height = newHeight;
            mView.requestLayout();
        }
    }

2.4 activity中的使用,如果是ListView那么需要给它添加 addHeaderView(View view),设置setParallaxImageView(ImageView iv),控制最大高度即可:

public class MainActivity extends Activity {

    private ParallaxListView mPlv;

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

        mPlv = (ParallaxListView) findViewById(R.id.parallax_listview);
        View header = View.inflate(this, R.layout.listview_header, null);
        mPlv.addHeaderView(header);

       // 设置下拉放大图片
       mPlv.setParallaxImageView((ImageView)header.findViewById(R.id.image_view));

        ArrayAdapter<String> adapter= new ArrayAdapter<String>(this, 
                android.R.layout.simple_list_item_1, 
                new String[]{"星期一 上班","星期二 打撸","星期三 约会","星期四 看电影","星期五 逛街","星期六 旅游","星期天 你懂的"});
        mPlv.setAdapter(adapter);
    }

   @Override
   public void onWindowFocusChanged(boolean hasFocus) {
       super.onWindowFocusChanged(hasFocus);
       if(hasFocus){
           // 当界面第一次显示,调用onWindowFocusChanged
           // 设置图片的缩放级别
           mPlv.setZoomRatio(2.5);
       }
   }
}

这个效果相对来讲其实比较简单,如果想要把它变成ScrollView效果,只需要改变继承类即可

附源码地址:http://download.youkuaiyun.com/detail/z240336124/9591321

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值