View 类绘制

View 类的基本绘制流程

  • 基本属性:4个方向位置,m

    mLeft;
    mTop;
    mBottom;
    mRight;
    
  • 修改属性的方法:修改了上述的4个值

    • setFrame(int left, int top, int right, int bottom)
  • 基本读取属性方法:

    • getHeight()

    • getWidth()

  • layout文件中的设置宽高的属性转换

match_parent --计算出屏幕上的值->MeasureSpec.makeMeasureSpec(windowSize,MeasureSpec.EXACTLY)

wrap_parent --计算出屏幕上的值->MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST)

default(layout_width="48dp"指定大小) ---> MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);

  • onLayout(xxx)方法:只给ViewGroup调用
    • 如果该View是一个ViewGroup时,可以调用View中onLayout(xxx)方法,assign a size and position to each of its children

ImageView

  • onMeasure(int widthMeasureSpec, int heightMeasureSpec):用来测量自身的大小

    1. 测量出自身的真实宽高(mDrawableWidth+pleft + pright)
    2. 与自身被设置的最小值比较,取最大值
    3. 与布局指定的大小比较 widthMeasureSpec ,根据Mode得到最终的合适值

    由参数可得Mode是否可以父类指定,还是由子类指定:

    final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
    final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

    可以知道其他参数:自身drawable的宽高,四个方向的padding

    w = mDrawableWidth;
    h = mDrawableHeight;
    int pleft = mPaddingLeft;
    int pright = mPaddingRight;
    int ptop = mPaddingTop;
    int pbottom = mPaddingBottom;
    w += pleft + pright;
    h += ptop + pbottom;

    最后计算出:w,h 为自身的宽高,加上相应的padding值:

    w = Math.max(w, getSuggestedMinimumWidth());//getSuggestedMinimumWidth 由layout布局父类调用,决定该view的最小值。
    h = Math.max(h, getSuggestedMinimumHeight());
    

    根据指定的大小 widthMeasureSpec 和 测量的大小w,获取最终的结果:

    widthSize = resolveSizeAndState(w, widthMeasureSpec, 0);
    heightSize = resolveSizeAndState(h, heightMeasureSpec, 0);

    调用设置方法,传入最终值:

    setMeasuredDimension(widthSize, heightSize);

View类的resolveSizeAndState方法:

  • 根据measureSpec得到Mode,由Mode去决定真实的值

    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
    int result = size;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    switch (specMode) {
    case MeasureSpec.UNSPECIFIED: //随子类想要
    result = size;
    break;
    case MeasureSpec.AT_MOST: //尽量满足子类所要的大小
    if (specSize < size) {
    result = specSize | MEASURED_STATE_TOO_SMALL;
    } else {
    result = size;
    }
    break;
    case MeasureSpec.EXACTLY: //由父类制定的情况
    result = specSize;
    break;
    }
    return result | (childMeasuredState&MEASURED_STATE_MASK);
    }

  • onDraw(Canvas canvas):绘制自身的样子

总结

  • 流程:measure(计算自身大小) ----> layout(计算在布局的位置)

  • 首先getMeasureWidth()方法在measure()过程结束后就可以获取到了,而getWidth()方法要在layout()过程结束后才能获取到。

  • 另外,getMeasureWidth()方法中的值是通过setMeasuredDimension()方法来进行设置的,而getWidth()方法中的值则是通过视图右边的坐标减去左边的坐标计算出来的。

    measure() {
    onMeasure() {
    setMeasuredDimension()
    };
    }

    layout(){
    onMeasure(){setMeasuredDimension()};
    setFrame(l, t, r, b);
    }

  • 复写子类的流程:

    • onMeasure():计算自身的大小,最后要调用setMeasuredDimension
    • onLayout(l,t,r,b):计算自身在布局中的位置,其中的参数(l,t,r,b)是相对父布局而言,这个只能给ViewGroup的子类实现调用。
    • onDraw():描绘自己的样子。

视图状态

  • View focusSearch(int direction):

       * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
       * Find the nearest view in the specified direction that can take focus.
       * This does not actually give focus to that view.
       *
       * @return The nearest focusable in the specified direction, or null if none
       *         can be found.
    

View 类的监听事件(与用户,外界的交流)

  • static class ListenerInfo :一个监听器的域(容器),包含了各种类型的监听器对象

  • 内部监听

      //监听View的focus状态的改变
      protected OnFocusChangeListener mOnFocusChangeListener;
      //监听View 绘制过程中的layout改变(在layout()方法中调用)
      private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
    
      private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
    
  • 外部监听

      //监听用户按下实体键,如menu键
      private OnKeyListener mOnKeyListener;
    
      //监听用户的手势
      private OnGenericMotionListener mOnGenericMotionListener;
    
      public OnClickListener mOnClickListener;
    
      protected OnLongClickListener mOnLongClickListener;
    
      protected OnCreateContextMenuListener mOnCreateContextMenuListener;
    
      private OnTouchListener mOnTouchListener;
    
      private OnHoverListener mOnHoverListener;
      
      private OnDragListener mOnDragListener;
    
      private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
    
posted @ 2015-10-30 08:32  beyondbycyx  阅读(230)  评论(0编辑  收藏  举报