今天已经是这个星期连续加班的第四天了,趁着现在后台在处理逻辑问题,将前几天写的一个小例子整理下来。
效果图
效果分析
1 向下滑动,头部的图片随着手指滑动不断变大
2 向上滑动,不断的向上移动图片,直到图片不可见
3 当顶部图片不可见时,向上滑动,滑动ListView
实现思路
1 由于这个View分上下两部分,垂直排列,可以通过继承LinearLayout实现::自定义一个DragImageView,该View继承LinearLayout
1
2
3
4
5
6
7
8
9
10
11
12
|
public DragImageView(Context context, AttributeSet attrs) { super (context, attrs); // 默认该View垂直排列 setOrientation(LinearLayout.VERTICAL); // 用于配合处理该View的惯性滑动 mScroller = new OverScroller(context); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mMaximumVelocity = ViewConfiguration.get(context) .getScaledMaximumFlingVelocity(); mMinimumVelocity = ViewConfiguration.get(context) .getScaledMinimumFlingVelocity(); } |
2 onMeasure中设置内容视图的高度
1
2
3
4
5
6
7
|
@Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { super .onMeasure(widthMeasureSpec, heightMeasureSpec); LayoutParams params = (LayoutParams) getChildAt( 1 ).getLayoutParams(); // 头部可以全部隐藏,所以内容视图的高度即为该控件的高度 params.height = getMeasuredHeight(); } |
3 设置ImageView的ScaleType属性
1
2
3
4
5
6
7
8
9
|
@Override protected void onFinishInflate() { super .onFinishInflate(); imageView = (ImageView) getChildAt( 0 ); // 随着手指滑动,图片不断放大(宽高都大于或者等于ImageView的大小),并居中显示: // 根据上边的分析,CENTER_CROP:可以使用均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都大于等于 相应的视图坐标(负的内边距),图像则位于视图的中央 imageView.setScaleType(ScaleType.CENTER_CROP); listView = (ListView) getChildAt( 1 ); } |
4 事件拦截
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { downX = ( int ) ev.getX(); downY = ( int ) ev.getY(); } if (ev.getAction() == MotionEvent.ACTION_MOVE) { int currentX = ( int ) ev.getX(); int currentY = ( int ) ev.getY(); // 确保是垂直滑动 if (Math.abs(currentY - downY) > Math.abs(currentX - downX)) { View childView = listView.getChildAt(listView .getFirstVisiblePosition()); // 有两种情况需要拦截: // 1 图片没有完全隐藏 // 2 图片完全隐藏,但是向下滑动,并且ListView滑动到顶部 if (getScrollY() != imageHeight || (getScrollY() == imageHeight && currentY - downY > 0 && childView != null && childView.getTop() == 0 )) { initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); return true ; } } } if (ev.getAction() == MotionEvent.ACTION_UP) { recycleVelocityTracker(); } return super .onInterceptTouchEvent(ev); } |
5 onTouchEvent的ACTION_MOVE处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
if (ev.getAction() == MotionEvent.ACTION_MOVE) { int currentX = ( int ) ev.getX(); int currentY = ( int ) ev.getY(); int deltyX = currentX - downX; int deltyY = currentY - downY; if (Math.abs(deltyY) > Math.abs(deltyX)) { if (deltyY > 0 ) { if (getScrollY() > 0 ) { if (getScrollY() - deltyY < 0 ) { scrollBy( 0 , -getScrollY()); return true ; } // 当图片没有完全显示,并且向下滑动时,继续整个view使图片可见 scrollBy( 0 , -deltyY); } else { // 当图片完全显示,并且向下滑动时,则不断的放大图片(通过改变ImageView)的高度 LayoutParams layoutParams = (LayoutParams) getChildAt( 0 ) .getLayoutParams(); layoutParams.height = layoutParams.height + deltyY / 2 ; getChildAt( 0 ).setLayoutParams(layoutParams); } } else { // 当图片还处于放大状态,并且向上滑动时,继续不断的缩小图片的高度,使图片缩小 if (getChildAt( 1 ).getTop() > imageHeight) { LayoutParams layoutParams = (LayoutParams) getChildAt( 0 ) .getLayoutParams(); layoutParams.height = layoutParams.height + deltyY / 2 ; getChildAt( 0 ).setLayoutParams(layoutParams); } else { // 当图片处于正常状态,并且向上滑动时,移动整个View,缩小图片的可见范围 if (getScrollY() - deltyY > imageHeight) { scrollBy( 0 , imageHeight - getScrollY()); return true ; } scrollBy( 0 , -deltyY); } } downY = currentY; downX = currentX; return true ; } } |
5 onTouchEvent的ACTION_UP处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
if (ev.getAction() == MotionEvent.ACTION_UP) { // 当图片处于放大状态时松手,使图片缓慢的缩回到原来的状态 if (getChildAt( 1 ).getTop() > imageHeight) { isAnimating = true ; ValueAnimator valueAnimator = ValueAnimator.ofInt(getChildAt( 1 ) .getTop(), imageHeight); valueAnimator.setDuration( 300 ); valueAnimator.addUpdateListener( new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (Integer) animation.getAnimatedValue(); LayoutParams layoutParams = (LayoutParams) getChildAt( 0 ) .getLayoutParams(); layoutParams.height = value; getChildAt( 0 ).setLayoutParams(layoutParams); } }); valueAnimator.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super .onAnimationEnd(animation); isAnimating = false ; } }); valueAnimator.start(); } // 当现在图片处于正常状态,并且图片没有完全隐藏,并且松手时滑动的速度大于可惯性滑动的最小值,让View产生惯性滑动效果 if (getChildAt( 1 ).getTop() == imageHeight && getScrollY() != imageHeight) { mVelocityTracker.computeCurrentVelocity( 1000 , mMaximumVelocity); int velocityY = ( int ) mVelocityTracker.getYVelocity(); if (Math.abs(velocityY) > mMinimumVelocity) { fling(-velocityY); } recycleVelocityTracker(); } |
总结
这里主要有两个学习的点
1 图片缩放的处理,事件的拦截
2 View的惯性滑动:主要是结合OverScroller的使用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/u012950099/article/details/51999305