View知识(开发艺术探索)

View是android中所有控件的基类,View是一种界面层的抽象。

image.png
测量 onMeasure()
  • 系统自顶向下遍历视图树,以确定每个 ViewGroup 和 View 元素应当有多大。在测量 ViewGroup 的同时也会测量其子对象。
    1)模式分类
    它有三种模式:
    ①、UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
    ②、EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小; --> match_parent
    ③、AT_MOST(至多),子元素至多达到指定大小的值。 --> wrap_content
布局 onLayout()
  • 系统执行另一个自顶向下的遍历操作,每个 ViewGroup 都根据测量阶段中所确定的大小来确定其子对象的位置。
绘制 onDraw()
  • 系统再次执行一个自顶向下的遍历操作。对于视图树中的每个对象,系统会为其创建一个 Canvas 对象,以便向 GPU 发送一个绘制命令列表。这些命令包含系统在前面 2 个阶段中确定的 ViewGroup 和 View 对象的大小和位置。

这里顺带讲一下getWidth()与getMeasureWidth()的区别,getMeasureWidth()是在onMeasure()获取到的,而getWidth()是在onLayout()中获取的 child.layout(left, top, right, bottom)中赋值获取的,在布局过程中,测量到的宽高只能作为建议值给布局,当布局中没有使用测量的值,就回出现两个值不同。

public class ILinearLayout extends LinearLayout {

    public ILinearLayout(Context context) {
        super(context);
    }

    public ILinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
        int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);

        int height = 0;
        int width = 0;
        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            //测量子控件
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            //获得子控件的高度和宽度
            int childHeight = child.getMeasuredHeight();
            int childWidth = child.getMeasuredWidth();
            //得到最大宽度,并且累加高度
            height += childHeight;
            width = Math.max(childWidth, width);
        }

        setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? measureWidth : width, (measureHeightMode == MeasureSpec.EXACTLY) ? measureHeight : height);

    }

    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int top = 0;
        int count = getChildCount();
        for (int i=0;i
  • View的位置参数
  • MotionEvent
  • TouchSlop对象
  • VelocityTracker
  • GestureDetector
  • Scroller
坐标系

注意

  • x = left + translationX;
  • y = top + translationY;
  • View在平移的过程中,top和left表示的的是原左上角的位置,值不会改变。发生改变的是x,y,translationX,translationY四个参数。

MotionEvent

通过MotionEvent对象我们得到点击事件的x和y坐标。系统提供两组方法:getX/getY和getRawX/getRawY.

  • getX/getY返回的是相对于当前View左上角的x和y坐标。
  • getRawX/getRawY 返回的相对于屏幕左上角的x和y坐标。

TouchSlop

  • TouchSlop是系统所能识别出的被认为是滑动的最小距离。
  • 获取方式 ViewConfiguration.get(getContext()).getScaledTouchSlop().

VelocityTracker

速度追踪,用于追踪手指在滑动过程中的速度,包括水平和竖直方向的速度。

   private void velocity() {
        VelocityTracker velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);

        // units时间内划过的像素数
        velocityTracker.computeCurrentVelocity(1000);
        float velocityX = velocityTracker.getXVelocity();
        float velocityY = velocityTracker.getYVelocity();

        // 清理
        velocityTracker.clear();
        velocityTracker.recycle();
    }

View的滑动

  • 第一种 通过View本身提供的srollTo/scollBy方法
  • 第二种 通过动画给view施加平移效果来实现滑动
  • 第三种 通过改变view的LayoutParams使得View重新布局从而实现滑动。

scrollBy

实现了基于当前位置的相对滑动

scrollTo

实现了基于所传参数的绝对滑动

滑动

你可能感兴趣的:(View知识(开发艺术探索))