Android View的用法中事件拦截和Scroller的滑动一直是值得注意的地方,这次的双向滑动ScrollView就是利用这2个知识点来实现。
关于Scroller
Scroller是用来帮助实现滑动的辅助类,它的内部封装了关于滚动的参数比如getCurrX(),getCurrY()获取目前应该滚动的位置,通过调用scrollTo(),scrollBy()方法来进行滚动(scrollBy()方法其实也就是调用的scrollTo())。滚动的时候会启动一个循环进程定期的去调用 computeScroll()方法,我们可以在这个方法中判断滚动的状态,如何判断滚动状态呢? 调用computeScrollOffset()方法会返回true或者false,true表示滑动未完成,未完成我们就继续 scrollTo() 然后postInvalidate() 让它完成滑动。整个过程有点费解,不过没关系,下面看代码的时候大家可以明白。
开始实现
首先开始做点准备工作。
public class MyScrollView extends FrameLayout {
//处理滑动的Scroller 这里如果是api 9以上最好使用OverScroller代替Scroller
//Scroller的速滑效果很差
private OverScroller mScroller;
//判断滑动速度
private VelocityTracker mVelocityTracker;
//滑动的阀值
private int mTouchSlop;
//滑动速度
private int mMaxVelocity, mMinVelocity;
//滑动锁
private boolean mDragging = false;
//上一次移动事件的位置
private float mLastX, mLastY;
public MyScrollView(Context context) {
super(context);
init(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void init(Context context) {
mScroller = new OverScroller(context);
mVelocityTracker = VelocityTracker.obtain();
//获取系统的触摸阀值
//可以认为用户是在滑动的距离
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
//滑动的最快速度
mMaxVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
//滑动的最慢速度
mMinVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
}
这里系统给我们提供了很多阀值给我们使用,比如这里的判断用户是否是滑动 ViewConfiguration.get(context).getScaledTouchSlop()
,在滑动的时候有快速滑动的情况这种情况,需要使用检测类VelocityTracker来帮我们计算用户的滑动速度,同时获取系统的滑动速度阀值,来判断是否进行速滑操作。
这里还需要去重写测量方法,原因如果不复写父视图的默认方案会强制子视图和父视图一样大 也就是按父视图的方案来实现
//这里的方案是不测量保证视图尽可能按自己的大小来 如果不复写父视图的默认方案会强制子视图和父视图一样大 也就是按父视图的方案来实现
@Override
protected void measureChild(View child, int p