Android View的事件体系
view的基本属性
以下各个属性可以通过get方法获取
- top
view的左上角纵坐标 - bottom
view的右下角纵坐标 - left
view的左上角横坐标 - right
view的右下角横坐标 - translationX
view在横坐标上的偏移量 - translationY
view在纵坐标上的偏移量 - x
view的左上角的横坐标 - y
view的左上角的纵坐标
其中 x = left + translationX;y = top + translationY;
实现view滑动的三种方式
- view自带的scrollTo和scrollBy方法(对view内容滑动)
scrollTo是绝对位置的滑动,而scrollBy是相对于当前位置滑动,且其滑动时瞬间执行的。
其原理是改变mScrollX,和mScrollY属性,使其重绘。且其会触发onScrollChanged
scrollBy是计算相对位置对应的绝对位置的坐标然后调用scrollTo方法实现的
源码如下
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();
}
}
}
-
使用动画(本体位置不变,需要交互时不推荐)
使用动画可以使view位置改变,如translate位移动画 -
修改LayoutParams的值(适用于需要交互的view)
由于所有的ViewGroup的LayoutParams都是继承MarginLayoutParams,我们可以将view的LayoutParams直接强转为MarginLayoutParams,然后修改margin值
弹性滑动
- Scroller
scroller使用中需要重写view的computeScroll方法,在里面进行一个滑动操作
//首先创建一个Scroller
Scroller scroller = new Scroller(getContext());
//需要滑动的时候调用startScroll方法,并且通知view重绘
scroller.startScroll(getScrollX(),getScrollY(),getScrollX()+100,getScrollY()+100,1000);
invalidate();
//重写view的computeScroll方法
public void computeScroll() {
if(scroller.computeScrollOffset())//如果计算成功
{
scrollTo(scroller.getCurrX(),scroller.getCurrY());//滑动
postInvalidate();//继续重绘
}
}
- 动画
由于ValueAnimator会不断计算当前值给我们,我们可以使用它实现类似于Scroller的效果,且无需重写computeScroll方法 - 延时策略
使用handler的sendEmptyMessageDelay方法即可实现
一些杂乱的api以及注意事项
获取手指移动的速度
VelocityTracker tracker = VelocityTracker.obtain();
tracker.addMovement(event);//event是MotionEvent对象
//获取速度之前需要计算,参数表示时间
//计算公式为(开始位置-结束位置)/时间
tracker.computeCurrentVelocity(1000);
LogUtil.d(tracker.getXVelocity());
LogUtil.d(tracker.getYVelocity());
//使用完毕后务必清理
tracker.clear();
tracker.recycle();
手势识别
其实现有些问题存在,如OnScroll实现跟随手指移动会卡顿
//当前类要实现OnGestureListener,如果需要可以实现OnDoubleTapListener
GestureDetector detector = new GestureDetector(this);
//然后在onTouchEvent或者OnTouchListener中将事件代理给detector
return detector.onTouchEvent(event);
//需要注意的是在重写各方法时需要按需求返回true,不然后续事件无法触发
Android动画注意点
如果需要旋转动画围绕自己某个点旋转,pivotX,pivotY需要使用百分比,如下:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="1000"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="180"
/>