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方法传入的模式。

     

  • 相关阅读:
    Palindrome Linked List 解答
    Word Break II 解答
    Array vs Linked List
    Reverse Linked List II 解答
    Calculate Number Of Islands And Lakes 解答
    Sqrt(x) 解答
    Find Median from Data Stream 解答
    Majority Element II 解答
    Binary Search Tree DFS Template
    188. Best Time to Buy and Sell Stock IV
  • 原文地址:https://www.cnblogs.com/jiezzy/p/2597448.html
Copyright © 2011-2022 走看看