代码如下 | 复制代码 |
publicclassMyScrollViewextendsScrollView { privateView childView; publicMyScrollView(Context context) { super(context); } publicMyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } publicMyScrollView(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); } // @Override // protected void onLayout(boolean changed, int l, int t, int r, int b) { // super.onLayout(changed, l, t, r, b); // } //获取子视图 @Override protectedvoidonFinishInflate() { super.onFinishInflate(); if(getChildCount() >0) { childView = getChildAt(0); } } privateintlastY;//上一次y轴方向操作的坐标位置 privateRect normal =newRect();//用于记录临界状态的左、上、右、下 privatebooleanisFinishAnimation =true;//是否动画结束 privateintlastX, downX, downY; //拦截:实现父视图对子视图的拦截 //是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败 @Override publicbooleanonInterceptTouchEvent(MotionEvent ev) { booleanisIntercept =false; inteventX = (int) ev.getX(); inteventY = (int) ev.getY(); switch(ev.getAction()) { caseMotionEvent.ACTION_DOWN: lastX = downX = eventX; lastY = downY = eventY; break; caseMotionEvent.ACTION_MOVE: //获取水平和垂直方向的移动距离 intabsX = Math.abs(eventX - downX); intabsY = Math.abs(eventY - downY); if(absY > absX && absY >= UIUtils.dp2px(10)){ isIntercept =true;//执行拦截 } lastX = eventX; lastY = eventY; break; } returnisIntercept; } @Override publicbooleanonTouchEvent(MotionEvent ev) { if(childView ==null|| !isFinishAnimation) { returnsuper.onTouchEvent(ev); } inteventY = (int) ev.getY();//获取当前的y轴坐标 switch(ev.getAction()) { caseMotionEvent.ACTION_DOWN: lastY = eventY; break; caseMotionEvent.ACTION_MOVE: intdy = eventY - lastY;//微小的移动量 if(isNeedMove()) { if(normal.isEmpty()) { //记录了childView的临界状态的左、上、右、下 normal.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom()); } //重新布局 childView.layout(childView.getLeft(), childView.getTop() + dy /2, childView.getRight(), childView.getBottom() + dy /2); } lastY = eventY;//重新赋值 break; caseMotionEvent.ACTION_UP: if(isNeedAnimation()) { //使用平移动画 inttranslateY = childView.getBottom() - normal.bottom; TranslateAnimation translateAnimation =newTranslateAnimation(0,0,0, -translateY); translateAnimation.setDuration(200); // translateAnimation.setFillAfter(true);//停留在最终位置上 translateAnimation.setAnimationListener(newAnimation.AnimationListener() { @Override publicvoidonAnimationStart(Animation animation) { isFinishAnimation =false; } @Override publicvoidonAnimationEnd(Animation animation) { isFinishAnimation =true; childView.clearAnimation();//清除动画 //重新布局 childView.layout(normal.left, normal.top, normal.right, normal.bottom); //清除normal的数据 normal.setEmpty(); } @Override publicvoidonAnimationRepeat(Animation animation) { } }); //启动动画 childView.startAnimation(translateAnimation); } break; } returnsuper.onTouchEvent(ev); } //判断是否需要执行平移动画 privatebooleanisNeedAnimation() { return!normal.isEmpty(); } privatebooleanisNeedMove() { intchildMeasuredHeight = childView.getMeasuredHeight();//获取子视图的高度 intscrollViewMeasuredHeight =this.getMeasuredHeight();//获取布局的高度 Log.e("TAG","childMeasuredHeight = "+ childMeasuredHeight); Log.e("TAG","scrollViewMeasuredHeight = "+ scrollViewMeasuredHeight); intdy = childMeasuredHeight - scrollViewMeasuredHeight;//dy >= 0 intscrollY =this.getScrollY();//获取用户在y轴方向上的偏移量 (上 + 下 -) if(scrollY <=0|| scrolly="">= dy) { returntrue;//按照我们自定义的MyScrollView的方式处理 } //其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理 returnfalse; } } |