[读书笔记之安卓开发艺术探索]View的事件体系前的知识准备

来源:互联网 发布:飞车雷诺全29数据测试 编辑:程序博客网 时间:2024/06/09 20:02

零碎的知识

View的位置参数

  • x,控件左上角在父容器中的x坐标像素值
  • y,控件左上角在父容器中的y坐标像素值
  • translationX,存在平移过程,控件在x轴上偏移的像素值
  • translationY,存在平移过程,空间在y轴上偏移的像素值
  • left,控件左上角在父容器中横坐标的像素值
  • right,控件左上角在父容器中纵坐标的像素值
  • top,控件右下角在父容器中横坐标的像素值
  • bottom,控件右下角在父容器中横坐标的像素值
  • scrollX,控件在x轴上滑动的长度(px)
  • scrollY,控件在y轴上滑动的长度(px)

存在如下关系如下:
x = left + translationX;
y = right = translationY;
scrollX = getScrollX;
scrollY = getScrollY;

TouchSlop

表示系统所能识别的最小滑动距离。通过以下方法获取:

ViewConfiguration.get(getContext()).getScaledTouchSlop()

VelocityTracker

用于跟踪手指在滑动过程中的速度,包括水平和竖直方向的速度。获取如下所示

VelocityTracker velocityTracker = VelocityTracker.obtain();velocityTracker.addMovement(motionEvent);velocityTracker.computeCurrentVelocity(1000);float x = velocityTracker.getXVelocity();float y = velocityTracker.getYVelocity();velocityTracker.clear();velocityTracker.recycle();

GestureDetector

如果只是坚挺滑动相关,倾向于在onTouchEvent中实现,如果要监听双击这样的行为,就是用GestureDetector

Scroller的使用

用于实现View的弹性滑动,配合在自定义View中重写ComputeScroll方法来共同达到这一功能。比如自定义一个线性布局,调用smoothScrollBy方法实现平滑滚动,代码如下:

public class ScrollerLinearLayout extends LinearLayout {public static final String TAG = "ScrollerLinearLayout";private Scroller mScroller;public ScrollerLinearLayout(Context context) {    super(context);    mScroller = new Scroller(context);}public ScrollerLinearLayout(Context context, AttributeSet attrs) {    super(context, attrs);    mScroller = new Scroller(context);}public void smoothScrollTo(int dstX,int dstY){    int dx = dstX - mScroller.getFinalX();    int dy = dstY - mScroller.getFinalY();    smoothScrollBy(dx,dy);}public void smoothScrollBy(int dx,int dy,int duration){    //上一次的最后位置作为本次重绘的开始位置,故调用getFinalX方法而不是getStartX方法    mScroller.startScroll(mScroller.getFinalX(),mScroller.getFinalY(),dx,dy,duration);    invalidate();}@Overridepublic void computeScroll() {    if(mScroller.computeScrollOffset()){        int currX = mScroller.getCurrX();        int currY = mScroller.getCurrY();        scrollTo(currX,currY);        postInvalidate();    }    super.computeScroll();}}

View的滑动

实现方式

使用scrollTo和scrollBy

scrollBy实际上是调用scrollTo方法,它实现了基于当前位置的相对滑动,而scrollTo实现了基于所传递的参数的绝对滑动。

滑动过程中,有两个属性值:mScrollX,mScrollY
通过getScrollX和getScrollY方法分别得到
mScrollX表示View左边缘到内容左边水平方向的距离
mScrollY表示View上边缘到内容上边竖直方向的距离

因此,scrollTo和scrollBy智能改变View的内容位置而不能改变View在布局中的位置。需要注意的是,使用scrollBy滑动,如果从左到右滑动,mScrollX为负值,从上往下滑动,mScrollY为负值。(前一个值减去后一个值)

使用动画

通过动画,我们能够让一个View进行平移,而平移就是一种滑动。通过操作View的translationX和translationY属性(因此View的平移,是在其父容器中移动),补间动画或属性动画都可以实现效果。

使用动画来做View的滑动需要注意的事项
补间动画是对View的映像做操作,它并不能真正改变View的位置参数,包括宽/高(如果需要View保留最后的动画状态,fillAfter置为true),因为View对应的位置信息(top,left,right,button)并没有改变,改变的只是translationX,translationY,x,y的值,而点击事件的位置根据View的位置信息来操作。对比属性动画,它是通过改变属性形成的动画,但是属性动画也存在不足,它只适用在Android 3.0以上。

改变布局参数

改变LayoutParams。

比如如果想让一个Button右移100px

  • LayoutParams里让marginLeft参数值为100px即可。
  • 在Button左边放置一个空的View,这个空View默认宽度为0,慢慢增加View的宽度,Button根据父容器的对齐方式,挤向另一边。

涉及到的API: ViewGroup.LayoutParams,ViewGroup.MarginLayoutParams

弹性滑动

将一次大的滑动分成若干次小的滑动并在一个时间段内完成。实现方式有:Scroller;Handler&postDelay;Thread&sleep。

使用Scroller

工作机制

当我们构造一个Scroller对象并且调用startScroll方法时,Scroller内部其实什么也没做,它只是保存了我们传递的参数。invalid方法会导致View重新绘制,即调用draw方法,draw方法里会调用computeScroll方法,这个方法需要我们去重写,在该方法里,调用scroller.computeScrollOffset方法,这个方法内部有时间因子(时间插值器),得到当前滑动的currX和currY,然后通过scrollTo方法实现滑动,接着又调用postInvalide方法进行第二次重绘。第二次重绘和第一次重绘过程一样。如此循环,直到滑动结束,computeScrollOffSet返回false。

通过动画

动画具有天然的弹性滑动

借鉴Scroller机制,通过ValueAnimator的onAnimationUpdate方法里,引入时间因子(Fraction)获取到每时每刻滑动的偏移量,再配合scrollTo/scrollBy,来完成也行。

使用延时策略

通过发送一系列延时的消息从而达到一种渐进式的效果。
具体实现方法:

  • 使用Handler或View的postDelayed方法。
  • while循环加sleep
1 0