Hiten's Blog.

Android中简单实现比例布局

字数统计: 465阅读时长: 2 min
2015/12/22 Share

前些时候阅读过google的iosched项目,发现有个自定义布局类:AspectRatioFrameLayout,这个类的代码很简单,却很有用,
就是实现一个高度跟宽度成比例的布局,我觉得在很多实际开发中,都会涉及到这个内容;关于这个保持宽高比的问题,我问了好几个人,
甚至在面试别人的时候也问到过,结果是很多人说没有考虑过这个问题,

也有人跟我说,在代码里获取到控件宽高,然后设按比例重新设置LayoutParams,
这样确实可以实现,但是,未免有点不够优雅,下面来看看google是怎么写的;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class AspectRatioFrameLayout extends FrameLayout {
private float mAspectRatio = 0f;

public AspectRatioFrameLayout(Context context) {
this(context, null, 0);
}

public AspectRatioFrameLayout(Context context, AttributeSet attrs) {

this(context, attrs, 0);
}

public AspectRatioFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//得到自定义控件属性
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.AspectRatioFrameLayout, defStyle, 0);

mAspectRatio = a.getFloat(R.styleable.AspectRatioFrameLayout_aspectRatio, 0);

if (mAspectRatio == 0f) {
throw new IllegalArgumentException("You must specify an aspect ratio when using the " +
"AspectRatioView.");
}
a.recycle();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int width, height;
if (mAspectRatio != 0) {
width = widthSize;
height = (int) (width / mAspectRatio);
int exactWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
int exactHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(exactWidthSpec, exactHeightSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}

代码很简单,mAspectRatio用来设置比例,onMeasure()中首先得到计算好的widthSize,如果mAspectRatio符合规则,height等于width除以mAspectRatio,得到新的宽高,再用MeasureSpec生成新的widthMeasureSpec和heightMeasureSpec,最后,调用super.onMeasure(),剩下的计算工作还是交给super去做。

从上面来看,这个布局并没有重写onLayout方法,所以我设想supeer可以是任何ViewGroup,可以依此写出AspectRatioLinearLayout,AspectRatioRelativeLayout等等布局。

经验证,继承自LinearLayout和RelativeLayout是没有问题的,不会影响到布局的layout属性,OK~~~

CATALOG