Android 百分比布局详解及实例代码
android 百分比布局
1.引入:compile 'com.android.support:percent:24.0.0'
2.点开源码可以看到,主要有两个布局类percentframelayout和percentrelativelayout,一个工具类percentlayouthelper。
3.点开布局类比如percentrelativelayout的源码,可以看到实现的很简单。
public class percentrelativelayout extends relativelayout { private final percentlayouthelper mhelper = new percentlayouthelper(this); /**省略若干行构造方法之类的代码**/ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { //重点在这 mhelper.adjustchildren(widthmeasurespec, heightmeasurespec); super.onmeasure(widthmeasurespec, heightmeasurespec); if (mhelper.handlemeasuredstatetoosmall()) { super.onmeasure(widthmeasurespec, heightmeasurespec); } } @override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { super.onlayout(changed, left, top, right, bottom); mhelper.restoreoriginalparams(); } public static class layoutparams extends relativelayout.layoutparams implements percentlayouthelper.percentlayoutparams { private percentlayouthelper.percentlayoutinfo mpercentlayoutinfo; public layoutparams(context c, attributeset attrs) { super(c, attrs); mpercentlayoutinfo = percentlayouthelper.getpercentlayoutinfo(c, attrs); } /**省略若干行构造方法之类的代码**/ @override public percentlayouthelper.percentlayoutinfo getpercentlayoutinfo() { if (mpercentlayoutinfo == null) { mpercentlayoutinfo = new percentlayouthelper.percentlayoutinfo(); } return mpercentlayoutinfo; } @override protected void setbaseattributes(typedarray a, int widthattr, int heightattr) { percentlayouthelper.fetchwidthandheight(this, a, widthattr, heightattr); } } }
就是在onmeasure和onlayout里面调用了percentlayouthelper 的一些方法,另外在里面定义了自己的layoutparams ,而这个layoutparams 也相当简单。
这里关键的一行代码是在onmeasure方法里面,mhelper.adjustchildren(widthmeasurespec, heightmeasurespec);通过percentlayouthelper 的adjustchildren 遍历子view来设置 子view的宽高,宽高在percentlayouthelper 的内部类percentlayoutinfo通过在布局文件中设置的值计算好了。
public void adjustchildren(int widthmeasurespec, int heightmeasurespec) { // calculate available space, accounting for host's paddings int widthhint = view.measurespec.getsize(widthmeasurespec) - mhost.getpaddingleft() - mhost.getpaddingright(); int heighthint = view.measurespec.getsize(heightmeasurespec) - mhost.getpaddingtop() - mhost.getpaddingbottom(); for (int i = 0, n = mhost.getchildcount(); i < n; i++) { //遍历子view来设置 子view的宽高 view view = mhost.getchildat(i); viewgroup.layoutparams params = view.getlayoutparams(); if (debug) { log.d(tag, "should adjust " + view + " " + params); } if (params instanceof percentlayoutparams) { percentlayoutinfo info = ((percentlayoutparams) params).getpercentlayoutinfo(); if (info != null) { if (params instanceof viewgroup.marginlayoutparams) { info.fillmarginlayoutparams(view, (viewgroup.marginlayoutparams) params, widthhint, heighthint); } else { info.filllayoutparams(params, widthhint, heighthint); } } } } }
4.布局中的使用方法:以percentrelativelayout为例
<android.support.percent.percentrelativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background_color" > <textview android:id="@+id/mian_tab_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textcolor="@color/back_green" android:textsize="15sp" android:text="name" /> <imageview app:layout_widthpercent="50%" app:layout_heightpercent="50%" android:src="@drawable/ic_launcher_icon" android:scaletype="fitxy" android:layout_below="@+id/mian_tab_name" android:background="@color/black" /> </android.support.percent.percentrelativelayout>
引入xmlns:app的命名空间,然后app:layout_widthpercent="50%"就可以设置宽高的百分比了。相当简单 。
5.不过在使用的过程中,可能会有一些其他的需求,比如app:layout_widthpercent="50%",app:layout_heightpercent="50%"都是相对于屏幕的宽高的,假如要显示一张正方形的图片,以宽的50%为准呢?这个时候就可以这样写了:
<imageview app:layout_widthpercent="50%" app:layout_aspectratio="100%" android:src="@drawable/ic_launcher_icon" android:scaletype="fitxy" android:layout_below="@+id/mian_tab_name" android:background="@color/cs_black" />
使用layout_aspectratio属性,设置app:layout_aspectratio="100%",layout_aspectratio就是宽高比。这个时候就不要设置app:layout_heightpercent属性了。在percentlayouthelper 里面, 源代码如下:
public void filllayoutparams(viewgroup.layoutparams params, int widthhint, int heighthint) { // preserve the original layout params, so we can restore them after the measure step. mpreservedparams.width = params.width; mpreservedparams.height = params.height; // we assume that width/height set to 0 means that value was unset. this might not // necessarily be true, as the user might explicitly set it to 0. however, we use this // information only for the aspect ratio. if the user set the aspect ratio attribute, // it means they accept or soon discover that it will be disregarded. final boolean widthnotset = (mpreservedparams.miswidthcomputedfromaspectratio || mpreservedparams.width == 0) && (widthpercent < 0); final boolean heightnotset = (mpreservedparams.misheightcomputedfromaspectratio || mpreservedparams.height == 0) && (heightpercent < 0); if (widthpercent >= 0) { params.width = (int) (widthhint * widthpercent); } if (heightpercent >= 0) { params.height = (int) (heighthint * heightpercent); } //这一段代码是关键,如果aspectratio >=0,aspectratio是宽高比 if (aspectratio >= 0) { if (widthnotset) { //如果宽没有设置,就以高为准 params.width = (int) (params.height * aspectratio); // keep track that we've filled the width based on the height and aspect ratio. mpreservedparams.miswidthcomputedfromaspectratio = true; } if (heightnotset) { //如果高没有设置,就以宽为准 params.height = (int) (params.width / aspectratio); // keep track that we've filled the height based on the width and aspect ratio. mpreservedparams.misheightcomputedfromaspectratio = true; } } if (debug) { log.d(tag, "after filllayoutparams: (" + params.width + ", " + params.height + ")"); } }
6.另外,假如我们要定义自己的percentlinearlayout,基本可以直接改一下名字,继承自linearlayout就好了:public class percentlinearlayout extends linearlayout ,在仿照percentrelativelayout里面的layoutparams定义一个自己的layoutparams就好了。
不过官方为什么没有直接提供一个percentlinearlayout 类,而只提供了两个percentframelayout和percentrelativelayout呢?或许是由于linearlayout 本身就有权重属性,自带百分比效果了。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: .NET 单点登录解决方案
下一篇: Android仿微信图片选择器