View是android系统中所有控件的基类,是一种界面层空间的抽象。
下面开始介绍view的基本api
1.view的位置参数
相对父容器位置坐标
Left=getLeft();
Right=getRight();
Top=getTop();
bottom=getBottom();
可以通过以上方法得出view的宽高
width=right-left
height=top-bottom
2.MotionEvent和TouchSlop
1)MotionEvent
- ACTION_DOWN-手指刚接触屏幕
- ACTION_MOVE-手指在屏幕上移动
- ACTION_UP-手指从屏幕上松开的一瞬间
通过MotionEvent对象可以得到点击事件发生的x和y坐标
系统提供两个方法getX/getY和getRawX/getRawY
区别:getX/getY返回当前view上的x和y坐标
getRawX/getRawY相对于手机屏幕的x和y坐标
2)TouchSlop
TouchSlop是系统所能识别出滑动的最小距离。这是一个常量,具体的值和设备有关系
ViewConfiguration.get(
this
).getScaledTouchSlop()
;
3.VelocityTracker、GestureDetector和Scroller
1)VelocityTracker
用于追踪手指滑动过程中的速度
long
tmp
;
@Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction()){
case MotionEvent. ACTION_DOWN :
Trace.e( "ACTION_DOWN" ) ;
tmp =System.currentTimeMillis() ;
break;
case MotionEvent. ACTION_MOVE :
velocityTracker .addMovement(event) ;
// Trace.d("ACTION_MOVE:x="+event.getX()+",y="+event.getY());
break;
case MotionEvent. ACTION_UP :
Trace.e( "ACTION_UP" ) ;
long during=System.currentTimeMillis()- tmp ;
velocityTracker .computeCurrentVelocity(( int ) during) ;
int xVelocity= ( int ) velocityTracker .getXVelocity() ;
int yVelocity= ( int ) velocityTracker .getYVelocity() ;
Trace.e( "xVelocity:" +xVelocity+ ",yVelocity" +yVelocity) ;
break;
default :
break;
}
return super .onTouchEvent(event) ;
@Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction()){
case MotionEvent. ACTION_DOWN :
Trace.e( "ACTION_DOWN" ) ;
tmp =System.currentTimeMillis() ;
break;
case MotionEvent. ACTION_MOVE :
velocityTracker .addMovement(event) ;
// Trace.d("ACTION_MOVE:x="+event.getX()+",y="+event.getY());
break;
case MotionEvent. ACTION_UP :
Trace.e( "ACTION_UP" ) ;
long during=System.currentTimeMillis()- tmp ;
velocityTracker .computeCurrentVelocity(( int ) during) ;
int xVelocity= ( int ) velocityTracker .getXVelocity() ;
int yVelocity= ( int ) velocityTracker .getYVelocity() ;
Trace.e( "xVelocity:" +xVelocity+ ",yVelocity" +yVelocity) ;
break;
default :
break;
}
return super .onTouchEvent(event) ;
}
2)GestureDetector
用于手势检测,检测用户的点击、滑动、长按、双击等行为。
private void
initializeView
() {
mGestureDetector = new GestureDetector( this ) ;
mGestureDetector = new GestureDetector( this ) ;
mGestureDetector.setIsLongpressEnabled(false);
}
3.Scroller 弹性滑动对象
实现view滑动的三种方式
1)使用scrollTo/scrollBy
view提供两种方法实现滑动效果
/**
* Set the scrolled position of your view. This will cause a call to
* {@link#onScrollChanged( int , int , int , int )} and the view will be
* invalidated.
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
public void scrollTo ( int x , int y) {
if ( mScrollX != x || mScrollY != y) {
int oldX = mScrollX ;
int oldY = mScrollY ;
mScrollX = x ;
mScrollY = y ;
invalidateParentCaches() ;
onScrollChanged( mScrollX , mScrollY , oldX , oldY) ;
if (!awakenScrollBars()) {
postInvalidateOnAnimation() ;
}
}
* Set the scrolled position of your view. This will cause a call to
* {@link#onScrollChanged( int , int , int , int )} and the view will be
* invalidated.
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
public void scrollTo ( int x , int y) {
if ( mScrollX != x || mScrollY != y) {
int oldX = mScrollX ;
int oldY = mScrollY ;
mScrollX = x ;
mScrollY = y ;
invalidateParentCaches() ;
onScrollChanged( mScrollX , mScrollY , oldX , oldY) ;
if (!awakenScrollBars()) {
postInvalidateOnAnimation() ;
}
}
}
/**
* Move the scrolled position of your view. This will cause a call to
* {@link#onScrollChanged( int , int , int , int )} and the view will be
* invalidated.
* @param x the amount of pixels to scroll by horizontally
* @param y the amount of pixels to scroll by vertically
*/
public void scrollBy ( int x , int y) {
scrollTo( mScrollX + x , mScrollY + y) ;
* Move the scrolled position of your view. This will cause a call to
* {@link#onScrollChanged( int , int , int , int )} and the view will be
* invalidated.
* @param x the amount of pixels to scroll by horizontally
* @param y the amount of pixels to scroll by vertically
*/
public void scrollBy ( int x , int y) {
scrollTo( mScrollX + x , mScrollY + y) ;
}
从源码可以看出scrollBy其实内部就是调用了scrollTo方法
两个方法的区别:scrollBy实现了基于当前位置的滑动,scrollTo实现基于传进参数的绝对滑动
注意scrollBy和scrollTo并不能改变view在布局中的位置,只能改变
mScrollX,
mScrollY
如何让view动起来?
调用view的invalidate方法 会导致view的draw方法被调用 draw方法在去调用computeScroll
@Override
public void computeScroll () {
if ( mScroller .computeScrollOffset()) {
scrollTo( mScroller .getCurrX() , mScroller .getCurrY()) ;
postInvalidate() ;
}
public void computeScroll () {
if ( mScroller .computeScrollOffset()) {
scrollTo( mScroller .getCurrX() , mScroller .getCurrY()) ;
postInvalidate() ;
}
}
postInvalidateI()方法进行二次重绘和第一次重绘一样,还是会调用computeScroll 然后继续获取当前scrollX和scrollY,如此反复,直到整个滑动过程结束
2)使用动画
可以使用动画效果来实现view的滑动
动画操作的是view的translationX和
translationY两个属性(view的绝对位置)
实现方式:可以采用view的传统动画和(v3.0)属性动画(为了能兼容3.0以下版本需要采用兼容库nineoldandroids)
下面我们来实现一个动画场景:
view在100ms内向右平移100像素
@Override
public void onClick (View v) {
float x=findViewById(R.id. mAnimalBtn ).getX() ;
ObjectAnimator.ofFloat(findViewById(R.id. mAnimalBtn ) , "translationX" , x , x+ 100 ).setDuration( 100 ).start() ;
public void onClick (View v) {
float x=findViewById(R.id. mAnimalBtn ).getX() ;
ObjectAnimator.ofFloat(findViewById(R.id. mAnimalBtn ) , "translationX" , x , x+ 100 ).setDuration( 100 ).start() ;
}
可以利用动画来模仿Scroller实现view的弹性滑动
mAnimalBtn
= (Button) findViewById(R.id.
mAnimalBtn
)
;
final int startX = 0 ;
final int deltaX = 100 ;
final ValueAnimator animator = ValueAnimator.ofInt( 0 , 1 ).setDuration( 1000 ) ;
animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate (ValueAnimator animation) {
float fraction = animation.getAnimatedFraction() ;
mAnimalBtn .scrollTo(( int ) ( startX + deltaX * fraction) , 0 ) ;
}
}) ;
mAnimalBtn .setOnClickListener( new View.OnClickListener() {
@Override
public void onClick (View v) {
animator .start() ;
}
final int startX = 0 ;
final int deltaX = 100 ;
final ValueAnimator animator = ValueAnimator.ofInt( 0 , 1 ).setDuration( 1000 ) ;
animator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate (ValueAnimator animation) {
float fraction = animation.getAnimatedFraction() ;
mAnimalBtn .scrollTo(( int ) ( startX + deltaX * fraction) , 0 ) ;
}
}) ;
mAnimalBtn .setOnClickListener( new View.OnClickListener() {
@Override
public void onClick (View v) {
animator .start() ;
}
});