之前写过一篇屏幕适配的文章,里面提到了类似百分比布局的东西,可是该方法缺点非常明显,就会添加非常多没用的数据,导致apk包变大。
而谷歌的support库中,添加了一个叫做percent库。该库在如图文件夹下,假设没有,请使用sdk manager更新至最新
在使用前,我们先看下这个库有哪些类
非常明显里面有一个FrameLayout布局的子类和RelativeLayout布局的子类。此外另一个Helper类。这个Helper类主要是完毕百分比的測量工作。里面有一个接口PercentLayoutParams,假设我们自己要实现百分比布局,那么就要实现这个接口。
我们看下谷歌对外发布了什么自己定义属性
>
<resources> <declare-styleable name="PercentLayout_Layout"> <attr name="layout_widthPercent" format="fraction"/> <attr name="layout_heightPercent" format="fraction"/> <attr name="layout_marginPercent" format="fraction"/> <attr name="layout_marginLeftPercent" format="fraction"/> <attr name="layout_marginTopPercent" format="fraction"/> <attr name="layout_marginRightPercent" format="fraction"/> <attr name="layout_marginBottomPercent" format="fraction"/> <attr name="layout_marginStartPercent" format="fraction"/> <attr name="layout_marginEndPercent" format="fraction"/> </declare-styleable> </resources>
看到这些属性应该能直接明确这些属性的意思,其属性值类型为fraction。即小数,百分比。主要属性有宽度,高度占是百分比,外边距的百分比,当中Android MarginLeft与MarginStart的差别參考。提取关键内容例如以下。
在写layout布局的时候,我们会发现有这样几个比較类似的属性:
MarginStart MarginLeft MarginEnd MarginRight这些属性的差别是什么? 依据api凝视,我们得知MarginStart指的是控件距离开头View部分的间距大小。MarginLeft则指的是控件距离左边View部分的间距大小,MarginEnd和MarginRight同理。
普通情况下,View開始部分就是左边,可是有的语言眼下为止还是依照从右往左的顺序来书写的,比如阿拉伯语。在Android 4.2系统之后,Google在Android中引入了RTL布局,更好了支持了由右到左文字布局的显示,为了更好的兼容RTL布局,google推荐使用MarginStart和MarginEnd来替代MarginLeft和MarginRight,这样应用能够在正常的屏幕和由右到左显示文字的屏幕上都保持一致的用户体验。
了解了这些后,我们開始使用PercentRelativeLayout
使用前添加库文件依赖
compile 'com.android.support:percent:22.2.0'
開始编写布局文件。我们要实现的效果如图所看到的
即左边红色部分宽度占屏幕30%,高度占屏幕90%,右边宽度占屏幕70%。高度各占屏幕45%。
在不使用百分比布局之前。我们通常是使用LinearLayout的weight达到这样的效果,然而使用weight会添加布局的嵌套。会过度绘制。那么使用百分比布局会变成什么样的,无需布局嵌套,设置高度宽度百分比就可以。
我们要设置左边的布局宽度占30%,使用app:layout_widthPercent=”30%”,高度占90%,为了演示另一个属性的使用,这里不直接设置高度为90%,而是设置高度为100%,底边距为10%,即
android:layout_alignParentBottom="true"app:layout_heightPercent="100%"app:layout_marginBottomPercent="10%"
同理编写右边两个的布局。
正如文章开头看到的,这个库仅仅提供了两个百分比布局给我们使用,比較常见的线性布局并没有提供相应的百分比布局。
因此。我们想能不能自己实现一个呢,答案是肯定的。通过观察现有的两个百分比布局的代码。我们需呀继承原来的布局。即LinearLayout。编写相应的构造方法调用父类。声明一个PercentLayoutHelper对象辅助完毕百分比測量。此外还须要重写onMeasure和onLayout方法,以及一个
实现了PercentLayoutHelper.PercentLayoutParams接口的继承原来布局的LayoutParams的LayoutParams。那么我们新建一个叫PercentLinearLayout的继承LinearLayout的类,实现其构造方法。以及声明一个final的PercentLayoutHelper 对象。
public class PercentLinearLayout extends LinearLayout { private final PercentLayoutHelper mHelper = new PercentLayoutHelper(this); public PercentLinearLayout(Context context) { super(context); } public PercentLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public PercentLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }}
仿造现有的两个百分比布局实现内部类LayoutParams ,这一步直接复制代码改动一下就可以,记得一定要继承自android.widget.LinearLayout.LayoutParams。
public static class LayoutParams extends android.widget.LinearLayout.LayoutParams implements PercentLayoutHelper.PercentLayoutParams { private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); this.mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs); } public LayoutParams(int width, int height) { super(width, height); } public LayoutParams(android.view.ViewGroup.LayoutParams source) { super(source); } public LayoutParams(MarginLayoutParams source) { super(source); } public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() { return this.mPercentLayoutInfo; } protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr); } }
此外,还要重写一个生成LayoutParams 的方法generateLayoutParams,返回我们的内部类。
@Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new PercentLinearLayout.LayoutParams(this.getContext(), attrs); }
然后又一次onLayout和onMeasure方法就可以,这一步也不须要自己实现,直接复制代码就可以。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { this.mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(this.mHelper.handleMeasuredStateTooSmall()) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); this.mHelper.restoreOriginalParams(); }
就这样,完毕了百分比线性布局,我们进行使用下。完毕以下的效果,任意发挥的涂鸦。
主要是红色部分,从上到下,高度各为父容器的20%,30%,30%。宽度各为父容器的30%,50%,40。当中第三个靠右边布局,右边距为父容器的20%。同一时候有上边距为父容器的10%,看代码更直接
怎么样,是不是轻轻松松就实现了百分比布局,很多其它内容自行挖掘,以下上源代码
eclipse可用的库请见下载链接,将该项目导入eclipse中去,依赖该项目就可以使用百分比布局.