View系列笔记(一)----基础概念知识

[TOC]

声明:此系列的部分内容出自《Android开发艺术探索》一书,是我当初学习时候的一些笔记和总结,在这里留个记录。
  View是android中所有控件的基类。

位置参数

在Android系统中,左上角为坐标原点,x和y轴正方向分别是往右和下。View的位置由它的4个顶点来决定,即top,left,right,bottom。需要注意的是这4个点是相对坐标,相对于view的父容器来说的。获取方法:

  • top: getTop()
  • left: getLeft()
  • right: getRight()
  • bottom: getBottom()

从Android3.0开始,View增加了4个额外的参数:x,y,translationX,translationY。其中x和y指view左上角的坐标,translationX和translationY指view左上角相对于父容器的偏移量。这4个参数也都是相对坐标,他们之间的相互关系如下:

  • x = left + translationX;
  • y = top + translationY;

即:在view发生平移的过程中,left和top始终是不变的,指view原始位置的左上角坐标,发生改变的只是x,y,translationX,translationY这4个参数。

触摸事件

MotionEvent

手指的触摸事件一般可以分为两种(姑且把单击和长按当成一种,滑动和多点触控当成一种吧,起码触发的事件是差不多的):

  • 手指按下,不滑动,放开:DOWN--->UP。
  • 手指按下,滑动一段距离,再松手:DOWN--->MOVE--->...--->MOVE--->UP。

通过MotionEvent对象我们可以得到点击位置的坐标:

  • getX()和getY():得到的是相对当前view左上角的坐标。
  • getRawX()和getRawY():得到的是相对手机屏幕左上角的坐标。

TouchSlop

即系统所能识别出的被认为是滑动的最小距离。常量,和硬件设备有关,可以通过ViewConfiguration.get(context).getScaledTouchSlop()得到,手指移动小于这个值得话则认为这次操作不是滑动。

VelocityTracker

用来测量某个触摸事件的速度。

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /**
         * 某个触摸时间的速度测量:
         * 1.通过obtain()方法获得velocityTracker变量,并添加需要测量的事件
         * 2.通过computeCurrentVelocity计算速度(参数单位为ms),再通过getter方法获取速度值(右下滑为正数,反之为负数)
         * 3.释放velocityTracker对象。
         */
        VelocityTracker velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);

        velocityTracker.computeCurrentVelocity(1000);//秒速
        int v_x = (int) velocityTracker.getXVelocity();
        int v_y = (int) velocityTracker.getYVelocity();

        LogUtils.i(TAG,"\t\tX:" + v_x + "\t\tY:" + v_y);

        velocityTracker.recycle();

        return true;
    }
    
02-17 11:26:55.483 27154-27154/lxf.androiddemos I/TestView:         X:5656      Y:1203
02-17 11:26:55.500 27154-27154/lxf.androiddemos I/TestView:         X:6255      Y:1202
02-17 11:26:55.509 27154-27154/lxf.androiddemos I/TestView:         X:0     Y:0
02-17 11:26:55.510 27154-27154/lxf.androiddemos I/TestView:         X:0     Y:0
02-17 11:27:01.207 27154-27154/lxf.androiddemos I/TestView:         X:0     Y:0
02-17 11:27:01.248 27154-27154/lxf.androiddemos I/TestView:         X:-421      Y:49
02-17 11:27:01.265 27154-27154/lxf.androiddemos I/TestView:         X:-2978     Y:372
02-17 11:27:01.282 27154-27154/lxf.androiddemos I/TestView:         X:-3426     Y:426

GestureDetector

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

//1.实现OnGestureListener接口
public class TestView extends View implements GestureDetector.OnGestureListener{
//2.获得GestureDetector对象,
gestureDetector = new GestureDetector(getContext(),this);
//如果要监听双击,可以实现DoubleTapListener接口
gestureDetector.setOnDoubleTapListener(mDoubleTapListener);
...
//3.接管onTouchEvent(event)方法。
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }
//4.在接口的相应回调方法中实现自己的逻辑。
...
}

View的滑动

scrollTo/scrollBy

scrollBy内部实际上就是调用的scrollTo方法,它实现了view基于当前位置的相对滑动,而scrollTo是相对于初始位置滚动某段距离,可以变向理解为绝对滑动。

    public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

在滑动过程中,mScrollX的值总是等于view的左边缘(left)和view的内容的左边缘在水平方向上的距离,mScrollY同理。scrollTo/scrollBy只能改变view的内容位置而不能改变view在布局中的位置。

使用动画

使用动画使view平移的方式有两种:

  • 补间动画:实际上是对view的影像进行操作,并不会改变view本身的位置、内容等参数。
TranslateAnimation animation = new TranslateAnimation(0,100,0,0);
setAnimation(animation);
animation.start();
  • 属性动画:直接操作view的属性,可以改变view自身。
ObjectAnimator.ofInt(targetView,"translationX",0,100).setDuration(500).start();

改变LayoutParams

        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
        params.leftMargin += 100;
        setLayoutParams(params);
//      或requestLayout();

弹性滑动

使用Scroller

Scroller的典型用法:

scroller = new Scroller(getContext());

    private void smoothScrollTo(int x, int y) {
        int scrollX = getScrollX();
        int delayX = x - scrollX;
        scroller.startScroll(scrollX, 0, delayX, 0, 1000);//仅仅保存相应参数
        invalidate();//draw方法中会调用computeScroll
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();
        }
    }

Scroller本身并不能使View滑动,它需要配合View的computeScroll方法才能实现弹性滑动的效果。它不断让view重绘,每一次重绘距离view的起始滑动会有一个时间间隔,通过这个时间间隔Scroller可以得到view的当前滑动位置,通过scrollTo()完成滑动。

使用属性动画

值动画:其实属性动画的根本就是属性值的改变

        ValueAnimator animator = ValueAnimator.ofFloat(0,1).setDuration(1000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float flag = animation.getAnimatedFraction();
                scrollTo(startX + (int)(delayX * flag),0);
            }
        });
        animator.start();

其实所谓弹性滑动,就是将一次滑动分成了若干个短距离滑动。

你可能感兴趣的:(View系列笔记(一)----基础概念知识)