androidsupportpercent
目录(?)[+]
一概述二使用
一PercentFrameLayout二 PercentRelativeLayout
三源码分析
一percent相关属性的获取二 onMeasue中重新计算child的尺寸
三实现PercentLinearlayout
一PercentLinearLayout二测试布局
三效果图
转载请标明出处:
http://blog.csdn.net/lmj623565791/article/details/46695347;
本文出自:【张鸿洋的博客】
一、概述
周末游戏打得过猛,于是周天熬夜码代码,周一早上浑浑噩噩的发现android-percent-support-lib-sample这个项目,Google终于开始支持百分比的方式布局了,瞬间脉动回来,啊咧咧。对于这种历史性的时刻,不出篇博客难以表达我内心的激动。
还记得不久前,发了篇博客:Android 屏幕适配方案,这篇博客以Web页面设计引出一种适配方案,最终的目的就是可以通过百分比控制控件的大小。当然了,存在一些问题,比如:
对于没有考虑到屏幕尺寸,可能会出现意外的情况;apk的大小会增加;
当然了android-percent-support这个库,基本可以解决上述问题,是不是有点小激动,稍等,我们先描述下这个support-lib。
这个库提供了:
两种布局供大家使用:
PercentRelativeLayout、PercentFrameLayout,通过名字就可以看出,这是继承自FrameLayout和RelativeLayout两个容器类;
支持的属性有:
layout_widthPercent、layout_heightPercent、
layout_marginPercent、layout_marginLeftPercent、
layout_marginTopPercent、layout_marginRightPercent、
layout_marginBottomPercent、layout_marginStartPercent、layout_marginEndPercent。
可以看到支持宽高,以及margin。
也就是说,大家只要在开发过程中使用PercentRelativeLayout、PercentFrameLayout替换FrameLayout、RelativeLayout即可。
是不是很简单,不过貌似没有LinearLayout,有人会说LinearLayout有weight属性呀。但是,weight属性只能支持一个方向呀~~哈,没事,刚好给我们一个机会去自定义一个PercentLinearLayout。
好了,本文分为3个部分:
PercentRelativeLayout、PercentFrameLayout的使用对上述控件源码分析自定义PercentLinearLayout
二、使用
关于使用,其实及其简单,并且github上也有例子,android-percent-support-lib-sample。我们就简单过一下:
首先记得在build.gradle添加:
<code class="language-xml hljs has-numbering"> compile 'com.android.support:percent:22.2.0'</code><ul class="pre-numbering" style="display: block;"><li>1</li></ul>
(一)PercentFrameLayout
<code class="language-xml hljs has-numbering"><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span> <span class="hljs-tag"><<span class="hljs-title">android.support.percent.PercentFrameLayout </span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">xmlns:app</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_gravity</span>=<span class="hljs-value">"left|top"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#44ff0000"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:30%,height:20%"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"20%"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"30%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_gravity</span>=<span class="hljs-value">"right|top"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#4400ff00"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:70%,height:20%"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"20%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"70%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_gravity</span>=<span class="hljs-value">"bottom"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#770000ff"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:100%,height:10%"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"10%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"100%"</span>/></span> <span class="hljs-tag"></<span class="hljs-title">android.support.percent.PercentFrameLayout</span>></span> </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li></ul>
3个TextView,很简单,直接看效果图:
(二) PercentRelativeLayout
<code class="language-xml hljs has-numbering"><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span> <span class="hljs-tag"><<span class="hljs-title">android.support.percent.PercentRelativeLayout </span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">xmlns:app</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:clickable</span>=<span class="hljs-value">"true"</span>></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/row_one_item_one"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_alignParentTop</span>=<span class="hljs-value">"true"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#7700ff00"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"w:70%,h:20%"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"20%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"70%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/row_one_item_two"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_toRightOf</span>=<span class="hljs-value">"@+id/row_one_item_one"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#396190"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"w:30%,h:20%"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"20%"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"30%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">ImageView </span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/row_two_item_one"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:src</span>=<span class="hljs-value">"@drawable/tangyan"</span> <span class="hljs-attribute">android:scaleType</span>=<span class="hljs-value">"centerCrop"</span> <span class="hljs-attribute">android:layout_below</span>=<span class="hljs-value">"@+id/row_one_item_one"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#d89695"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"70%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_below</span>=<span class="hljs-value">"@id/row_two_item_one"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#770000ff"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:100%,height:10%"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"10%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"100%"</span>/></span> <span class="hljs-tag"></<span class="hljs-title">android.support.percent.PercentRelativeLayout</span>></span> </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li></ul>
ok,依然是直接看效果图:
使用没什么好说的,就是直观的看一下。
三、源码分析
其实细想一下,Google只是对我们原本熟悉的RelativeLayout和FrameLayout进行的功能的扩展,使其支持了percent相关的属性。
那么,我们考虑下,如果是我们添加这种扩展,我们会怎么做:
通过LayoutParams获取child设置的percent相关属性的值onMeasure的时候,将child的width,height的值,通过获取的自定义属性的值进行计算(eg:容器的宽 * fraction ),计算后传入给child.measure(w,h);
ok,有了上面的猜想,我们直接看PercentFrameLayout的源码。
<code class="language-java hljs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PercentFrameLayout</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">FrameLayout</span> {</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> PercentLayoutHelper mHelper = <span class="hljs-keyword">new</span> PercentLayoutHelper(<span class="hljs-keyword">this</span>); <span class="hljs-comment">//省略了,两个构造方法</span> <span class="hljs-keyword">public</span> <span class="hljs-title">PercentFrameLayout</span>(Context context, AttributeSet attrs) { <span class="hljs-keyword">super</span>(context, attrs); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> LayoutParams <span class="hljs-title">generateLayoutParams</span>(AttributeSet attrs) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> LayoutParams(getContext(), attrs); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) { mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">if</span> (mHelper.handleMeasuredStateTooSmall()) { <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); } } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLayout</span>(<span class="hljs-keyword">boolean</span> changed, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> top, <span class="hljs-keyword">int</span> right, <span class="hljs-keyword">int</span> bottom) { <span class="hljs-keyword">super</span>.onLayout(changed, left, top, right, bottom); mHelper.restoreOriginalParams(); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LayoutParams</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">FrameLayout</span>.<span class="hljs-title">LayoutParams</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PercentLayoutHelper</span>.<span class="hljs-title">PercentLayoutParams</span> {</span> <span class="hljs-keyword">private</span> PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; <span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(Context c, AttributeSet attrs) { <span class="hljs-keyword">super</span>(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } <span class="hljs-comment">//省略了一些代码...</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> PercentLayoutHelper.PercentLayoutInfo <span class="hljs-title">getPercentLayoutInfo</span>() { <span class="hljs-keyword">return</span> mPercentLayoutInfo; } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setBaseAttributes</span>(TypedArray a, <span class="hljs-keyword">int</span> widthAttr, <span class="hljs-keyword">int</span> heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(<span class="hljs-keyword">this</span>, a, widthAttr, heightAttr); } } }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li></ul>
代码是相当的短,可以看到PercentFrameLayout里面首先重写了generateLayoutParams方法,当然了,由于支持了一些新的layout_属性,那么肯定需要定义对应的LayoutParams。
(一)percent相关属性的获取
可以看到PercentFrameLayout.LayoutParams在原有的FrameLayout.LayoutParams基础上,实现了PercentLayoutHelper.PercentLayoutParams接口。
这个接口很简单,只有一个方法:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PercentLayoutParams</span> {</span> PercentLayoutInfo getPercentLayoutInfo(); }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li></ul>
而,这个方法的实现呢,也只有一行:return mPercentLayoutInfo;,那么这个mPercentLayoutInfo在哪完成赋值呢?
看PercentFrameLayout.LayoutParams的构造方法:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(Context c, AttributeSet attrs) { <span class="hljs-keyword">super</span>(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
可以看到,将attrs传入给getPercentLayoutInfo方法,那么不用说,这个方法的内部,肯定是获取自定义属性的值,然后将其封装到PercentLayoutInfo对象中,最后返回。
代码如下:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> PercentLayoutInfo <span class="hljs-title">getPercentLayoutInfo</span>(Context context, AttributeSet attrs) { PercentLayoutInfo info = <span class="hljs-keyword">null</span>; TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PercentLayout_Layout); <span class="hljs-keyword">float</span> value = array.getFraction(R.styleable.PercentLayout_Layout_layout_widthPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent width: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.widthPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_heightPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent height: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.heightPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.leftMarginPercent = value; info.topMarginPercent = value; info.rightMarginPercent = value; info.bottomMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginLeftPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent left margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.leftMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginTopPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent top margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.topMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginRightPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent right margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.rightMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginBottomPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent bottom margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.bottomMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginStartPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent start margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.startMarginPercent = value; } value = array.getFraction(R.styleable.PercentLayout_Layout_layout_marginEndPercent, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>f); <span class="hljs-keyword">if</span> (value != -<span class="hljs-number">1</span>f) { <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, <span class="hljs-string">"percent end margin: "</span> + value); } info = info != <span class="hljs-keyword">null</span> ? info : <span class="hljs-keyword">new</span> PercentLayoutInfo(); info.endMarginPercent = value; } array.recycle(); <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"constructed: "</span> + info); } <span class="hljs-keyword">return</span> info; }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li><li>83</li><li>84</li><li>85</li><li>86</li><li>87</li><li>88</li><li>89</li><li>90</li><li>91</li><li>92</li></ul>
是不是和我们平时的取值很类似,所有的值最终封装到PercentLayoutInfo对象中。
ok,到此我们的属性获取就介绍完成,有了这些属性,是不是onMeasure里面要进行使用呢?
(二) onMeasue中重新计算child的尺寸
<code class="language-java hljs has-numbering"><span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) { mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">if</span> (mHelper.handleMeasuredStateTooSmall()) { <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); } }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
可以看到onMeasure中的代码页很少,看来核心的代码都被封装在mHelper的方法中,我们直接看mHelper.adjustChildren方法。
<code class="language-java hljs has-numbering"><span class="hljs-javadoc">/** * Iterates over children and changes their width and height to one calculated from percentage * values. *<span class="hljs-javadoctag"> @param</span> widthMeasureSpec Width MeasureSpec of the parent ViewGroup. *<span class="hljs-javadoctag"> @param</span> heightMeasureSpec Height MeasureSpec of the parent ViewGroup. */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">adjustChildren</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) { <span class="hljs-comment">//...</span> <span class="hljs-keyword">int</span> widthHint = View.MeasureSpec.getSize(widthMeasureSpec); <span class="hljs-keyword">int</span> heightHint = View.MeasureSpec.getSize(heightMeasureSpec); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>, N = mHost.getChildCount(); i < N; i++) { View view = mHost.getChildAt(i); ViewGroup.LayoutParams params = view.getLayoutParams(); <span class="hljs-keyword">if</span> (params <span class="hljs-keyword">instanceof</span> PercentLayoutParams) { PercentLayoutInfo info = ((PercentLayoutParams) params).getPercentLayoutInfo(); <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"using "</span> + info); } <span class="hljs-keyword">if</span> (info != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">if</span> (params <span class="hljs-keyword">instanceof</span> ViewGroup.MarginLayoutParams) { info.fillMarginLayoutParams((ViewGroup.MarginLayoutParams) params, widthHint, heightHint); } <span class="hljs-keyword">else</span> { info.fillLayoutParams(params, widthHint, heightHint); } } } } } </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li></ul>
通过注释也能看出,此方法中遍历所有的孩子,通过百分比的属性重新设置其宽度和高度。
首先在widthHint、heightHint保存容器的宽、高,然后遍历所有的孩子,判断其LayoutParams是否是PercentLayoutParams类型,如果是,通过params.getPercentLayoutInfo拿出info对象。
是否还记得,上面的分析中,PercentLayoutInfo保存了percent相关属性的值。
如果info不为null,则判断是否需要处理margin;我们直接看fillLayoutParams方法(处理margin也是类似的)。
<code class="language-java hljs has-numbering"> <span class="hljs-javadoc">/** * Fills {@code ViewGroup.LayoutParams} dimensions based on percentage values. */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fillLayoutParams</span>(ViewGroup.LayoutParams params, <span class="hljs-keyword">int</span> widthHint, <span class="hljs-keyword">int</span> heightHint) { <span class="hljs-comment">// Preserve the original layout params, so we can restore them after the measure step.</span> mPreservedParams.width = params.width; mPreservedParams.height = params.height; <span class="hljs-keyword">if</span> (widthPercent >= <span class="hljs-number">0</span>) { params.width = (<span class="hljs-keyword">int</span>) (widthHint * widthPercent); } <span class="hljs-keyword">if</span> (heightPercent >= <span class="hljs-number">0</span>) { params.height = (<span class="hljs-keyword">int</span>) (heightHint * heightPercent); } <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"after fillLayoutParams: ("</span> + params.width + <span class="hljs-string">", "</span> + params.height + <span class="hljs-string">")"</span>); } }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>
首先保存原本的width和height,然后重置params的width和height为(int) (widthHint * widthPercent)和(int) (heightHint * heightPercent);。
到此,其实我们的百分比转换就结束了,理论上就已经实现了对于百分比的支持,不过Google还考虑了一些细节。
我们回到onMeasure方法:
<code class="language-java hljs has-numbering"><span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) { mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">if</span> (mHelper.handleMeasuredStateTooSmall()) { <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); } }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
下面还有个mHelper.handleMeasuredStateTooSmall的判断,也就是说,如果你设置的百分比,最终计算出来的MeasuredSize过小的话,会进行一些操作。
代码如下:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">handleMeasuredStateTooSmall</span>() { <span class="hljs-keyword">boolean</span> needsSecondMeasure = <span class="hljs-keyword">false</span>; <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>, N = mHost.getChildCount(); i < N; i++) { View view = mHost.getChildAt(i); ViewGroup.LayoutParams params = view.getLayoutParams(); <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"should handle measured state too small "</span> + view + <span class="hljs-string">" "</span> + params); } <span class="hljs-keyword">if</span> (params <span class="hljs-keyword">instanceof</span> PercentLayoutParams) { PercentLayoutInfo info = ((PercentLayoutParams) params).getPercentLayoutInfo(); <span class="hljs-keyword">if</span> (info != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">if</span> (shouldHandleMeasuredWidthTooSmall(view, info)) { needsSecondMeasure = <span class="hljs-keyword">true</span>; params.width = ViewGroup.LayoutParams.WRAP_CONTENT; } <span class="hljs-keyword">if</span> (shouldHandleMeasuredHeightTooSmall(view, info)) { needsSecondMeasure = <span class="hljs-keyword">true</span>; params.height = ViewGroup.LayoutParams.WRAP_CONTENT; } } } } <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"should trigger second measure pass: "</span> + needsSecondMeasure); } <span class="hljs-keyword">return</span> needsSecondMeasure; }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li></ul>
首先遍历所有的孩子,拿出孩子的layoutparams,如果是PercentLayoutParams实例,则取出info。如果info不为null,调用shouldHandleMeasuredWidthTooSmall判断:
<code class="language-java hljs has-numbering"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">shouldHandleMeasuredWidthTooSmall</span>(View view, PercentLayoutInfo info) { <span class="hljs-keyword">int</span> state = ViewCompat.getMeasuredWidthAndState(view) & ViewCompat.MEASURED_STATE_MASK; <span class="hljs-keyword">return</span> state == ViewCompat.MEASURED_STATE_TOO_SMALL && info.widthPercent >= <span class="hljs-number">0</span> && info.mPreservedParams.width == ViewGroup.LayoutParams.WRAP_CONTENT; }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
这里就是判断,如果你设置的measuredWidth或者measureHeight过小的话,并且你在布局文件中layout_w/h 设置的是WRAP_CONTENT的话,将params.width / height= ViewGroup.LayoutParams.WRAP_CONTENT,然后重新测量。
哈,onMeasure终于结束了~~~现在我觉得应该代码结束了吧,尺寸都设置好了,还需要干嘛么,but,你会发现onLayout也重写了,我们又不改变layout规则,在onLayout里面干什么毛线:
<code class="language-java hljs has-numbering"><span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLayout</span>(<span class="hljs-keyword">boolean</span> changed, <span class="hljs-keyword">int</span> left, <span class="hljs-keyword">int</span> top, <span class="hljs-keyword">int</span> right, <span class="hljs-keyword">int</span> bottom) { <span class="hljs-keyword">super</span>.onLayout(changed, left, top, right, bottom); mHelper.restoreOriginalParams(); }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
继续看mHelper.restoreOriginalParams
<code class="language-java hljs has-numbering"> <span class="hljs-javadoc">/** * Iterates over children and restores their original dimensions that were changed for * percentage values. Calling this method only makes sense if you previously called * {@link PercentLayoutHelper#adjustChildren(int, int)}. */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">restoreOriginalParams</span>() { <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>, N = mHost.getChildCount(); i < N; i++) { View view = mHost.getChildAt(i); ViewGroup.LayoutParams params = view.getLayoutParams(); <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"should restore "</span> + view + <span class="hljs-string">" "</span> + params); } <span class="hljs-keyword">if</span> (params <span class="hljs-keyword">instanceof</span> PercentLayoutParams) { PercentLayoutInfo info = ((PercentLayoutParams) params).getPercentLayoutInfo(); <span class="hljs-keyword">if</span> (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, <span class="hljs-string">"using "</span> + info); } <span class="hljs-keyword">if</span> (info != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">if</span> (params <span class="hljs-keyword">instanceof</span> ViewGroup.MarginLayoutParams) { info.restoreMarginLayoutParams((ViewGroup.MarginLayoutParams) params); } <span class="hljs-keyword">else</span> { info.restoreLayoutParams(params); } } } } } </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li></ul>
噗,原来是重新恢复原本的尺寸值,也就是说onMeasure里面的对值进行了改变,测量完成后。在这个地方,将值又恢复成如果布局文件中的值,上面写的都是0。恢复很简单:
<code class="language-java hljs has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">restoreLayoutParams</span>(ViewGroup.LayoutParams params) { params.width = mPreservedParams.width; params.height = mPreservedParams.height; }</code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
你应该没有忘在哪存的把~忘了的话,麻烦Ctrl+F ‘mPreservedParams.width’ 。
也就是说,你去打印上面写法,布局文件中view的v.getLayoutParams().width,这个值应该是0。
这里感觉略微不爽~这个0没撒用处呀,还不如不重置~~
好了,到此就分析完了,其实主要就几个步骤:
LayoutParams中属性的获取onMeasure中,改变params.width为百分比计算结果,测量如果测量值过小且设置的w/h是wrap_content,重新测量onLayout中,重置params.w/h为布局文件中编写的值
可以看到,有了RelativeLayout、FrameLayout的扩展,竟然没有LinearLayout几个意思。好在,我们的核心代码都由PercentLayoutHelper封装了,自己扩展下LinearLayout也不复杂。
三、实现PercentLinearlayout
可能有人会说,有了weight呀,但是weight能做到宽、高同时百分比赋值嘛?
好了,代码很简单,如下:
(一)PercentLinearLayout
<code class="language-java hljs has-numbering"><span class="hljs-keyword">package</span> com.juliengenoud.percentsamples; <span class="hljs-keyword">import</span> android.content.Context; <span class="hljs-keyword">import</span> android.content.res.TypedArray; <span class="hljs-keyword">import</span> android.support.percent.PercentLayoutHelper; <span class="hljs-keyword">import</span> android.util.AttributeSet; <span class="hljs-keyword">import</span> android.view.ViewGroup; <span class="hljs-keyword">import</span> android.widget.LinearLayout; <span class="hljs-javadoc">/** * Created by zhy on 15/6/30. */</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PercentLinearLayout</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LinearLayout</span> {</span> <span class="hljs-keyword">private</span> PercentLayoutHelper mPercentLayoutHelper; <span class="hljs-keyword">public</span> <span class="hljs-title">PercentLinearLayout</span>(Context context, AttributeSet attrs) { <span class="hljs-keyword">super</span>(context, attrs); mPercentLayoutHelper = <span class="hljs-keyword">new</span> PercentLayoutHelper(<span class="hljs-keyword">this</span>); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onMeasure</span>(<span class="hljs-keyword">int</span> widthMeasureSpec, <span class="hljs-keyword">int</span> heightMeasureSpec) { mPercentLayoutHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); <span class="hljs-keyword">if</span> (mPercentLayoutHelper.handleMeasuredStateTooSmall()) { <span class="hljs-keyword">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec); } } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onLayout</span>(<span class="hljs-keyword">boolean</span> changed, <span class="hljs-keyword">int</span> l, <span class="hljs-keyword">int</span> t, <span class="hljs-keyword">int</span> r, <span class="hljs-keyword">int</span> b) { <span class="hljs-keyword">super</span>.onLayout(changed, l, t, r, b); mPercentLayoutHelper.restoreOriginalParams(); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> LayoutParams <span class="hljs-title">generateLayoutParams</span>(AttributeSet attrs) { <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> LayoutParams(getContext(), attrs); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LayoutParams</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">LinearLayout</span>.<span class="hljs-title">LayoutParams</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PercentLayoutHelper</span>.<span class="hljs-title">PercentLayoutParams</span> {</span> <span class="hljs-keyword">private</span> PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; <span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(Context c, AttributeSet attrs) { <span class="hljs-keyword">super</span>(c, attrs); mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> PercentLayoutHelper.PercentLayoutInfo <span class="hljs-title">getPercentLayoutInfo</span>() { <span class="hljs-keyword">return</span> mPercentLayoutInfo; } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setBaseAttributes</span>(TypedArray a, <span class="hljs-keyword">int</span> widthAttr, <span class="hljs-keyword">int</span> heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(<span class="hljs-keyword">this</span>, a, widthAttr, heightAttr); } <span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(<span class="hljs-keyword">int</span> width, <span class="hljs-keyword">int</span> height) { <span class="hljs-keyword">super</span>(width, height); } <span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(ViewGroup.LayoutParams source) { <span class="hljs-keyword">super</span>(source); } <span class="hljs-keyword">public</span> <span class="hljs-title">LayoutParams</span>(MarginLayoutParams source) { <span class="hljs-keyword">super</span>(source); } } } </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li><li>83</li><li>84</li><li>85</li><li>86</li><li>87</li><li>88</li><li>89</li><li>90</li><li>91</li></ul>
如果你详细看了上面的源码分析,这个代码是不是没撒解释的了~
(二)测试布局
<code class="language-xml hljs has-numbering"><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span> <span class="hljs-tag"><<span class="hljs-title">com.juliengenoud.percentsamples.PercentLinearLayout </span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">xmlns:app</span>=<span class="hljs-value">"http://schemas.android.com/apk/res-auto"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:orientation</span>=<span class="hljs-value">"vertical"</span>></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ff44aacc"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:60%,height:5%"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#ffffff"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"5%"</span> <span class="hljs-attribute">app:layout_marginBottomPercent</span>=<span class="hljs-value">"5%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"60%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ff4400cc"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#ffffff"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:70%,height:10%"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"10%"</span> <span class="hljs-attribute">app:layout_marginBottomPercent</span>=<span class="hljs-value">"5%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"70%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ff44aacc"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:80%,height:15%"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#ffffff"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"15%"</span> <span class="hljs-attribute">app:layout_marginBottomPercent</span>=<span class="hljs-value">"5%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"80%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ff4400cc"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:90%,height:5%"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#ffffff"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"20%"</span> <span class="hljs-attribute">app:layout_marginBottomPercent</span>=<span class="hljs-value">"10%"</span> <span class="hljs-attribute">app:layout_widthPercent</span>=<span class="hljs-value">"90%"</span>/></span> <span class="hljs-tag"><<span class="hljs-title">TextView </span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"0dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#ff44aacc"</span> <span class="hljs-attribute">android:gravity</span>=<span class="hljs-value">"center"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"width:100%,height:25%"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#ffffff"</span> <span class="hljs-attribute">app:layout_heightPercent</span>=<span class="hljs-value">"25%"</span> <span class="hljs-attribute">app:layout_marginBottomPercent</span>=<span class="hljs-value">"5%"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">com.juliengenoud.percentsamples.PercentLinearLayout</span>></span> </code><ul class="pre-numbering" style="display: block;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li></ul>
我们纵向排列的几个TextView,分别设置宽/高都为百分比,且之间的间隔为5%p。
(三)效果图
ok,到此,我们使用、源码分析、扩展PercentLinearLayout就结束了。
添加PercentLinearLayout后的地址:点击查看
扩展下载:android-percent-support-extend 包含android studio, eclipse项目,以及上述源码。
~~have a nice day ~~
新浪微博
群号:463081660
微信公众号:hongyangAndroid
(欢迎关注,第一时间推送博文信息)