头部视差效果
- 分析思路:先给listview头部添加ImageView,然后根据手指往下拖动的距离,去让ImageView的高度不断增高,当手指抬起的时候让ImageView恢复至最初高度
- 首先,自定义ParallaxListView,继承ListView
- 然后,给ListView填充数据,并addHeaderView,添加ImageView作为头布局:
//1.添加头部IMageView View view = View.inflate(this, R.layout.layout_header, null); parallaxImage = (ImageView) view.findViewById(R.id.parallaxImage); listView.addHeaderView(view); //2.填充数据 listView.setAdapter(new MyAdapter());
- 给ParallaxListView添加setParallaxImageView方法,让外界传入ImageView的引用,因为后面需要用到:
private ImageView parallaxImageView; public void setParallaxImageView(final ImageView parallaxImageView) { this.parallaxImageView = parallaxImageView; }
并且在Activity中传入ImageView对象://设置ImageView listView.setParallaxImageView(parallaxImage);
- 根据观察,我们需要在listview滑动到头的时候去计算手指移动的距离,但是不采用去监听onTouchEvent的move事件了,我们去重写overScrollBy方法,该方法就是在listview滑动到头的时候才调用,并且可以获取到继续滑动的距离;所以我们进行判断如下:
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { isTouchEvent:"+isTouchEvent); //表示手指拖动,并且是顶部到头了, if(deltaY<0 && isTouchEvent){ ... } return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); }
-
在overScrollBy方法中判断,如果是顶部滑动到头,并且是手指继续拖动,则不断增加ImageView的高度,并且对高度作最大值的限制,代码如下:
//根据继续滑动的距离,就是deltaY,让ImageView的高度变高 int newHeight = parallaxImageView.getHeight()-deltaY/3; //对高度进行限制 if(newHeight>maxHeight)newHeight = maxHeight; //将ImageView的高变成newHeight android.view.ViewGroup.LayoutParams params = parallaxImageView.getLayoutParams(); params.height = newHeight; //重新设置高度 parallaxImageView.setLayoutParams(params);
- 当手指抬起的时候让ImageView恢复到最初高度,首先求出最初高度,需要注意的是不能够直接get,因为可能还没有测量完,我们选择添加一个全局的布局监听器,在setParallaxImageView方法中去获取:
parallaxImageView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //用完立即移除 parallaxImageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); originalHeight = parallaxImageView.getHeight(); } });
- 然后在onTouchEvent中去判断TOUCH_UP的事件,最终通过ValueAnimator实现自定义的动画,此处自定义动画的逻辑就是让ImageView的高度进行变化到指定高度:
if(ev.getAction()==MotionEvent.ACTION_UP){ //让ImageView缓慢恢复到最初的高度 ValueAnimator animator = ValueAnimator.ofInt(parallaxImageView.getHeight() ,originalHeight); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { //获取动画的值, int animatedValue = (Integer) animator.getAnimatedValue(); //将动画的值设置给parallaxImageView的高度 android.view.ViewGroup.LayoutParams params = parallaxImageView.getLayoutParams(); params.height = animatedValue; //重新设置高度 parallaxImageView.setLayoutParams(params); } }); //给动画添加速度插值器 animator.setInterpolator(new OvershootInterpolator(4));//超过一点再回来 animator.setDuration(350); animator.start(); }