自定义view 重写onMeasure()方法

来源:互联网 发布:年金保险 知乎 编辑:程序博客网 时间:2024/06/05 00:26
<div id="article_details" class="details">
    <div class="article_title">   
         <span class="ico ico_type_Repost"></span>




    <h1>
        <span class="link_title"><a href="/easyer2012/article/details/37900583">
        ANDROID自定义视图——onMeasure流程,MeasureSpec详解
        </a></span>
    </h1>
</div>


    <div class="article_manage">
        <span class="link_categories">
        分类:
            <a href="/easyer2012/article/category/1167761" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">android 高手进阶教程</a> 
        </span>
    <span class="link_postdate">2014-07-17 09:09</span>
    <span class="link_view" title="阅读次数">83人阅读</span>
    <span class="link_comments" title="评论次数"><a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(0)</span>
    <span class="link_collect"><a href="javascript:void(0);" onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shoucang']);collectArticle('ANDROID自定义视图——onMeasure流程,MeasureSpec详解','37900583');return false;" title="收藏">收藏</a></span>
    <span class="link_report"><a href="#report" onclick="javascript:_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_jubao']);report(37900583,2);return false;" title="举报">举报</a></span>
    
</div>


  
    
<div id="article_content" class="article_content">


<p><span style="font-size:24px; color:#cc0000"><strong>简介:</strong></span></p>
<p><span style="font-size:18px">在自定义view的时候,其实很简单,只需要知道3步骤:</span></p>
<p><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-size:18px">1.测量——onMeasure():决定View的大小</span></span></p>
<p><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-size:18px">2.布局——onLayout():决定View在ViewGroup中的位置</span></span></p>
<p><span style="font-size:18px"><span style="font-family:Arial; color:#333333; line-height:26px">3.绘制——onDraw():如何绘制这个View。</span><br>
</span></p>
<p><span style="font-size:18px">而第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到<span style="font-family:Arial; font-size:18px; color:#333333; line-height:26px">1</span>,2两个步骤就中好了。</span></p>
<p><span style="font-size:18px">而这篇文章就来谈谈第一步,也是十分关键得一步:“<strong>测量(Measure)</strong>”</span></p>
<p><span style="font-size:18px"><br>
</span></p>
<p><span style="font-family:Arial; line-height:26px"><strong><span style="font-size:24px; color:#cc0000">Measure():</span></strong></span></p>
<p><span style="font-family:Arial; color:#333333"><span style="font-size:14px; line-height:26px">Measure的中文意思就是测量。所以它的作用就是测量View的大小。</span></span></p>
<p><span style="font-family:Arial; color:#333333"><span style="font-size:14px; line-height:26px">而决定View的大小只需要两个值:宽<span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">详细</span>测量值(widthMeasureSpec)和高<span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">详细</span>测量值(heightMeasureSpec)。也可以把详细测量值理解为视图View想要的大小说明(想要的未必就是最终大小)。</span></span></p>
<p><span style="font-family:Arial; color:#333333"><span style="font-size:14px; line-height:26px">对于详细测量值(<span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">measureSpec</span>)需要两样东西来确定它,那就是大小(size)和模式(mode)。</span></span><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">而</span><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">measureSpec,size,mode他们三个的关系,都封装在View类中的一个内部类里,名叫<strong>MeasureSpec</strong>。</span></p>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><br>
</span></p>
<p><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><strong><span style="font-size:24px; color:#cc0000">MeasureSpec:</span></strong></span><br>
</span></p>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">因为MeasureSpec类很小,而且设计的很巧妙,所以我贴出了全部的源码并进行了详细的标注。(<span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px">掌握MeasureSpec的机制后会对整个Measure方法有更深刻的理解。)</span></span></p>
<p><span style="font-family:Arial; color:#333333"><span style="font-size:14px; line-height:26px"><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"></span></span></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 1170px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_1" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;MeasureSpec由size和mode组成。</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;三种Mode:</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;1.UNSPECIFIED</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;父不没有对子施加任何约束,子可以是任意大小(也就是未指定)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;(UNSPECIFIED在源码中的处理和EXACTLY一样。当View的宽高值设置为0的时候或者没有设置宽高时,模式为UNSPECIFIED</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;2.EXACTLY</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;父决定子的确切大小,子被限定在给定的边界里,忽略本身想要的大小。</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;(当设置width或height为match_parent时,模式为EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;3.AT_MOST</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;子最大可以达到的指定大小</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;(当设置为wrap_content时,模式为AT_MOST,&nbsp;表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸)</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;MeasureSpecs使用了二进制去减少对象的分配。</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;MeasureSpec&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;进位大小为2的30次方(int的大小为32位,所以进位30位就是要使用int的最高位和倒数第二位也就是32和31位做标志位)</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;MODE_SHIFT&nbsp;=&nbsp;</span><span class="number">30</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;运算遮罩,0x3为16进制,10进制为3,二进制为11。3向左进位30,就是11&nbsp;00000000000(11后跟30个0)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;(遮罩的作用是用1标注需要的值,0标注不要的值。因为1与任何数做与运算都得任何数,0与任何数做与运算都得0)</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;MODE_MASK&nbsp;&nbsp;=&nbsp;</span><span class="number">0x3</span><span>&nbsp;&lt;&lt;&nbsp;MODE_SHIFT;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;0向左进位30,就是00&nbsp;00000000000(00后跟30个0)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;UNSPECIFIED&nbsp;=&nbsp;</span><span class="number">0</span><span>&nbsp;&lt;&lt;&nbsp;MODE_SHIFT;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;1向左进位30,就是01&nbsp;00000000000(01后跟30个0)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;EXACTLY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;</span><span class="number">1</span><span>&nbsp;&lt;&lt;&nbsp;MODE_SHIFT;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;2向左进位30,就是10&nbsp;00000000000(10后跟30个0)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;AT_MOST&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;</span><span class="number">2</span><span>&nbsp;&lt;&lt;&nbsp;MODE_SHIFT;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据提供的size和mode得到一个详细的测量结果</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;measureSpec&nbsp;=&nbsp;size&nbsp;+&nbsp;mode;&nbsp;&nbsp;&nbsp;(注意:二进制的加法,不是10进制的加法!)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;这里设计的目的就是使用一个32位的二进制数,32和31位代表了mode的值,后30位代表size的值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;例如size=100(4),mode=AT_MOST,则measureSpec=100+10000...00=10000..00100</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;makeMeasureSpec(</span><span class="keyword">int</span><span>&nbsp;size,&nbsp;</span><span class="keyword">int</span><span>&nbsp;mode)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;size&nbsp;+&nbsp;mode;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过详细测量结果获得mode</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;mode&nbsp;=&nbsp;measureSpec&nbsp;&amp;&nbsp;MODE_MASK;</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;MODE_MASK&nbsp;=&nbsp;11&nbsp;00000000000(11后跟30个0),原理是用MODE_MASK后30位的0替换掉measureSpec后30位中的1,再保留32和31位的mode值。</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;例如10&nbsp;00..00100&nbsp;&amp;&nbsp;11&nbsp;00..00(11后跟30个0)&nbsp;=&nbsp;10&nbsp;00..00(AT_MOST),这样就得到了mode的值</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;getMode(</span><span class="keyword">int</span><span>&nbsp;measureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;(measureSpec&nbsp;&amp;&nbsp;MODE_MASK);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;通过详细测量结果获得size</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;size&nbsp;=&nbsp;measureSpec&nbsp;&amp;&nbsp;~MODE_MASK;</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;原理同上,不过这次是将MODE_MASK取反,也就是变成了00&nbsp;111111(00后跟30个1),将32,31替换成0也就是去掉mode,保留后30位的size</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;getSize(</span><span class="keyword">int</span><span>&nbsp;measureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;(measureSpec&nbsp;&amp;&nbsp;~MODE_MASK);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;重写的toString方法,打印mode和size的信息,这里省略</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;toString(</span><span class="keyword">int</span><span>&nbsp;measureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">null</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><span style="font-family:Arial; font-size:24px; color:#cc00; line-height:26px"><strong><br>
</strong></span></span></p>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><span style="font-family:Arial; font-size:24px; color:#cc00; line-height:26px"><strong>源码中的onMeasure()</strong></span><span style="font-family:Arial; font-size:24px; color:#cc00; line-height:26px"><strong>:</strong></span><br>
</span></p>
<p><span style="font-size:18px"><span style="font-family:Arial; color:#333333; line-height:26px">知道了widthMeasureSpec和heightMeasureSpec是什么以后</span><span style="font-family:Arial; color:#333333; line-height:26px">,我们就可以来看onMeasure方法了:</span></span></p>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 2691px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_2" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=2&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;这个方法需要被重写,应该由子类去决定测量的宽高值,</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onMeasure(</span><span class="keyword">int</span><span>&nbsp;widthMeasureSpec,&nbsp;</span><span class="keyword">int</span><span>&nbsp;heightMeasureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),&nbsp;widthMeasureSpec),&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getDefaultSize(getSuggestedMinimumHeight(),&nbsp;heightMeasureSpec));&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<p><span style="color:rgb(51,51,51); font-family:Arial; line-height:26px"><span style="font-size:18px">在onMeasure中只调用了setMeasuredDimension()方法,接受两个参数,这两个参数是通过<span style="font-family:Arial; color:#333333; line-height:26px">getDefaultSize方法得到的,我们到源码里看看<span style="font-family:Arial; color:#333333; line-height:26px">getDefaultSize究竟做了什么</span></span>。</span></span></p>
<p><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><strong><span style="font-size:24px; color:#cc0000">getDefaultSize():</span></strong></span><br>
</span></p>
<p><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 2976px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_3" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=3&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;*&nbsp;作用是返回一个默认的值,如果MeasureSpec没有强制限制的话则使用提供的大小.否则在允许范围内可任意指定大小</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;*&nbsp;第一个参数size为提供的默认大小,第二个参数为测量的大小</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;getDefaultSize(</span><span class="keyword">int</span><span>&nbsp;size,&nbsp;</span><span class="keyword">int</span><span>&nbsp;measureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;result&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;specMode&nbsp;=&nbsp;MeasureSpec.getMode(measureSpec);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;specSize&nbsp;=&nbsp;MeasureSpec.getSize(measureSpec);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">switch</span><span>&nbsp;(specMode)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;Mode&nbsp;=&nbsp;UNSPECIFIED,AT_MOST时使用提供的默认大小</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.UNSPECIFIED:&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.AT_MOST:&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;Mode&nbsp;=&nbsp;EXACTLY时使用测量的大小&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.EXACTLY:&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;specSize;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;result;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;}&nbsp;&nbsp;</span></li></ol>
</div>
<span style="color:rgb(51,51,51); font-family:Arial; line-height:26px"><span style="font-size:18px">getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),这里就是获取最小宽度作为默认值,然后再根据具体的测量值和选用的模式来得到<span style="color:rgb(51,51,51); font-family:Arial; line-height:26px">widthMeasureSpec。<span style="font-family:Arial; color:#333333; line-height:26px">heightMeasureSpec同理。之后将<span style="font-family:Arial; color:#333333; line-height:26px">widthMeasureSpec,</span><span style="font-family:Arial; color:#333333; line-height:26px">heightMeasureSpec传入<span style="font-family:Arial; color:#333333; line-height:26px">setMeasuredDimension()方法。</span></span></span></span></span></span>
<p><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"><span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px"><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><span style="font-family:Arial; font-size:14px; color:#333333; line-height:26px"><br>
</span></span></span></span></span></p>
<p><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><span style="font-family:Arial; line-height:26px"><span style="font-size:24px; color:#cc0000"><strong>setMeasuredDimension():</strong></span></span></span></span></span></span></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 3634px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_4" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=4&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;这个方法必须由onMeasure(int,&nbsp;int)来调用,来存储测量的宽,高值。</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setMeasuredDimension(</span><span class="keyword">int</span><span>&nbsp;measuredWidth,&nbsp;</span><span class="keyword">int</span><span>&nbsp;measuredHeight)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;mMeasuredWidth&nbsp;=&nbsp;measuredWidth;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;mMeasuredHeight&nbsp;=&nbsp;measuredHeight;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;mPrivateFlags&nbsp;|=&nbsp;PFLAG_MEASURED_DIMENSION_SET;&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<span style="font-size:18px">这个方法就是我们重写onMeasure()所要实现的最终目的。它的作用就是存储我们测量好的宽高值。</span>
<p><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-size:18px">这下思路清晰了,现在的任务就是<span style="font-family:Arial; color:#333333; line-height:26px">计算出准确</span>的measuredWidth和heightMeasureSpec并传递进去,我们所有<span style="font-family:Arial; color:#333333; line-height:26px">的测量任务就算完成了。</span></span></span></p>
<p><span style="color:rgb(51,51,51); font-family:Arial; line-height:26px"><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-size:18px">源码中使用的<span style="font-family:Arial; color:#333333; line-height:26px">getDefaultSize()只是简单的测量了宽高值,在实际使用时需要精细、具体的测量。而</span>具体的测量任务就交给我们在子类中重写的onMeasure方法。</span></span></span></p>
<p><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-family:Arial; color:#333333; line-height:26px"><span style="font-size:18px"><br>
</span></span></span></p>
<p><span style="font-family:Arial; line-height:26px"><span style="font-size:24px; color:#cc00"><strong>在子类中重写的onMeasure:</strong></span></span></p>
<p><span style="font-size:18px">在测量之前首先要明确一点,需要测量的是一个View(例如TextView),还是一个ViewGroup(例如LinearLayout),还是多个ViewGroup嵌套。如果只有一个View的话我们就测量这一个就可以了,如果有多个View或者ViewGroup嵌套我们就需要循环遍历视图中所有的View。</span></p>
<p><span style="font-size:18px">下面列出一个最简单的小例子,写一个自定义类CostomViewGroup继承自ViewGroup,然后重写它的构造方法,onMeasure和onLayout方法。用这个自定义的ViewGroup去写一个布局文件如下:</span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 4331px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_5" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_5" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=5&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span>&lt;com.gxy.text.CostomViewGroup&nbsp;xmlns:android=</span><span class="string">"http://schemas.android.com/apk/res/android"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;android:layout_width=<span class="string">"match_parent"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;android:layout_height=<span class="string">"match_parent"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;android:background=<span class="string">"#bbbaaa"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Button&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:text=<span class="string">"@string/hello_world"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_width=<span class="string">"match_parent"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:layout_height=<span class="string">"wrap_content"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:background=<span class="string">"#aaabbb"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;android:id=<span class="string">"@+id/textView1"</span><span>&nbsp;/&gt;&nbsp;&nbsp;</span></span></li><li><span>&lt;/com.gxy.text.CostomViewGroup&gt;&nbsp;&nbsp;</span></li></ol>
</div>
<span style="font-size:18px">将一个Button放入自定义的ViewGroup中,然后在MainActivity的onCreate回调方法中调用setContentView把整个布局文件设置进去。</span>
<p><span style="font-size:18px">最后看一下自定义CostomViewGroup中的onMeasure方法的内容:</span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 4704px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_6" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_6" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=6&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onMeasure(</span><span class="keyword">int</span><span>&nbsp;widthMeasureSpec,&nbsp;</span><span class="keyword">int</span><span>&nbsp;heightMeasureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//调用ViewGroup类中测量子类的方法</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;measureChildren(widthMeasureSpec,&nbsp;heightMeasureSpec);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//调用View类中默认的测量方法</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">super</span><span>.onMeasure(widthMeasureSpec,heightMeasureSpec);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<p><span style="font-size:18px">本文只是介绍测量,所以onLayout方法先省略,下面来看看效果图:</span></p>
<p><img src="http://img.blog.csdn.net/20140716223856156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</p>
<span style="font-size:18px">在子类重写的onMeasure中只调用两个方法,第一个是父类的onMeasure方法,之前已经介绍了它的作用,它最后会调用<span style="font-family:Arial; color:#333333; line-height:26px">setMeasuredDimension()将测量好的宽高值传递进去。第二个会调用measureChildren方法,它的作用是测量所有的子View,下面我们看看它是如何工作的。</span></span>
<p><span style="font-size:24px; color:#cc00"><strong>measureChildren()</strong></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 5705px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_7" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_7" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=7&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span>&nbsp;</span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;遍历所有的子view去测量自己(跳过GONE类型View)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;widthMeasureSpec&nbsp;父视图的宽详细测量值</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;heightMeasureSpec&nbsp;父视图的高详细测量值</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;measureChildren(</span><span class="keyword">int</span><span>&nbsp;widthMeasureSpec,&nbsp;</span><span class="keyword">int</span><span>&nbsp;heightMeasureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;size&nbsp;=&nbsp;mChildrenCount;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;View[]&nbsp;children&nbsp;=&nbsp;mChildren;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;size;&nbsp;++i)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;View&nbsp;child&nbsp;=&nbsp;children[i];&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;((child.mViewFlags&nbsp;&amp;&nbsp;VISIBILITY_MASK)&nbsp;!=&nbsp;GONE)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;measureChild(child,&nbsp;widthMeasureSpec,&nbsp;heightMeasureSpec);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<span style="font-size:18px">代码很简单,就是遍历所有的子View,如果View的状态不是GONE就调用measureChild去进行下一步的测量</span>
<p><br>
</p>
<p><span style="font-size:24px; color:#cc0000"><strong>measureChild()</strong></span><br>
</p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 6170px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_8" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;测量单个视图,将宽高和padding加在一起后交给getChildMeasureSpec去获得最终的测量值</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;child&nbsp;需要测量的子视图</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;parentWidthMeasureSpec&nbsp;父视图的宽详细测量值</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;parentHeightMeasureSpec&nbsp;父视图的高详细测量值</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;measureChild(View&nbsp;child,&nbsp;</span><span class="keyword">int</span><span>&nbsp;parentWidthMeasureSpec,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;parentHeightMeasureSpec)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;取得子视图的布局参数</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;LayoutParams&nbsp;lp&nbsp;=&nbsp;child.getLayoutParams();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;通过getChildMeasureSpec获取最终的宽高详细测量值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;childWidthMeasureSpec&nbsp;=&nbsp;getChildMeasureSpec(parentWidthMeasureSpec,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPaddingLeft&nbsp;+&nbsp;mPaddingRight,&nbsp;lp.width);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">final</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;childHeightMeasureSpec&nbsp;=&nbsp;getChildMeasureSpec(parentHeightMeasureSpec,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPaddingTop&nbsp;+&nbsp;mPaddingBottom,&nbsp;lp.height);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;将计算好的宽高详细测量值传入measure方法,完成最后的测量</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;child.measure(childWidthMeasureSpec,&nbsp;childHeightMeasureSpec);&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<p><br>
</p>
<p><span style="font-size:24px; color:#cc0000"><strong>getChildMeasureSpec()</strong></span></p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><strong>[java]</strong> <a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="ViewSource" title="view plain">
view plain</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="CopyToClipboard" title="copy">copy</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="PrintSource" title="print">print</a><a target="_blank" href="http://blog.csdn.net/a396901990/article/details/36475213#" class="About" title="?">?</a><a target="_blank" href="https://code.csdn.net/snippets/428404" title="在CODE上查看代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/CODE_ico.png" alt="在CODE上查看代码片" height="12" width="12" style="position:relative; top:1px; left:2px"></a><a target="_blank" href="https://code.csdn.net/snippets/428404/fork" title="派生到我的代码片" style="text-indent:0"><img src="https://code.csdn.net/assets/ico_fork.svg" alt="派生到我的代码片" height="12" width="12" style="position:relative; top:2px; left:2px"></a><div style="position: absolute; left: 514px; top: 6658px; width: 18px; height: 18px; z-index: 99;"><embed id="ZeroClipboardMovie_9" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="18" height="18" name="ZeroClipboardMovie_9" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&amp;width=18&amp;height=18" wmode="transparent"></div></div>
</div>
<ol class="dp-j" start="1">
<li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;在measureChildren中最难的部分:找出传递给child的MeasureSpec。</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;目的是结合父view的MeasureSpec与子view的LayoutParams信息去找到最好的结果</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;(也就是说子view的确切大小由两方面共同决定:1.父view的MeasureSpec&nbsp;2.子view的LayoutParams属性)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;spec&nbsp;父view的详细测量值(MeasureSpec)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;padding&nbsp;view当前尺寸的的内边距和外边距(padding,margin)</span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;childDimension&nbsp;child在当前尺寸下的布局参数宽高值(LayoutParam.width,height)</span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;getChildMeasureSpec(</span><span class="keyword">int</span><span>&nbsp;spec,&nbsp;</span><span class="keyword">int</span><span>&nbsp;padding,&nbsp;</span><span class="keyword">int</span><span>&nbsp;childDimension)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//父view的模式和大小</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;specMode&nbsp;=&nbsp;MeasureSpec.getMode(spec);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;specSize&nbsp;=&nbsp;MeasureSpec.getSize(spec);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//通过父view计算出的子view&nbsp;=&nbsp;父大小-边距(父要求的大小,但子view不一定用这个值)&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;size&nbsp;=&nbsp;Math.max(</span><span class="number">0</span><span>,&nbsp;specSize&nbsp;-&nbsp;padding);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//子view想要的实际大小和模式(需要计算)</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;resultSize&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;resultMode&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//通过1.父view的MeasureSpec&nbsp;2.子view的LayoutParams属性这两点来确定子view的大小</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">switch</span><span>&nbsp;(specMode)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当父view的模式为EXACITY时,父view强加给子view确切的值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.EXACTLY:&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当子view的LayoutParams&gt;0也就是有确切的值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;&gt;=&nbsp;</span><span class="number">0</span><span>)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//子view大小为子自身所赋的值,模式大小为EXACTLY</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;childDimension;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.EXACTLY;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当子view的LayoutParams为MATCH_PARENT时(-1)</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.MATCH_PARENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//子view大小为父view大小,模式为EXACTLY</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.EXACTLY;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当子view的LayoutParams为WRAP_CONTENT时(-2)&nbsp;&nbsp;&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.WRAP_CONTENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//子view决定自己的大小,但最大不能超过父view,模式为AT_MOST</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.AT_MOST;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当父view的模式为AT_MOST时,父view强加给子view一个最大的值。</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.AT_MOST:&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;道理同上</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;&gt;=&nbsp;</span><span class="number">0</span><span>)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;childDimension;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.EXACTLY;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.MATCH_PARENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.AT_MOST;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.WRAP_CONTENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;size;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.AT_MOST;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;当父view的模式为UNSPECIFIED时,子view为想要的值</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">case</span><span>&nbsp;MeasureSpec.UNSPECIFIED:&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;&gt;=&nbsp;</span><span class="number">0</span><span>)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;子view大小为子自身所赋的值</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;childDimension;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.EXACTLY;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.MATCH_PARENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;因为父view为UNSPECIFIED,所以MATCH_PARENT的话子类大小为0</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;<span class="number">0</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.UNSPECIFIED;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">else</span><span>&nbsp;</span><span class="keyword">if</span><span>&nbsp;(childDimension&nbsp;==&nbsp;LayoutParams.WRAP_CONTENT)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;因为父view为UNSPECIFIED,所以WRAP_CONTENT的话子类大小为0</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSize&nbsp;=&nbsp;<span class="number">0</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultMode&nbsp;=&nbsp;MeasureSpec.UNSPECIFIED;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">break</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;MeasureSpec.makeMeasureSpec(resultSize,&nbsp;resultMode);&nbsp;&nbsp;</span></span></li><li class="alt"><span>}&nbsp;&nbsp;</span></li></ol>
</div>
<p><span style="font-size:18px">可能看完后感觉有点迷糊,接下来通过几个例子演示一下,可能大家就会对getChildMeasureSpec方法中的逻辑清晰一些。</span></p>
<p><span style="font-size:18px"><br>
</span></p>
<p><span style="font-size:18px">1.当父类View中宽高都为MATCH_PARENT(EXACTLY)时,宽高都为MATCH_PARENT(EXACTLY)时:</span></p>
<p><span style="font-size:18px">2.当父类View中宽高都为MATCH_PARENT(EXACTLY)时,宽高都为WRAP_CONTENT(EXACTLY)时:<br>
</span></p>
<p><span style="font-size:18px">3.当父类View中宽高都为MATCH_PARENT(EXACTLY)时。子类宽WRAP_CONTENT(AT_MOST),高为MATCH_PARENT(EXACTLY)时:</span><br>
</p>
<p><img src="http://img.blog.csdn.net/20140716232208687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><img src="http://img.blog.csdn.net/20140716233105536?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><img src="http://img.blog.csdn.net/20140716232846593?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</p>
<p><span style="font-size:18px"><br>
</span></p>
<p><span style="font-size:18px">1.当父类View中宽高都为WRAP_CONTENT(AT_MOST)时,子类宽高都为MATCH_PARENT(EXACTLY)时:</span></p>
<p><span style="font-size:18px">2.当父类View中宽高都为WRAP_CONTENT(AT_MOST)时。子类宽WRAP_CONTENT(AT_MOST),高为MATCH_PARENT(EXACTLY)时:</span></p>
<p><img src="http://img.blog.csdn.net/20140716233403002?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">&nbsp;<img src="http://img.blog.csdn.net/20140717002350329?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTM5NjkwMTk5MA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""></p>
<p><span style="font-size:18px">通过这两组简单的对比,其实大家就可以把测量子类大小的代码理解为:</span></p>
<p><span style="font-size:18px">父类中MATCH_PARENT,WRAP_CONTENT,指定值和子类中的MATCH_PARENT,WRAP_CONTENT,指定值这两对值的相互作用。</span></p>
<p><span style="font-size:18px">更复杂的情况则需要加上padding内边距和margin外边距等等一些其他对于View大小的约束。</span></p>
<p><br>
</p>
<p><span style="font-size:24px; color:#cc0000"><strong>总结:</strong></span></p>
<p><span style="font-size:18px">今天介绍的都是系统提供的测量方法,除了这些以外还有一些其他的,大家可以看看源码。而且在真正的自定义View视图时,很大一部分都是借助这些系统提供的现成方法,并且根据需求再加上自己的特殊逻辑(当然也可以全部用自己的逻辑,但我们不要重复制造轮子)。</span></p>
<p><span style="font-size:18px">这篇文章写了2个礼拜,写之前思路非常清晰,但是在写的时候越写越乱。写完以后感觉逻辑仍然不是很清晰,因为有的内容我也是一知半解比如UNSPECIFIED。如果大家水平和我差不多都是菜鸟级别的,希望大家不要深入的去研究源码逻辑,这样会导致越来越来混乱,从应用的角度出发可能会更好一些。</span></p>
<p><span style="font-size:18px">下面会接着写onLayout和LayoutParams的相关内容。最后再将onMeasure,onLayout结合起来写一个完整的例子。也许这些都写完以后会对整个流程的思路会更加清晰。</span></p>
<p><span style="font-size:18px">来源:http://blog.csdn.net/a396901990/article/details/36475213</span></p>
<p><span style="font-size:18px"><br>
</span></p>


</div>








<!-- Baidu Button BEGIN -->


<div class="bdsharebuttonbox bdshare-button-style0-16" style="float: right;" data-bd-bind="1411716159256">
<a href="#" class="bds_more" data-cmd="more" style="background-position:0 0 !important; background-image: url(http://bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png) !important"></a>
<a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间" style="background-position:0 -52px !important"></a>
<a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博" style="background-position:0 -104px !important"></a>
<a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博" style="background-position:0 -260px !important"></a>
<a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网" style="background-position:0 -208px !important"></a>
<a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信" style="background-position:0 -1612px !important"></a>
</div>
<script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script>
<!-- Baidu Button END -->


<!--192.168.100.35-->
<ul class="article_next_prev">
            <li class="prev_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian']);location.href='/easyer2012/article/details/37872457';">上一篇</span><a href="/easyer2012/article/details/37872457" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">Android UI开发第二十四篇——Action Bar</a></li>
            <li class="next_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian']);location.href='/easyer2012/article/details/38346695';">下一篇</span><a href="/easyer2012/article/details/38346695" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">log4j使用简介</a></li>
</ul>


<!-- Baidu Button BEGIN -->
<script type="text/javascript" id="bdshare_js" data="type=tools&amp;uid=1536434" src="http://bdimg.share.baidu.com/static/js/bds_s_v2.js?cdnversion=392144"></script>


<script type="text/javascript">
    document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
</script>
<!-- Baidu Button END -->




</div>
0 0