自定义ScrollView实现头尾部的下拉,上拉
public class MyScrollView extends ScrollView {
private View childView;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//假设ScrollView中有个LinearLayout,首先获取LinearLayout
@Override
protected void onFinishInflate() {
super.onFinishInflate();
childView = this.getChildAt(0);
}
private int lastY;//上次移动的Y坐标
private Rect normal = new Rect();//记录默认的坐标
private boolean isFinishAnimation = true;
private int lastX, downX, downY;
/**
* 事件拦截:拦截:实现父视图对子视图的拦截
* 是否拦截成功,取决于方法的返回值。返回值true:拦截成功。反之,拦截失败
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean isIntercept = false;
int eventX = (int) ev.getX();
int eventY = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = lastX = eventX;
downY = lastY = eventY;
break;
case MotionEvent.ACTION_MOVE:
//获取水平和垂直方向的移动距离
int absX = Math.abs(eventX - downX);
int absY = Math.abs(eventY - downY);
if (absY > absX && absY > UIUtils.dp2px(10)) {
isIntercept = true;
}
lastY=eventY;
lastX=eventX;
break;
}
return isIntercept;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (childView == null || !isFinishAnimation) {//没有完成动画的情况下不可再点击触摸事件
return super.onTouchEvent(ev);
}
int eventY = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = eventY;
break;
case MotionEvent.ACTION_MOVE:
int dy = eventY - lastY;
if (isNeedMove()) {
if (normal.isEmpty()) {
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;
case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {
//使用平移动画
int translateY = childView.getBottom() - normal.bottom;
TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, -translateY);
translateAnimation.setDuration(200);
//translateAnimation.setFillAfter(true);//不能使用该方法,使用后点击事件还留在原本的位置
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
isFinishAnimation = false;
}
@Override
public void onAnimationEnd(Animation animation) {
isFinishAnimation = true;
childView.clearAnimation();//清除动画
//重新布局
childView.layout(normal.left, normal.top, normal.right, normal.bottom);
//清楚normal的数据
normal.setEmpty();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
//启动动画
childView.startAnimation(translateAnimation);
}
break;
}
return super.onTouchEvent(ev);
}
private boolean isNeedMove() {
//获取子视图LinearLayout的高
int childMeasureHeight = childView.getMeasuredHeight();
//获得布局的高度(ScrollView)的高度
int scrollViewMeasuredHeight = this.getMeasuredHeight();
int dy = childMeasureHeight - scrollViewMeasuredHeight;
//获取用户在y轴方向上的偏移量(上 + 下 -)
int scrollY = this.getScrollY();
Log.e("TAG", scrollY + "");
if (scrollY <= 0 || scrollY >= dy) {//默认的的时候scroolY是处于0
return true;//按照我们自定义的MyScrollView的方式处理
}
//其他处在临界范围内的,返回false。即表示,仍按照ScrollView的方式处理
return false;
}
//判断是否需要执行平移动画
public boolean isNeedAnimation() {
return !normal.isEmpty();
}
}