转载请注明出处:王亟亟的大牛之路
我们过去经常使用传统的RelativeLayout,LinearLayout,FrameLayout.以及一些较新的诸如可拉伸的CollapsingToolbarLayout等等都已经多多少少的在项目中使用,早前就已经知晓了百分比布局percent
,但是一直没想到去看,去试验相关的内容,正好今天想到了就写一篇关于他的(貌似是本周的第一篇)
安利下自己的整合库:https://github.com/ddwhan0123/Useful-Open-Source-Android,快来fork,star!!!
废话不多,先贴一下试验的效果:(看上去比传统的样子差不多,别心急,看下去)
在具体贴代码之前,先加以解释,毕竟是官方控件,例子都不需要加太多,让大家理解更重要
这篇主要讲的是RelativeLayout的演化版 PercentRelativeLayout
再顺道提一提一个自定义的PercentLinearLayout
看字面意思大家就很容易理解,一个是百分比的相对布局,一个就是百分比的线性布局。(接下来的例子我们拿的是官方的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">
<ImageView
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%"/>
</android.support.percent.PercentFrameLayout>
直接像引用正常RelativeLayout控件一样往里面一丢,具体的百分比行为在子控件里操作。乍一看就比较清楚,和通常的配置的区别在于 layout_width或者layout_height来控制空间的尺寸而是使用 app:layout_widthPercent=”50%”和 app:layout_heightPercent=”50%”这样的标签来控制大小,大小的具体数值由%决定,当然这里的占比取决于容器父控件的%大小。
那么既然有新标签,那就来介绍下
//长度和宽度在上面已经做出了解释,这里补充一句,如果百分比设定的值太小,并且你仍然设置了layout_width/height="wrap_content"的话,他的尺寸会变成"wrap_content"大小
app:layout_widthPercent
app:layout_heightPercent
//下面这些就是一些间距的设置,跟RelativeLayout类似只是用%作为尺寸大小,其他并没有区别
app:layout_marginPercent
app:layout_marginLeftPercent
app:layout_marginTopPercent
app:layout_marginRightPercent
app:layout_marginBottomPercent
app:layout_marginStartPercent
app:layout_marginEndPercent
//如果你想让你的控件成一定比例的形式诸如16:9你可以设置如下,这将使画面比例16:9(1.78:1)
app:layout_aspectRatio="178%"
详细内容可以看:https://developer.android.com/reference/android/support/percent/PercentRelativeLayout.html
OK,我们来简单的读下源码,再贴例子代码就收工!
整个类本身代码并不太多,也就100行不到,读起来还算轻松,Go
public class PercentRelativeLayout extends RelativeLayout
跟之前预想的一样他是继承于RelativeLayout
在文章的一开始官方有介绍到
If a layout wants to support percentage based dimensions and use this helper class, its LayoutParams subclass must implement this interface.
所以PercentRelativeLayout的一系列实现都与PercentLayoutHelper
相关
private final PercentLayoutHelper mHelper = new PercentLayoutHelper(this);
在源码的开始,就获取了这个Helper的实例用于调用。
//返回默认的布局参数
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
//生成布局参数
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
//尺寸操作,一层一层向里传递
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mHelper.handleMeasuredStateTooSmall()) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
//位置操作,都是mHelper给与相应实现
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mHelper.restoreOriginalParams();
}
内部类,用于给PercentRelativeLayout做布局实现,因为单继承多实现的原则,只能构建一个LayoutParams作为PercentRelativeLayout的实现。
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);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
@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);
}
}
我们再贴下实现的XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="wjj.com.percentdemo.MainActivity">
<ImageView
android:id="@+id/a1"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:background="@drawable/a1"
app:layout_heightPercent="30%"
app:layout_widthPercent="70%" />
<ImageView
android:id="@+id/a3"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_below="@id/a1"
android:background="@drawable/a3"
app:layout_heightPercent="28%"
app:layout_widthPercent="60%" />
<ImageView
android:id="@+id/a2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_below="@id/a1"
android:layout_toRightOf="@+id/a3"
android:background="@drawable/a2"
app:layout_heightPercent="28%"
app:layout_widthPercent="40%" />
<ImageView
android:id="@+id/a4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="@drawable/a4"
app:layout_heightPercent="25%"
app:layout_widthPercent="25%" />
<ImageView
android:layout_below="@id/a2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/a5"
app:layout_heightPercent="35%"
android:layout_centerHorizontal="true"
app:layout_widthPercent="35%"
android:layout_alignParentBottom="true"/>
</android.support.percent.PercentRelativeLayout>
这里再补充下:
最低版本android 2.1 也就是 7 (现在4.0以下的还有吗?再退一步,4.3以下的还有吗?)
源码地址:https://github.com/ddwhan0123/BlogSample/tree/master/PercentDemo
下载地址:https://github.com/ddwhan0123/BlogSample/blob/master/PercentDemo/PercentDemo.zip?raw=true
PercentLinearLayout,这个类,网上抠来的不知道作者,这里也声明下0,0