Android View

View基础知识

View的位置参数:

top、left、right、bottom,分别对应View的左上角和右下角相对于父容器的横纵座标值。从Android 3.0开始,view增加了x、y、translationX、translationY四个参数,这几个参数也是相对于父容器的座标。x和y是左上角的座标,而translationX和translationY是view左上角相对于父容器的偏移量,默认值都是0。

这里写图片描述
这几个参数的换算公式:
x=left+translationX
y=top+translation

View在平移过程中,top和left表示原始左上角的位置信息,其值并不会发生改变

MotionEvent和TouchSlop

MotionEvent是指手指接触屏幕后所产生的一系列事件,主要有ACTION_UP、ACTION_DOWN、ACTION_MOVE等。
正常情况下,一次手指触屏会触发一系列点击事件,主要有下面两种典型情况:

  • 点击屏幕后离开,事件序列是ACTION_DOWN->ACTION_UP;
  • 点击屏幕后滑动一会再离开,事件序列是ACTION_DOWN->ACTION_MOVE->ACTION_MOVE-> … ->ACTION_UP;

TouchSlope是系统所能识别出的可以被认为是滑动的最小距离,获取方式是

ViewConfiguration.get(getContext()).getScaledTouchSlope()。

VelocityTracker

VelocityTracker用于追踪手指在滑动过程中的速度,包括水平和垂直方向上的速度。速度可能为负值,例如当手指从屏幕右边往左边滑动的时候。此外,速度是单位时间内移动的像素数,单位时间不一定是1秒钟,可以使用方法computeCurrentVelocity(xxx)指定单位时间是多少,单位是ms。例如通过computeCurrentVelocity(1000)来获取速度,手指在1s中滑动了100个像素,那么速度是100,即100(像素/1000ms)。如果computeCurrentVelocity(100)来获取速度,在100ms内手指只是滑动了10个像素,那么速度是10,即10(像素/100ms)。

使用步骤:
1.获取VelocityTracker实例:

VelocityTracker mVelocityTracker = VelocityTracker.obtain();

2.将MotionEvent事件纳入到VelocityTracker中:

mVelocityTracker.addMovement(event);

3.计算瞬时速度:

mVelocityTracker.computeCurrentVelocity(units,maxVelocity);

4.获取xy方向上的速度:

float vX = mVelocityTracker.getXVelocity(pointId);
float vY = mVelocityTracker.getYVelocity(pointId);

5.回收VelocityTracker:

mVelocityTracker.clear();
mVelocityTracker.recycle();

6.使用示例:

/**
     * 获取速度追踪器
     * @return
     */
    private VelocityTracker getVelocityTracker()
    {
        if(mVelocityTracker == null)
        {
            mVelocityTracker = VelocityTracker.obtain();
        }
        return mVelocityTracker;
    }

    /**
     * 回收速度追踪器
     */
    private void recycleVelocityTracker()
    {
        if(mVelocityTracker != null)
        {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //1.获取速度追踪器
        getVelocityTracker();
        //2.将当前事件纳入到追踪器中
        mVelocityTracker.addMovement(event);

        int pointId = -1;

        switch (event.getAction())
        {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG,"ACTION_DOWN");
            pointId = event.getPointerId(0);
            break;
        case MotionEvent.ACTION_MOVE:
            Log.i(TAG,"ACTION_MOVE");
            //3.计算当前速度
            mVelocityTracker.computeCurrentVelocity(1000,mMaxFlingVelocity);
            //获取x y方向上的速度
            float vX = mVelocityTracker.getXVelocity(pointId);
            float vY = mVelocityTracker.getYVelocity(pointId);
            Log.i(TAG,"vX = "+vX+",vY = "+vY);
            break;

        case MotionEvent.ACTION_UP:
            Log.i(TAG,"ACTION_UP");
            //4.回收速度追踪器
            recycleVelocityTracker();
            break;
        default:
            break;
        }
        return super.onTouchEvent(event);
    }

GestureDetector

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

  • 首先需要实现GestureListener接口
mGestureDetector = new GestureDetector(this, new GestureScrollListener());
  • 在TouchEvent方法中接管手势
 mGestureDetector.onTouchEvent(ev)

View的滑动

常见的实现view的滑动的方式有三种:

  • 1.通过view本身提供的scrollTo和scrollBy方法:操作简单,适合对view内容的滑动;
  • 2.通过动画给view施加平移效果来实现滑动:操作简单,适用于没有交互的view和实现复杂的动画效果;
  • 3.通过改变view的LayoutParams使得view重新布局从而实现滑动:操作稍微复杂,适用于有交互的view

scrollTo和scrollBy

  • scrollTo(int x, int y) 是将View中内容滑动到相应的位置
  • scrollBy(int x, int y)其实是对scrollTo的包装,移动的是相对的位置

scrollTo和scrollBy源代码:

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();  
        }  
    }  
} 
public void scrollBy(int x, int y) { 
    scrollTo(mScrollX + x, mScrollY + y);
}  

使用动画

  • 使用动画来移动view主要是操作view的translationX和translationY属性,既可以使用传统的view动画,也可以使用属性动画。
  • 使用动画还存在一个交互问题:在android3.0以前的系统上,view动画和属性动画,新位置均无法触发点击事件,同时,老位置仍然可以触发单击事件。从3.0开始,属性动画的单击事件触发位置为移动后的位置,view动画仍然在原位置。
  • 动画兼容库nineoldandroids中的ViewHelper类提供了很多的get/set方法来为属性动画服务,例如setTranslationX和setTranslationY方法,这些方法是没有版本要求的。
    ViewHelper.getTranslationX(view);
    ViewHelper.setTranslationY(view,100);
    ViewHelper.setTranslationX(view,100);

改变布局参数

通过params来设置margin改变位置

Scroller

  • Scroller:弹性滑动对象
  • v4中ScrollerCompat类兼容库
  • 需要computeScroll配合更新位置

执行滑动:

 mScroller.startScroll( startX, startY,dx, dy, duration);

控制滑动这个流程:

@Override
 public void computeScroll() {
        super.computeScroll();
        // 判断Scroller是否执行完毕
        if (mScroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo( mScroller.getCurrX(), mScroller.getCurrY());
            // 通过重绘来不断调用computeScroll
            invalidate();//很重要
        }
    }

computeScroll:主要功能是计算拖动的位移量、更新背景、设置要显示的屏幕(setCurrentScreen(mCurrentScreen);)。

重写computeScroll()的原因:

调用startScroll()是不会有滚动效果的,只有在computeScroll()获取滚动情况,做出滚动的响应

computeScroll在父控件执行drawChild时,会调用这个方法

发布了46 篇原创文章 · 获赞 23 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章