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)
;
}
2)GestureDetector
用于手势检测,检测用户的点击、滑动、长按、双击等行为。
private void
initializeView
() {
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()
;
}
}
}
/**
* 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()
;
}
}
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()
;
}
可以利用动画来模仿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()
;
}
});