• View 中 onMeasure


    今天学习android自定义组件:docs/guide/topics/ui/custom-components.html

    其中有两个对布局界面影响很的方法,onDraw(),和onMeasure().

    onDraw()比较好理解.onMeasure()就比较难理解一些,也更复杂些 ,引用文档中的说法就是:

    实现onMeasure()方法基本需要完成下面三个方面的事情(最终结果是你自己写相应代码得出测量值并调用view的一个方法进行设置,告诉给你的view安排位置大小的父容器你要多大的空间.):

    1.传递进来的参数widthMeasureSpec和heightMeasureSpec是你对你应该得出来的测量值的限制.

    2. 你在onMeasure计算出来设置的width和height将被用来渲染组件.应当尽量在传递进来的width和height 声明之间.

    虽然你也可以选择你设置的尺寸超过传递进来的声明.但是这样的话,父容器可以选择,如clipping,scrolling,或者抛出异常,或者(也许是用新的声明参数)再次调用onMeasure()

    3.一但width和height计算好了,就应该调用View.setMeasuredDimension(int width,int height)方法,否则将导致抛出异常.    

    在Android提提供的一个自定义View示例中(在API demos 中的 view/LabelView)可以看到一个重写onMeasure()方法的

    实例,也比较好理解.

     
      @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
     }
     
     /**
      * 高度
      * @param heightMeasureSpec
      * @return
      */
     private int measureHeight(int heightMeasureSpec) {
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);//父的空间大小
        int h = bitmap.getHeight();  //图片的高度
        int result = 0 ;
        if (specMode == MeasureSpec.EXACTLY) {//父为 wrap_content
           result = Math.min(h, specSize);
        }else if(specMode == MeasureSpec.AT_MOST){//父为fill_parent
            result = specSize;
        } else {
            result = specSize;
           }
           return result;
     }

      private int measureWidth(int measureSpec) {
             int result = 0;
             int specMode = MeasureSpec.getMode(measureSpec);
             int specSize = MeasureSpec.getSize(measureSpec);
     
             if (specMode == MeasureSpec.EXACTLY) {
                 // We were told how big to be
                 result = specSize;
             } else {
                // Measure the text
                result = (int) mTextPaint.measureText(mText) + getPaddingLeft()+ getPaddingRight();
              if (specMode == MeasureSpec.AT_MOST) {
                 // Respect AT_MOST value if that was what is called for by measureSpec
                 result = Math.min(result, specSize);
               }
         }
         return result;
     }

    直接看measureWidth()

    首先看到的是参数,分别代表宽度和高度的MeasureSpec

    android2.2文档中对于MeasureSpec中的说明是:

    一个MeasureSpec封装了从父容器传递给子容器的布局需求.

    每一个MeasureSpec代表了一个宽度,或者高度的说明.

    一个MeasureSpec是一个大小跟模式的组合值.一共有三种模式.

     (1)UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.
     
     (2) EXACTLY 父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间
     
     (3) AT_MOST 子容器可以是声明大小内的任意大小.
     
    MeasureSpec是View类下的静态公开类,MeasureSpec中的值作为一个整型是为了减少对象的分配开支.此类用于

    将size和mode打包或者解包为一个整型.

     
  • 相关阅读:
    csuOJ啊 1553
    Codeforces 111B【看看自己和别人在代码能力上的差距!】
    hdu1849
    hdu 1847
    校队训练赛,同时也是HDU4497(数论:素数分解+组合数学)
    POJ 2356 (抽屉原理)
    线段树总结一【转】
    训练赛(1---5)D
    训练赛(1---5)A
    HDU1556 【树状数组】(改段求点)
  • 原文地址:https://www.cnblogs.com/zhongle/p/2660170.html
Copyright © 2020-2023  润新知