最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android  MeasureSpec的理解和源碼的解析

 更新時(shí)間:2017年09月05日 09:26:54   投稿:lqh  
這篇文章主要介紹了Android MeasureSpec的理解和源碼的解析的相關(guān)資料,希望通過(guò)本文大家可以掌握理解這部分內(nèi)容,需要的朋友可以參考下

Android  MeasureSpec的理解和源碼的解析

MeasureSpec的創(chuàng)建規(guī)則:

實(shí)例詳解:

package cc.ww; 
 
import android.view.View; 
import android.view.View.MeasureSpec; 
import android.view.ViewGroup.LayoutParams; 
import android.view.ViewGroup.MarginLayoutParams; 
import android.widget.LinearLayout; 
 
/** 
 * @author http://blog.csdn.net/lfdfhl 
 * 
 * 文檔描述: 
 * 關(guān)于MeasureSpec的理解 
 * 
 * (1) MeasureSpec基礎(chǔ)知識(shí) 
 *   MeasureSpec通常翻譯為"測(cè)量規(guī)格",它是一個(gè)32位的int數(shù)據(jù). 
 *   其中高2位代表SpecMode即某種測(cè)量模式,低32位為SpecSize代表在該模式下的規(guī)格大小. 
 *   可以通過(guò):  
 *   int specMode = MeasureSpec.getMode(measureSpec) 獲取specMode 
    int specSize = MeasureSpec.getSize(measureSpec) 獲取SpecSize 
    
      常用的SpecMode有三種: 
      
    MeasureSpec.EXACTLY 
      官方文檔 
    Measure specification mode: The parent has determined an exact size 
    for the child. The child is going to be given those bounds regardless of how big it wants to be. 
         父容器已經(jīng)檢測(cè)出子View所需要的精確大小.該子View最終的測(cè)量大小即為SpecSize. 
    (1) 當(dāng)子View的LayoutParams的寬(高)采用具體的值(如100px)時(shí)且父容器的MeasureSpec為 MeasureSpec.EXACTLY或者 
    MeasureSpec.AT_MOST或者M(jìn)easureSpec.UNSPECIFIED時(shí): 
         系統(tǒng)返回給該子View的specMode就為 MeasureSpec.EXACTLY 
         系統(tǒng)返回給該子View的specSize就為子View自己指定的大小(childSize) 
         通俗地理解: 
         子View的LayoutParams的寬(高)采用具體的值(如100px)時(shí),那么說(shuō)明該子View的大小是非常明確的,明確到已經(jīng)用具體px值 
         指定的地步了.那么此時(shí)不管父容器的specMode是什么,系統(tǒng)返回給該子View的specMode總是MeasureSpec.EXACTLY,并且 
         系統(tǒng)返回給該子View的specSize就為子View自己指定的大小(childSize). 
    
    (2) 當(dāng)子View的LayoutParams的寬(高)采用match_parent時(shí)并且父容器的MeasureSpec為 MeasureSpec.EXACTLY時(shí): 
         系統(tǒng)返回給該子View的specMode就為 MeasureSpec.EXACTLY 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
         通俗地理解: 
      子View的LayoutParams的寬(高)采用match_parent時(shí)并且父容器的MeasureSpec為 MeasureSpec.EXACTLY. 
      這時(shí)候說(shuō)明子View的大小還是挺明確的:就是要和父容器一樣大,更加直白地說(shuō)就是父容器要怎樣子View就要怎樣. 
      所以,如果父容器MeasureSpec為 MeasureSpec.EXACTLY那么: 
      系統(tǒng)返回給該子View的specMode就為 MeasureSpec.EXACTLY,和父容器一樣. 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize),就是父容器的剩余大小. 
         同樣的道理如果此時(shí),MeasureSpec為 MeasureSpec.AT_MOST呢? 
         系統(tǒng)返回給該子View的specMode也為 MeasureSpec.AT_MOST,和父容器一樣. 
         系統(tǒng)返回給該子View的specSize也為該父容器剩余空間的大小(parentLeftSize),就是父容器的剩余大小. 
      
    MeasureSpec.AT_MOST 
      官方文檔 
    The child can be as large as it wants up to the specified size. 
      父容器指定了一個(gè)可用大小即specSize,子View的大小不能超過(guò)該值. 
    (1) 當(dāng)子View的LayoutParams的寬(高)采用match_parent時(shí)并且父容器的MeasureSpec為 MeasureSpec.AT_MOST時(shí): 
         系統(tǒng)返回給該子View的specMode就為 MeasureSpec.AT_MOST 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
         這種情況已經(jīng)在上面介紹 MeasureSpec.EXACTLY時(shí)已經(jīng)討論過(guò)了. 
   (2) 當(dāng)子View的LayoutParams的寬(高)采用wrap_content時(shí)并且父容器的MeasureSpec為 MeasureSpec.EXACTLY時(shí): 
         系統(tǒng)返回給該子View的specMode就為 MeasureSpec.AT_MOST 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
         通俗地理解: 
         子View的LayoutParams的寬(高)采用wrap_content時(shí)說(shuō)明這個(gè)子View的寬高不明確,要視content而定. 
         這個(gè)時(shí)候如果父容器的MeasureSpec為 MeasureSpec.EXACTLY即父容器是一個(gè)精確模式;這個(gè)時(shí)候簡(jiǎn)單地說(shuō) 
         子View是不確定的,父容器是確定的,那么 
         系統(tǒng)返回給該子View的specMode也就是不確定的即為 MeasureSpec.AT_MOST 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
    (3) 當(dāng)子View的LayoutParams的寬(高)采用wrap_content時(shí)并且父容器的MeasureSpec為 MeasureSpec.AT_MOST時(shí): 
         系統(tǒng)返回給該子View的specMode就為 MeasureSpec.AT_MOST 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
         通俗地理解: 
         子View的LayoutParams的寬(高)采用wrap_content時(shí)說(shuō)明這個(gè)子View的寬高不明確,要視content而定. 
         這個(gè)時(shí)候如果父容器的MeasureSpec為 MeasureSpec.AT_MOST這個(gè)時(shí)候簡(jiǎn)單地說(shuō) 
         子View是不確定的,父容器也是不確定的,那么 
         系統(tǒng)返回給該子View的specMode也就是不確定的即為 MeasureSpec.AT_MOST 
         系統(tǒng)返回給該子View的specSize就為該父容器剩余空間的大小(parentLeftSize) 
         
    
    MeasureSpec.UNSPECIFIED 
      官方文檔 
    The parent has not imposed any constraint on the child. It can be whatever size it wants. 
      父容器不對(duì)子View的大小做限制. 
      一般用作Android系統(tǒng)內(nèi)部,或者ListView和ScrollView.在此不做討論. 
      
      關(guān)于這個(gè)三種測(cè)量規(guī)格下面的源碼分析中體現(xiàn)得很明顯,也可參考以下附圖. 
    
 * (2) 在onMeasure()時(shí)子View的MeasureSpec的形成過(guò)程分析 
 *   關(guān)于該技術(shù)點(diǎn)的討論,請(qǐng)看下面的源碼分析. 
 * 
 */ 
public class UnderstandMeasureSpec { 
   
  /** 
   * 第一步: 
   * 在ViewGroup測(cè)量子View時(shí)會(huì)調(diào)用到measureChildWithMargins()方法,或者與之類(lèi)似的方法. 
   * 請(qǐng)注意方法的參數(shù): 
   * @param child 
   * 子View 
   * @param parentWidthMeasureSpec 
   * 父容器(比如LinearLayout)的寬的MeasureSpec 
   * @param widthUsed 
   * 父容器(比如LinearLayout)在水平方向已經(jīng)占用的空間大小 
   * @param parentHeightMeasureSpec 
   * 父容器(比如LinearLayout)的高的MeasureSpec 
   * @param heightUsed 
   * 父容器(比如LinearLayout)在垂直方向已經(jīng)占用的空間大小 
   * 
   * 在該方法中主要有四步操作,其中很重要的是調(diào)用了getChildMeasureSpec()方法來(lái)確定 
   * 子View的MeasureSpec.詳情參見(jiàn)代碼分析 
   */ 
  protected void measureChildWithMargins(View child,int parentWidthMeasureSpec, int widthUsed, 
                           int parentHeightMeasureSpec, int heightUsed) { 
    //1 得到子View的LayoutParams 
    final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 
    //2 得到子View的寬的MeasureSpec 
    final int childWidthMeasureSpec = getChildMeasureSpec 
    (parentWidthMeasureSpec,mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width); 
    //3 得到子View的高的MeasureSpec 
    final int childHeightMeasureSpec = getChildMeasureSpec 
    (parentHeightMeasureSpec,mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin + heightUsed, lp.height); 
    //4 測(cè)量子View 
    child.measure(childWidthMeasureSpec, childHeightMeasureSpec); 
  } 
   
   
  /** 
   * getChildMeasureSpec()方法確定子View的MeasureSpec 
   * 請(qǐng)注意方法的參數(shù): 
   * @param spec 
   * 父容器(比如LinearLayout)的寬或高的MeasureSpec 
   * @param padding 
   * 父容器(比如LinearLayout)在垂直方向或者水平方向已被占用的空間. 
   * 在measureChildWithMargins()方法里調(diào)用getChildMeasureSpec()時(shí)注意第二個(gè)參數(shù)的構(gòu)成: 
   * 比如:mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin 
   * 其中: 
   * mPaddingLeft和mPaddingRight表示父容器左右兩內(nèi)側(cè)的padding 
   * lp.leftMargin和lp.rightMargin表示子View左右兩外側(cè)的margin 
   * 這四部分都不可以再利用起來(lái)布局子View.所以說(shuō)這些值的和表示: 
   * 父容器在水平方向已經(jīng)被占用的空間 
   * 同理: 
   * mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin 
   * 表示: 
   * 父容器(比如LinearLayout)在垂直方向已被占用的空間. 
   * @param childDimension 
   * 通過(guò)子View的LayoutParams獲取到的子View的寬或高 
   * 
   * 
   * 經(jīng)過(guò)以上分析可從getChildMeasureSpec()方法的第一個(gè)參數(shù)和第二個(gè)參數(shù)可以得出一個(gè)結(jié)論: 
   * 父容器(如LinearLayout)的MeasureSpec和子View的LayoutParams共同決定了子View的MeasureSpec?。。?
   * 
   * 
   * 
   */ 
   public static int getChildMeasureSpec(int spec, int padding, int childDimension) { 
      /** 
       * 第一步:得到父容器的specMode和specSize 
       */ 
      int specMode = MeasureSpec.getMode(spec); 
      int specSize = MeasureSpec.getSize(spec); 
      /** 
       * 第二步:得到父容器在水平方向或垂直方向可用的最大空間值. 
       *    關(guān)于padding參見(jiàn)上面的分析 
       */ 
      int size = Math.max(0, specSize - padding); 
 
      int resultSize = 0; 
      int resultMode = 0; 
 
       
      /** 
       * 第三步:確定子View的specMode和specSize. 
       *    在此分為三種情況進(jìn)行. 
       */ 
      switch (specMode) { 
      /** 
       * 第一種情況: 
       * 父容器的測(cè)量模式為EXACTLY 
       * 
       * 請(qǐng)注意兩個(gè)系統(tǒng)常量: 
       * LayoutParams.MATCH_PARENT=-1 
       * LayoutParams.WRAP_CONTENT=-2 
       * 所以在此處的代碼: 
       * childDimension >= 0 表示子View的寬或高不是MATCH_PARENT和WRAP_CONTENT 
       */ 
      case MeasureSpec.EXACTLY: 
        /** 
         * 當(dāng)父容器的測(cè)量模式為EXACTLY時(shí)如果: 
         * 子View的寬或高是一個(gè)精確的值,比如100px; 
         * 那么: 
         * 子View的size就是childDimension 
         * 子View的mode也為MeasureSpec.EXACTLY 
         */ 
        if (childDimension >= 0) { 
          resultSize = childDimension; 
          resultMode = MeasureSpec.EXACTLY; 
        /** 
         * 當(dāng)父容器的測(cè)量模式為EXACTLY時(shí)如果: 
         * 子View的寬或高是LayoutParams.MATCH_PARENT 
         * 那么: 
         * 子View的size就是父容器在水平方向或垂直方向可用的最大空間值即size 
         * 子View的mode也為MeasureSpec.EXACTLY 
         */ 
        } else if (childDimension == LayoutParams.MATCH_PARENT) { 
          // Child wants to be our size. So be it. 
          resultSize = size; 
          resultMode = MeasureSpec.EXACTLY; 
        /** 
         * 當(dāng)父容器的測(cè)量模式為EXACTLY時(shí)如果: 
         * 子View的寬或高是LayoutParams.WRAP_CONTENT 
         * 那么: 
         * 子View的size就是父容器在水平方向或垂直方向可用的最大空間值即size 
         * 子View的mode為MeasureSpec.AT_MOST 
         */ 
        } else if (childDimension == LayoutParams.WRAP_CONTENT) { 
          // Child wants to determine its own size. It can't be bigger than us. 
          resultSize = size; 
          resultMode = MeasureSpec.AT_MOST; 
        } 
        break; 
 
      /** 
       * 第二種情況: 
       * 父容器的測(cè)量模式為AT_MOST 
       * 
       * 請(qǐng)注意兩個(gè)系統(tǒng)常量:pp 
       * LayoutParams.MATCH_PARENT=-1 
       * LayoutParams.WRAP_CONTENT=-2 
       * 所以在此處的代碼: 
       * childDimension >= 0 表示子View的寬或高不是MATCH_PARENT和WRAP_CONTENT 
       */ 
      case MeasureSpec.AT_MOST: 
        /** 
         * 當(dāng)父容器的測(cè)量模式為AT_MOST時(shí)如果: 
         * 子View的寬或高是一個(gè)精確的值,比如100px; 
         * 那么: 
         * 子View的size就是childDimension 
         * 子View的mode也為MeasureSpec.EXACTLY 
         */ 
        if (childDimension >= 0) { 
          // Child wants a specific size... so be it 
          resultSize = childDimension; 
          resultMode = MeasureSpec.EXACTLY; 
        /** 
         * 當(dāng)父容器的測(cè)量模式為AT_MOST時(shí)如果: 
         * 子View的寬或高為L(zhǎng)ayoutParams.MATCH_PARENT 
         * 那么: 
         * 子View的size就是父容器在水平方向或垂直方向可用的最大空間值即size 
         * 子View的mode也為MeasureSpec.AT_MOST 
         */ 
        } else if (childDimension == LayoutParams.MATCH_PARENT) { 
          // Child wants to be our size, but our size is not fixed. 
          // Constrain child to not be bigger than us. 
          resultSize = size; 
          resultMode = MeasureSpec.AT_MOST; 
         /** 
         * 當(dāng)父容器的測(cè)量模式為AT_MOST時(shí)如果: 
         * 子View的寬或高為L(zhǎng)ayoutParams.WRAP_CONTENT 
         * 那么: 
         * 子View的size就是父容器在水平方向或垂直方向可用的最大空間值即size 
         * 子View的mode也為MeasureSpec.AT_MOST 
         */ 
        } else if (childDimension == LayoutParams.WRAP_CONTENT) { 
          // Child wants to determine its own size. It can't be 
          // bigger than us. 
          resultSize = size; 
          resultMode = MeasureSpec.AT_MOST; 
        } 
        break; 
 
      /** 
       * 第三種情況: 
       * 父容器的測(cè)量模式為UNSPECIFIED 
       * 
       * 請(qǐng)注意兩個(gè)系統(tǒng)常量: 
       * LayoutParams.MATCH_PARENT=-1 
       * LayoutParams.WRAP_CONTENT=-2 
       * 所以在此處的代碼: 
       * childDimension >= 0 表示子View的寬或高不是MATCH_PARENT和WRAP_CONTENT 
       */ 
      case MeasureSpec.UNSPECIFIED: 
        /** 
         * 當(dāng)父容器的測(cè)量模式為UNSPECIFIED時(shí)如果: 
         * 子View的寬或高是一個(gè)精確的值,比如100px; 
         * 那么: 
         * 子View的size就是childDimension 
         * 子View的mode也為MeasureSpec.EXACTLY 
         */ 
        if (childDimension >= 0) { 
          // Child wants a specific size... let him have it 
          resultSize = childDimension; 
          resultMode = MeasureSpec.EXACTLY; 
        /** 
         * 當(dāng)父容器的測(cè)量模式為UNSPECIFIED時(shí)如果: 
         * 子View的寬或高為L(zhǎng)ayoutParams.MATCH_PARENT 
         * 那么: 
         * 子View的size為0 
         * 子View的mode也為MeasureSpec.UNSPECIFIED 
         */ 
        } else if (childDimension == LayoutParams.MATCH_PARENT) { 
          // Child wants to be our size... find out how big it should be 
          resultSize = 0; 
          resultMode = MeasureSpec.UNSPECIFIED; 
        /** 
         * 當(dāng)父容器的測(cè)量模式為UNSPECIFIED時(shí)如果: 
         * 子View的寬或高為L(zhǎng)ayoutParams.WRAP_CONTENT 
         * 那么: 
         * 子View的size為0 
         * 子View的mode也為MeasureSpec.UNSPECIFIED 
         */ 
        } else if (childDimension == LayoutParams.WRAP_CONTENT) { 
          // Child wants to determine its own size.... find out how big it should be 
          resultSize = 0; 
          resultMode = MeasureSpec.UNSPECIFIED; 
        } 
        break; 
      } 
      return MeasureSpec.makeMeasureSpec(resultSize, resultMode); 
    } 
   
   
 
} 




 如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Android側(cè)滑菜單控件DrawerLayout使用詳解

    Android側(cè)滑菜單控件DrawerLayout使用詳解

    這篇文章主要為大家詳細(xì)介紹了Android側(cè)滑菜單控件DrawerLayout的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android指紋識(shí)別功能

    Android指紋識(shí)別功能

    這篇文章主要為大家詳細(xì)介紹了Android指紋識(shí)別功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Android activity和view判斷滑動(dòng)

    Android activity和view判斷滑動(dòng)

    這篇文章主要介紹了Android activity和view判斷滑動(dòng)的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Android判斷網(wǎng)絡(luò)狀態(tài)的代碼

    Android判斷網(wǎng)絡(luò)狀態(tài)的代碼

    這篇文章主要為大家詳細(xì)介紹了Android判斷網(wǎng)絡(luò)狀態(tài)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android14原生PackageInstaller安裝某些apk報(bào)錯(cuò)問(wèn)題

    Android14原生PackageInstaller安裝某些apk報(bào)錯(cuò)問(wèn)題

    本文主要介紹了在Android 14上安裝大型應(yīng)用時(shí)遇到的java.lang.RuntimeException: Could not copy bitmap to parcel blob錯(cuò)誤,下面就一起來(lái)介紹一下解決方法,感興趣的可以了解一下
    2025-03-03
  • Android中.9.png圖片的使用及制作

    Android中.9.png圖片的使用及制作

    這篇文章主要介紹了Android中.9.png圖片的使用及制作的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android入門(mén)之ScrollView的使用教程

    Android入門(mén)之ScrollView的使用教程

    我們經(jīng)常可以看到在手機(jī)里正在垂直加載一堆的數(shù)據(jù),然后過(guò)一會(huì)加載得內(nèi)容過(guò)多,到了手機(jī)的底部了,垂直方向就會(huì)出現(xiàn)一個(gè)“滾動(dòng)條”。本文就來(lái)通過(guò)一些示例和大家介紹下ScrollView(滾動(dòng)條)的使用,感興趣的可以了解一下
    2022-11-11
  • Android中dataBinding使用的簡(jiǎn)單封裝

    Android中dataBinding使用的簡(jiǎn)單封裝

    前面一段時(shí)間學(xué)習(xí)了一下Android中的DataBinding,但是只是很簡(jiǎn)單地實(shí)現(xiàn)了一下,DataBinding中最強(qiáng)大的地方還沒(méi)有認(rèn)真地學(xué)習(xí)過(guò),有很多地方還不理解,下面這篇文章主要給大家介紹了關(guān)于Android中dataBinding使用的簡(jiǎn)單封裝,需要的朋友可以參考下
    2023-06-06
  • Kotlin中的高階函數(shù)深入講解

    Kotlin中的高階函數(shù)深入講解

    這篇文章主要給大家介紹了關(guān)于Kotlin中高階函數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Android音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)案例

    Android音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)案例

    我們平時(shí)長(zhǎng)時(shí)間打代碼的時(shí)候肯定會(huì)感到疲憊和乏味,這個(gè)時(shí)候一邊播放自己喜歡的音樂(lè),一邊繼續(xù)打代碼,心情自然也愉快很多。音樂(lè)帶給人的聽(tīng)覺(jué)享受是無(wú)可比擬的,動(dòng)聽(tīng)的音樂(lè)可以愉悅?cè)说纳硇?,讓人更加積極地去熱愛(ài)生活,這篇文章主要介紹了Android音樂(lè)播放器簡(jiǎn)單實(shí)現(xiàn)案例
    2022-12-12

最新評(píng)論

鄂尔多斯市| 灵宝市| 永昌县| 鹿泉市| 扶沟县| 昭苏县| 分宜县| 遂宁市| 门头沟区| 平湖市| 汽车| 上杭县| 互助| 和顺县| 扶余县| 修水县| 江西省| 华容县| 茌平县| 黄石市| 滕州市| 北碚区| 常德市| 肇州县| 尚志市| 葵青区| 万山特区| 随州市| 宁武县| 息烽县| 田林县| 呼伦贝尔市| 莎车县| 墨脱县| 金寨县| 芷江| 长垣县| 拉孜县| 乡宁县| 长垣县| 宜宾市|