zoukankan      html  css  js  c++  java
  • MeasureSpec简介

     onMeasure方法在控件的父元素正要放置它的子控件时调用。它会问一个问题,“你想要用多大地方啊?”,然后传入两个参数—— widthMeasureSpec和heightMeasureSpec。它们指明控件可获得的空间以及关于这个空间描述的元数据。比返回一个结果要好的 方法是你传递View的高度和宽度到setMeasuredDimension方法里。
        
      接下来的代码片段给出了如何重写onMeasure。注意,调用的本地空方法是来计算高度和宽度的。它们会译解widthHeightSpec和heightMeasureSpec值,并计算出合适的高度和宽度值。
      
      Java代码:
        @Override
      protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
      
      
      intmeasuredHeight=measureHeight(heightMeasureSpec);
      intmeasuredWidth=measureWidth(widthMeasureSpec);
      setMeasuredDimension(measuredHeight,measuredWidth);
      }
      
      privateintmeasureHeight(intmeasureSpec){
      //高度测量窗口的回归.
      }
      
      privateintmeasureWidth(intmeasureSpec){
      //还测量窗口的宽度.
      }

      边界参数——widthMeasureSpec和heightMeasureSpec,效率的原因以整数的方式传入。在它们使用之前,首先要做的是使用MeasureSpec类的静态方法getMode和getSize来译解,如下面的片段代码所示:
      
      Java代码:
      intspecMode=MeasureSpec.getMode(measureSpec);
      intspecSize=MeasureSpec.getSize(measureSpec);

      接下来的框架代码给出了处理View测量的典型实现:
      
      Java代码:
      

      @Override
      protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
      intmeasuredHeight=measureHeight(heightMeasureSpec);
      intmeasuredWidth=measureWidth(widthMeasureSpec);
      setMeasuredDimension(measuredHeight,measuredWidth);
      }
      
      privateintmeasureHeight(intmeasureSpec){
      intspecMode=MeasureSpec.getMode(measureSpec);
      intspecSize=MeasureSpec.getSize(measureSpec);
      
      //如果没有限制默认大小是指定的.
      intresult=500;
      if(specMode==MeasureSpec.AT_MOST)
      {
      //你理想的大小的计算
      //在这个最大值控制.
      //如果你能控制的充满可用
      //外太空返回束缚.
      result=specSize;
      }
      elseif(specMode==MeasureSpec.EXACTLY)
      {
      //如果你的控制能符合这些界限返回那个价值.
      result=specSize;
      }
      returnresult;
      }
      
      privateintmeasureWidth(intmeasureSpec){
      intspecMode=MeasureSpec.getMode(measureSpec);
      intspecSize=MeasureSpec.getSize(measureSpec);
      
      //如果没有限制默认大小是指定的.
      intresult=500;
      if(specMode==MeasureSpec.AT_MOST)
      {
      //理想尺寸的计算你的控制
      //在这个最大的尺寸。
      //如果你的控制填充的可用空间
      //返回外面的束缚。
      result=specSize;
      }
      elseif(specMode==MeasureSpec.EXACTLY)
      {
      //如果你的控制能符合这些界限返回那个价值.
      result=specSize;
      }
      returnresult;
      }

    的要求。一个MeasureSpec包含一个尺寸和模式。
    有三种可能的模式:
    UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。
    EXACTLY:父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。
    AT_MOST:子布局可以根据自己的大小选择任意大小。

    为了减少内存分配,MeasueSpecs用整数表示。这个类提供打包和解包<size,mode>元组为整型。参考方法:public static int makeMeasureSpec(int size,int mode)。

    转:http://blog.csdn.net/zjl5211314/article/details/6952698

    一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。

     

      它常用的三个函数:

      1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)

      2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)

      3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)

     

      这个类的使用呢,通常在view组件的onMeasure方法里面调用但也有少数例外,看看几个例子:

     

      a.首先一个我们常用到的一个有用的函数,View.resolveSize(int size,int measureSpec)

     

    复制代码
    8421     public static int resolveSize(int size, int measureSpec) {
    8422 int result = size;
    8423 int specMode = MeasureSpec.getMode(measureSpec);
    8424 int specSize = MeasureSpec.getSize(measureSpec);
    8425 switch (specMode) {
    8426 case MeasureSpec.UNSPECIFIED:
    8427 result = size;
    8428 break;
    8429 case MeasureSpec.AT_MOST:
    8430 result = Math.min(size, specSize);
    8431 break;
    8432 case MeasureSpec.EXACTLY:
    8433 result = specSize;
    8434 break;
    8435 }
    8436 return result;
    8437 }
    复制代码

      上面既然要用到measureSpec值,那自然表示这个函数通常是在onMeasure方法里面调用的。简单说一下,这个方法的主要作用就是根据你提供的大小和模式,返回你想要的大小值,这个里面根据传入模式的不同来做相应的处理。

      再看看MeasureSpec.makeMeasureSpec方法,实际上这个方法很简单:

    9023         public static int makeMeasureSpec(int size, int mode) {
    9024 return size + mode;
    9025 }

      这样大家不难理解size跟measureSpec区别了。看看它的使用吧,ListView.measureItem(View child)

     

    复制代码
    2464     private void measureItem(View child) {
    2465 ViewGroup.LayoutParams p = child.getLayoutParams();
    2466 if (p == null) {
    2467 p = new ViewGroup.LayoutParams(
    2468 ViewGroup.LayoutParams.MATCH_PARENT,
    2469 ViewGroup.LayoutParams.WRAP_CONTENT);
    2470 }
    2471
    2472 int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
    2473 mListPadding.left + mListPadding.right, p.width);
    2474 int lpHeight = p.height;
    2475 int childHeightSpec;
    2476 if (lpHeight > 0) {
    2477 childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
    2478 } else {
    2479 childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    2480 }
    2481 child.measure(childWidthSpec, childHeightSpec);
    2482 }
    复制代码

      measureSpec方法通常在ViewGroup中用到,它可以根据模式(MeasureSpec里面的三个)可以调节子元素的大小。

      注意,使用EXACTLY和AT_MOST通常是一样的效果,如果你要区别他们,那么你就要使用上面的函数View.resolveSize(int size,int measureSpec)返回一个size值,然后使用你的view调用setMeasuredDimension(int,int)函数。

     

    8406     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
    8407 mMeasuredWidth = measuredWidth;
    8408 mMeasuredHeight = measuredHeight;
    8409
    8410 mPrivateFlags |= MEASURED_DIMENSION_SET;
    8411 }

      然后你调用view.getMeasuredWidth,view.getMeasuredHeigth 返回的就是上面函数里的mMeasuredWidth,mMeasuredHeight的值。

     

     

     

     

    mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。

     

    MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件

     

    大小已经确定的情况,都是精确尺寸。

     

    MeasureSpec.AT_MOST 是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行 变化,此时控件尺寸

    只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

     

    MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

     

  • 相关阅读:
    剖析C语言中a=a+++++a的无聊问题
    [转]精确到1%秒的单片机计时器汇编程序
    [转]学DSP、FPGA、ARM,哪个更有前途?
    【Java】Eclipse导出JAR包
    二维码生成器(支持历史记录点击和清空)
    移动端开发注意之一二
    localStorage实现按钮点击禁用
    JavaScript之查找元素
    扒拉扒拉table
    解惑之JavaScript
  • 原文地址:https://www.cnblogs.com/jiezzy/p/2597448.html
Copyright © 2011-2022 走看看