View的事件体系(上)(View基础知识,滑动,弹性滑动)

View不是四大组件之一,但重要性堪比四大组件,本篇博文主要讲解View的事件体系,包括View的基础知识,滑动,弹性滑动,事件分发机制,滑动冲突的种类与解决方案。

一 View的基础知识

(1).View 的位置参数

View的位置主要由它的四个顶点来决定,分别对应于View的四个属性:top,left,right,bottom。从android3.0开始 View增加了额外的几个参数:x,y,translationX,和translationY

x= left + translationX

y=top +translationY

(2).MotionEvent 和 TouchSlop

1.MotionEvent

在手指接触屏幕后所产生的一系列事件中,典型的事件类型有如下几种:

A.ACTION_DOWN  : 手指刚接触屏幕

B.ACTION_MOVE   : 手指在屏幕上移动

C.ACTION_UP   : 手指离开屏幕的一瞬间

 

正常情况下,一次手指触摸屏幕的行为会触发一系列点击事件,例如:

A. 点击屏幕后离开,事件序列为DOWN->UP;

B. 点击屏幕滑动一会松开,事件序列为DOWN->MOVE->...->MOVE->UP;

 

通过MotionEvent的对象我们可以得到点击事件发生的xy坐标。因此,系统系统提供了两组方法:getX/getYgetRawX/getRawY。它们的区别很简单,getXgetY返回的是相当于当前View左上角的xy坐标,getRawXgetRawY返回的是相对于手机屏幕左上角的xy坐标。

 

2.TouchSlop

TouchSlop是系统所能识别出的被认为是滑动的最小距离。当我们在处理滑动时,就可以利用这个常量做一些过滤,比如当两次滑动事件的滑动距离小于这个值,我们就可以认为未滑动。

 

 

3.VelocityTracker,GestureDetector Scroller

a) VelocityTracker是速度追踪,用户追踪手指在滑动过程中的速度,包括水平和竖直方向的速度。他的使用很简单,首先,在ViewonTouchEvent方法中追踪当前单机事件的速度:

VelocityTracker vt=VelocityTracker.obtain();

vt.addMovement(event);

 

接着就想知道当前的滑动速度时,就可以采用这个方式来获得速度:

vt.computeurrentVelocity(100);//100表示时间间隔为100 ms

Int x=(int)vt.getXVelovity();

Int y=(int)vt.getYVelovity();

当不需要使用它的时候,用clear方法来重置回收内存:

vt.clear();

vt.recycle();
b) GestureDetector

手势检测,用于辅助检测用户的单击,滑动,长按,双击等行为。

首先,我们创建一个GestureDetector 对象并实现onGestureListener接口,根据需要我们还可以实现onDoubleTapListener从而能够监听双击行为:

GestureDetector mGestureDetector =new GestureDetector(this);

//解决长按屏幕无法拖动的现象

mGestureDetector.setIsLongPressEnable(false);

 

接着实现目标ViewonTouchEvent方法,在待监听的ViewonTouchEvent方法中添加如下实现:

Boolean consume=mGestureDetector.onTouchEvent(event);

做完上两步,我们就可以有选择地实现OnGestureListenerOnDoubleTapListenter中的方法了。另外,在实际开发中,我们可以不使用GestureDetector,完全可以自己在ViewonTouchEvent方法中实现所需的监听,当需要监听双击这种行为时,再使用GestureDetector.

 

(c).Scroller

弹性滑动对象,用于实现View的弹性滑动。我们知道,当使用ViewscrollTo/scrollBy方法进行滑动时,其过程是可以瞬间完成的,这个没有过渡效果的滑动用户体验不好。这个时候,我们就可以使用Scroller来实现由过渡效果的滑动,其过程不是瞬间完成的,而是在一定时间间隔内完成的。Scroller配合viewcomputeScroll就能完成这个功能。它的典型代码固定如下:

Scroller scroller =new Scroller(mContext);

 

Private void smoothScrollTo(int destX,int destY) {

Int scrollX=getScrollX();

Int delta = destX - scrollX;

 

mSroller.startScroll(scrollX,0delta,0,1000);

Invalidate();

}

@Override

Public void computeScroll(){

If(mSroller.computeScrollOffset()) {

scrollTo(mScroller.getCurrX().mScroller.getCurrY());

postInvalidate();

}

}

 

 

二 View的滑动

不管一些滑动效果多么绚丽,归根到底,他们都是由不同的滑动外加一些特效所组成的。因此。掌握滑动的方法是实现绚丽的自定义控件的基础。通过三种方式可以实现View的滑动第一种事通过View 本身提供的scrollTo/scrollBy 方法来实现滑动;第二种是通过动画给View施加平移来实现滑动;第三种是通过改变ViewLayoutParams使得View重新布局从而实现滑动。下面,我们一一对其进行讲解。

 

(1).使用scrollTo/scrollBy

为了实现View的滑动,View提供了专门的方法来实现这个功能。那就是scrollTo/scrollBy。经过分析源码得知,scrollBy实际上也是调用了scrollTo方法,而scrollTo则实现了基于所传递参数的绝对滑动。利用scrollToscrollBy来实现View的滑动,这不困难,但我们要知道。滑动过程中,View内部的两个属性mScrollXmScrollY的改变规则。这两个属性可以通过getScrollXgetScrollY方法分别得到。

 

在滑动过程中,mScrollX的值总是等于View左边缘和View内容左边缘在水平方向上的距离,而mScrollY的值,总是等于View上边缘和View内容上边缘的竖直方向的距离。scrollToscrollBy只能改变View的内容的位置,而不能改变View在布局中的位置。mScrollXmScrollY的单位是像素,并且当View左边缘在View内容左边缘右边时,mScrollX为正值,反之为负值。当View上边缘在View内容上边缘的下边时,mScrollY为正值,反之为负值。换句话说,如果从左向右滑动,那么mScrollX为负值,反之为正值。如果从上往下滑动,mScrollY为负值,反之为正值。

 

(2).使用动画

使用动画来移动View,主要操作ViewtranslationXtranslationY属性,即可以使用传统的View动画来完成,也可以采用属性动画,如果采用属性动画的话,为了兼容3.0一下版本,需要采用开源动画库nineoldandroidshttp://nineoldandroids.com/

使用传统的View动画,可以xml中的指定translate,采用属性动画,更简单了,比如:

ObjectAnimator.ofFloat(targetView,”translationX”,0,100).setDuration(100).start();

 

具体更多的动画使用方法,我会接下来的博文中单独列出来一篇讲解动画,这里就先不详述了。

需要注意的一点是,View动画是对View的影像的操作,它并不能真正改变View的位置包括宽/高,造成View无法响应点击事件,因为View的真身还在原来的位置,并且如果希望动画后的状态得以保留。还必须将fillAfter的属性设置为true,否则动画完成后,其动画效果就会消失。

 

(3).改变布局参数

改变布局参数,即改变LayoutParams比较好理解,比如我们想把一个Button向右平移100px,我们主要将这个ButtonLayoutParams里的marginLeft参数的值增加100px即可。

MarginLayoutParams params = (MarginLayoutParams )mButton1.getLayoutParams();

Params.width +=100;

params.leftMargin +=100;

mButton1.requestLayout();

//或者 mButton1.setLayoutParams(params);

 

          (4).各种滑动方式对比

 

1.scrollTo/scrollBy:操作简单。适合View滑动,滑动后支持响应事件。

2.动画:操作简单,主要适用于没有交互的View和实现复杂的动画效果。推荐使用nineoldandroids兼容android 3.0以下版本。

3.改变布局参数:操作稍微复杂,适用于有交互的Veiw.

 

 

 

三 弹性滑动

如果View生硬的滑动过去,用户体验实在太差,因此。我们要实现渐进式滑动。渐进式滑动有一个共同思想:将依次大的滑动分成若干次小的滑动,并在一个时间段内完成。常用的弹性滑动方式有Scroller,使用动画,还有延时策略。下面我们一一讲解

 

(1) .使用Scroller

Scroller方法已经分析过了,如果有有兴趣可以分析它的源码。原理如下:

invalidate方法会导致View重绘,在Viewdraw方法中,又会去调用computeScroll方法。

(2) .通过动画

动画本身就是一种渐进过程,因此通过它来实现滑动天然就具有弹性效果,比如下面代码可以让一个View的内容在100ms内向左移动100ms.

ObjectAnimator.ofFloat(targetView”translationX”,0,100).setDuration(100).start();不过这里想说的并不是这个问题,我们可以利用动画特性来实现一些动画不能实现的效果。还拿scrollTo来说,我们也想模仿Scroller来实现View的弹性滑动。那么利用动画的特性。我们可以采用如下方式来实现。

Final int startX=0;

Final int deltax=100;

valueAnimator animator = ValueAnimator.ofInt(0,1).setDuration(1000);

animator.addUpdateListener(new AnimatorUpdateListener(){

@Override

public void onAnimatorUpdate(ValueAnimator animator){

Float fraction=animator.getAnimatedFraction();

mButton1.scrollTo(startX+(int)(deltaX*fraction),0)

 

}

 

});

animator.start();

上述代码,我们的动画本质上没有作用于任何对象上,它只是在1000ms内完成了整个动画过程。利用这个特性,我们就可以在动画的每一帧到来时获取动画完成比例,然后再根据这个比例计算当前View的滑动距离。注意,这里的滑动特性针对的是View的内容而非View本身。它与Scroller比较类似,都是通过改变一根百分比配合scrollTo方法来完成View的滑动。需要说明一点,采用这种方法除了能够完成弹性滑动以外,还可以实现其动动画效果,我们可以在onAnimationUpdate方法中加上我们想要的操作。

 

 

(3) .使用延时策略

 

延时策略的核心思想是通过发送一系列延时消息,从而达到渐进式的效果,具体来说,可以使用Handler ViewpostDelayed方法,也可因使用线程的sleep方法。使用起来比较简单,就不举例子了。

 

 

讲了这么多,还都是基础知识,将这篇文章,设为View事件体系的上篇吧,在下篇中,我们再去事件分发机制,滑动冲突的结局方案。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值