ScrollTo(x,y):滑动到某个位置,传递的是位置的坐标
ScrollBy(x,y):滑动某个距离,传递的是移动过的距离
同时这两个方法移动的是view中的内容,而不是view本身,比如作用于Layout,将会移动的是layout中button的位置。从理解上来说,可以理解为画布在移动。
可以通过如下代码调用ObjectAnimator来实现动画滑动效果,这里给出简单的实例代码,详细代码参见本人的另一篇博客
ObjectAnimator.ofFloat(targetView,"translationX",0,100).setDuration(100).start();
一般我们可以改变一个view的布局来对它进行移动,如果想把一个button向右移动100px,只需要将这个Button的LayoutParams里的marginLeft参数的值增加100px即可。示例代码如下:
MarginLayoutParams params = (MarginLayoutParams)mButton1.getLayoutParams();
params.width += 100;
params.leftMargin += 100;
mButton1.requestLayout();
//或mButton1.setLayoutParams(params);
Scroller scroller = new Scroller(mContext);
//缓慢滑动到指定的位置
private void smothScrollTo(int destX,int destY){
int scrollX = getScrollX();
int delta = destX - scrollX;
mScroller.startScroll(scrollX,0,delta,0,1000);
invalidate();
}
@Override
public void computeScroll(){
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.etCurrX(),mScroller.getCurrY());
postInvalidate();
}
}
利用动画本身的间隔时间来完成
ObjectAnimator.ofFloat(TargetView,"translationX",0,100).setDuration(100).start();
利用监听动画更新的方法实现移动
ValueAnimator animator = ValueAnimator.ofInt(0,1).setDuration(1000);
animator.addUpdateListeneer(new AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animator){
float fraction = animator.getAnimatedFraction();
mButton1.scrollTo(startX + (int) (deltaX*fraction),0);
}
});
animator.start();
实现原理是通过发送一系列的延时消息,从而达到渐变的效果。实际上就是通过while不断发消息和睡眠,从而达到动画效果。
private static final int MESSAGE_SCROLL_TO = 1;
private static final int FRAME_COUNT = 30;
private static final int DELAYED_TIME=33;
private int mCount = 0;
private Handler mHandler = new Handler(){
public void handleMEssage(Message msg){
switch(msg.what){
case MESSAGE_SCROLL_TO:{
mCount++;
if(mCount <= FRAME_COUNT{
float fraction = mCount/(float)FRAME_COUNT;
int scrollX = (int) (fraction*100);
mButton1.scrollTo(scrollX,0);
mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO,
DELATED_TIME);
}
break;
}
default:
break;
};
};
}
事件分发机制就是其实就是对MotionEvent事件的分发过程。即当一个MotionEvent(点击事件)产生后,系统需要把这个事件传递给一个具体的view进行处理,这个过程就是事件的分发过程。
事件分发过程由三个很重要的方法来共同完成:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent
事件进入当前view调用的第一个方法,用来进行事件分发。返回结果受到当前view的onTouchEvent方法和下级view的dispatchTouchEvent的方法的影响,表示是否消耗当前事件。
在disPatchTouchEvent方法的内部调用,用来判断是否拦截当前事件。如果拦截则执行onTouchEvent方法,否则执行下级view的dispatchTouchEvent方法。
用来处理点击事件中的各种方法,返回结果便是是否消耗当前的点击事件。如果不消耗,则在同一个事件序列中,当前view无法再次接收到事件。
public voolean dispatchTouchEvent(MotionEvent ev){
boolean consume = false;
if(onInterceptTouchEvent(ev)){//判断是否拦截事件
consume = onTouchEvent(ev);//是否消耗当前事件
}else{
consume = child.dispatchTouchEvent(ev);//子事件处理
京东
return consume;//返回false会调用父控件的onTouchEvent方法
}
OnTouchListener>onTouchEvent>onClickListener
1、事件序列:从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程中产生的一系列事件。
2、一个事件序列真能被一个view拦截且消耗。除非在onTouchEvent中强行传递给其它view
3、如果view的onTouchEvent返回false,则事件不会向下传递,而会调用父控件的onTouchEvent方法进行处理。
4、如果view只消耗ACTION_DOWN事件,那么这个点击事件的其他后续事件会返回给Activity进行处理。
5、ViewGroup默认不拦截任何事件。
6、非ViewGroup的View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它就会执行onTouchEvent方法。
7、非ViewGroup的View会默认消耗onTouchEvent,除非把clickable和longclickable同时设置为false。
8、onClick发生情况必须是当前view是可点击的,并且它收到了down和up事件。