自定义布局之宽高比布局的实现

最近在项目中遇到一个屏幕适配的问题,在显示图片时我在布局中宽度和高度都设置了固定的dp值,但当app运行在一些屏幕比较宽的手机上时,会出现图片宽高比不对情况,因为宽屏的手机横向的像素密度比较大,为此在网上找到一个解决方案是,定义一个可以根据图片本身宽高比来设置控件宽高的布局。实现如下

首先声明两个属性,一个是picRatio表示图片的宽高比,一个是relative表示要根据宽度按比例确定高度,还是根据高度按比例确定宽度

<resources>

    <declare-styleable name="RatioLayout">
        <attr name="picRatio" format="float" />
        <attr name="relative">
            <enum name="width" value="0" />
            <enum name="height" value="1" />
        </attr>
    </declare-styleable>

</resources>


下面是具体的代码实现
public class RatioLayout extends FrameLayout {
	private float				mPicRatio		= 0f;				// 图片的宽高比 2.43
	public static final int	RELATIVE_WIDTH	= 0;				// 控件宽度固定,已知图片的宽高比,求控件的高度
	public static final int	RELATIVE_HEIGHT	= 1;				// 控件高度固定,已知图片的宽高比,求控件的宽度
	private int					mRelative		= RELATIVE_WIDTH;

	public void setPicRatio(float picRatio) {
		mPicRatio = picRatio;
	}

	public void setRelative(int relative) {
		mRelative = relative;
	}

	public RatioLayout(Context context) {
		this(context, null);
	}

	public RatioLayout(Context context, AttributeSet attrs) {
		super(context, attrs);

		TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioLayout);

		mPicRatio = typedArray.getFloat(R.styleable.RatioLayout_picRatio, 0);

		mRelative = typedArray.getInt(R.styleable.RatioLayout_relative, RELATIVE_WIDTH);

		typedArray.recycle();
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		// 获取控件宽度模式,若控件宽度固定,已知图片的宽高比,求控件的高度
		int parentWidthMode = MeasureSpec.getMode(widthMeasureSpec);

		// 获取控件高度模式,若控件高度固定,已知图片的宽高比,求控件的宽度
		int parentHeightMode = MeasureSpec.getMode(heightMeasureSpec);

		if (parentWidthMode == MeasureSpec.EXACTLY && mPicRatio != 0 && mRelative == RELATIVE_WIDTH) {// 控件宽度固定,已知图片的宽高比,求控件的高度
			// 得到父容器的宽度
			int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
			// 得到孩子的宽度
			int childWidth = parentWidth - getPaddingLeft() - getPaddingRight();
			// 控件的宽度/控件的高度 = mPicRatio;

			// 计算孩子的高度
			int childHeight = (int) (childWidth / mPicRatio + .5f);

			// 计算父容器的高度
			int parentHeight = childHeight + getPaddingBottom() + getPaddingTop();

			// 主动测绘孩子.固定孩子的大小
			int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
			int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
			measureChildren(childWidthMeasureSpec, childHeightMeasureSpec);

			// 设置自己的测试结果
			setMeasuredDimension(parentWidth, parentHeight);

		} else if (parentHeightMode == MeasureSpec.EXACTLY && mPicRatio != 0 && mRelative == RELATIVE_HEIGHT) {
			// 控件高度固定,已知图片的宽高比,求控件的宽度
			// 得到父亲的高度
			int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

			// 得到孩子的高度
			int childHeight = parentHeight - getPaddingBottom() - getPaddingTop();

			// 控件的宽度/控件的高度 = mPicRatio;
			// 计算控件宽度
			int childWidth = (int) (childHeight * mPicRatio + .5f);

			// 得到父亲的宽度
			int parentWidth = childWidth + getPaddingRight() + getPaddingLeft();

			// 主动测绘孩子.固定孩子的大小
			int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
			int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
			measureChildren(childWidthMeasureSpec, childHeightMeasureSpec);

			// 设置自己的测试结果
			setMeasuredDimension(parentWidth, parentHeight);

		} else {
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		}

	}
}
这个布局的使用跟FrameLayout差不多,只要嵌入一个显示图片(只放一个)的ImageView并设置宽高比,它就会按图片比例进行显示了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值