原理:以父容器尺寸为参考,在View的加载过程,根据当前父容器的实际尺寸计算出目标尺寸,再作用在view上。
例如:设计师给的布局像素是720 * 1080,布局中有一个view的宽度是360px,为屏幕宽度的一半,如果我们再手机像素为1080 * 1920的手机上设置宽度为360px时,显然不合适,正常的宽度应该是540px,这里我们可以通过设置比例的方式来实现,比如设置为屏幕宽度的0.5。
下面以RelativeLayout为例自定义布局。创建PercentLayout继承RelativeLayout。在attr.xml文件中设置自定义属性。
1.代码实现:
复制代码
java代码实现:
public class PercentLayout extends RelativeLayout { public PercentLayout(Context context) { super(context); } public PercentLayout(Context context, AttributeSet attrs) { super(context, attrs); } public PercentLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //测量之前先对view百分比设置 //获取父容器的宽高 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int count = getChildCount(); for (int i = 0; i < count; i++) { //重新设置子view的布局属性,再进行View的测量 View child = getChildAt(i); ViewGroup.LayoutParams params = child.getLayoutParams(); if (checkLayoutParams(params)) { LayoutParams layoutParams = (LayoutParams) params; //强转成layoutParams //获取百分比属性 float widthPercent = layoutParams.widthPercent; float heightPercent = layoutParams.heightPercent; float marginLeftPercent = layoutParams.marginLeftPercent; float marginRightPercent = layoutParams.marginRightPercent; float marginTopPercent = layoutParams.marginTopPercent; float marginBottomPercent = layoutParams.marginBottomPercent; if (widthPercent > 0) { //赋值成功 layoutParams.width = (int) (widthSize * widthPercent); //尺寸大小为:父容器宽*百分比 } if (heightPercent > 0) { layoutParams.height = (int) (heightSize * heightPercent); } if (marginLeftPercent > 0) { layoutParams.leftMargin = (int) (widthSize * marginLeftPercent); } if (marginRightPercent > 0) { layoutParams.rightMargin = (int) (widthSize * marginRightPercent); } if (marginTopPercent > 0) { layoutParams.topMargin = (int) (heightSize * marginTopPercent); } if (heightPercent > 0) { layoutParams.bottomMargin = (int) (heightSize * marginBottomPercent); } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } //用于LayoutParams的判断,判断是否为当前类的子类(参考RelativeLayout中的此方法) @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p instanceof LayoutParams; //判断是否是PercentLayout.LayoutParams } //重写此方法,用于返回我们内部创建的LayoutParams(参考RelativeLayout中的此方法) @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new LayoutParams(getContext(), attrs); } //这里参考RelativeLayout中将自定属性封装在LayoutParams中 public static class LayoutParams extends RelativeLayout.LayoutParams { private float heightPercent; private float widthPercent; private float marginLeftPercent; private float marginRightPercent; private float marginTopPercent; private float marginBottomPercent; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); //添加自定义属性 TypedArray typedArray = c.obtainStyledAttributes(attrs, R.styleable.PercentLayout); heightPercent = typedArray.getFloat(R.styleable.PercentLayout_heightPercent, 0); widthPercent = typedArray.getFloat(R.styleable.PercentLayout_widthPercent, 0); marginLeftPercent = typedArray.getFloat(R.styleable.PercentLayout_marginLeftPercent, 0); marginRightPercent = typedArray.getFloat(R.styleable.PercentLayout_marginRightPercent, 0); marginTopPercent = typedArray.getFloat(R.styleable.PercentLayout_marginTopPercent, 0); marginBottomPercent = typedArray.getFloat(R.styleable.PercentLayout_marginBottomPercent, 0); typedArray.recycle(); } }}复制代码
2.xml布局文件中设置子view的百分比:
这里我们设置了宽高都是为屏幕的0.5。
复制代码
3.运行效果: