1.滑动效果的产生
1.1.Android坐标系
Android坐标系是以屏幕的左上角为坐标系原点,从原点水平向右为X轴正方向,从原点竖直向下为Y轴正方向。
在触摸事件中,通过getRawX( ) , etRawY( )可以获得对应的坐标。
1.2.视图坐标系
不同于上面的Android坐标系,这个坐标系是以该视图控件的左上角为原点,对应的X,Y轴和上面的同样原理。
不同于上面,这里在触摸事件中,需要通过getX( ) ,getY( )获得视图坐标系中的坐标。
1.3.触摸事件–MotionEvent
几种常用到触摸动作:
1. ACTION_DOWN:单点触摸按下动作
2. ACTION_UP:单点触摸离开动作
3. ACTION_MOVE:单点触摸移动动作
4. ACTION_CANCEL:触摸动作取消
5. ACTION_OUTSIDE:触摸动作超出边界
6. ACTION_POINTER_DOWN:多点触摸按下动作
7. ACTION_POINTER_UP:多点离开动作
常用的获取坐标值、相对距离等方法:
- View提供的获取坐标方法:
1. getTop():获取到View自身顶边到其父布局顶边的距离;
2. getLeft():获取到View自身左边到其父布局左边的距离;
3. getRight():获取到View自身右边到其父布局右边的距离;
4. getBottom():获取到View自身顶部到其父布局顶边的距离;
- MotionEvent提供的方法:
1. getX():获取到点击事件距离控件左边的距离;
2. getY():获取到点击事件距离控件顶部的距离;
3. getRawX():获取到点击事件距离整个屏幕左边的距离,为绝对坐标;
4. getRawY():获取到点击事件距离整个屏幕右边的距离,为绝对坐标。
2.七种实现滑动的方法
思路:当触摸View的时候,记录当前的触摸点,然后手指移动止呕胡,记录下移动后的距离,通过计算比较两次坐标点的偏移量,来修改View的坐标,从而实现滑动。
2.1.layout方法
就是在View的OnTouchEvent方法中,通过在ACTION_MOVE事件中动态的调用onLayout方法来实现View的滑动。
2.2.offsetLeftAndRight()与offsetTopAndBottom()
效果和onLayout一样,只是这个是计算一个偏移量之后,调用系统提供的此API。
2.3.LayoutParams
这里通过计算出来的offset来动态的改变layoutparams的margin值,这里最好用ViewGroup.MarginLayoutParams,这样就不用过多的考虑父布局到底是LinearLayout还是其他了。
2.4.scrollTo和scrollBy
to和by的区别,顾名思义,一个是移动到某一个点,一个是便宜一点的距离。
另外,scrollTo和scrollBy移动的是View的Content,也就是说让View的内容移动。如果是ViewGroup,那么移动的是它的子View,如果是View,那么移动的就是他的内容了(比如,TextView就是移动的文本内容…)。
最后一点,就是scrollBy方法的偏移量移动的是父布局,所以要想看起来是控件在动,需要设置偏移量为负值即可。
2.5.Scroller
使用Scroller类的三个步骤:
1. 初始化,通过构造方法传入一个Context对象创建一个Scroller对象;
2. 重写computeScroll()方法,实现模拟互动,系统绘制View的时候,会在onDraw()方法中调用此方法:此方法实际上就是一个scrollTo方法,就是通过这个Scroller对象把偏移量转换成一个个小距离,进行顺滑的实现。另外需要通过调用View的invalidate()方法主动的实现循环绘图;
3. startScroll开启模拟过程
2.6.属性动画
采用位移动画可以实现滚动效果。
2.7.ViewDragHelper(重点)
viewdraghelper实现;
1.初始化ViewDragHelper:
mViewDragHelper=ViewDragHelper.create(this,callback)
,调用静态方法实现初始化,第一个参数传入的是一个ViewGroup,第二个传入的是一个非常重要的回调,这个后面会深入研究;
2.拦截事件:
拦截ViewGroup的onInterceptTouchEvent
和onTouchEvent
3.处理computScroll():
一般都是这个模板
@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
4.处理回调callback:
ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {}
里面几个主要的回调方法:
public boolean tryCaptureView(View child, int pointerId) {}:
设置何时开始检测触摸事件,比如指定只有触摸的某一个child的时候才会检测。
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {}:
此时已经开始滚动,这个里面可以进行一些视图位置的改变,动画效果的添加等。
public int getViewVerticalDragRange(View child) {}:
设置垂直方向拖动的范围。
public int clampViewPositionVertical(View child, int top, int dy) {}:处理垂直方向的滑动。
public void onViewReleased(View releasedChild, float xvel, float yvel) {}:
拖动结束后的处理。