使用FrameLayout来适配ImageViw按比例展示

一、布局文件:

<com.hsc.googleplay.ui.view.RatioLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:ratio="2.43">
    <ImageView
        android:id="@+id/iv_pic"
        android:src="@drawable/subject_default"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</com.hsc.googleplay.ui.view.RatioLayout>

再创建attrs.xml文件:

<resources>

    <declare-styleable name="RatioLayout">
        <attr name="ratio" format="float"/>
    </declare-styleable>
    
</resources>

/**
 * 自定义控件,按比例来决定布局高度 做了让View支持wrap_content与padding
 * Created by 15827 on 2017/5/22.
 */

public class RatioLayout extends FrameLayout {

    private float mRatio;

    public RatioLayout(Context context) {
        super(context);
    }

    public RatioLayout( Context context,  AttributeSet attrs) {
        super(context, attrs);
        //获取属性值
        //当自定义属性时,系统会自动生成属性相关id,此id通过R.styleable来引用
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioLayout);

        // id = 属性名_具体属性字段名称
        //系统自动生成RatioLayout_ratio,根据两个name        mRatio = typedArray.getFloat(R.styleable.RatioLayout_ratio, -1);//宽高比例值
        typedArray.recycle();//回收,提高具体性能
        //LogUtils.i("ratio=" + mRatio); //布局中的app:ratio=“2.43” 来自这里 也可以利用图片的真实宽高
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 1 获取宽度
        // 2 根据宽度和比例ratio,计算控件的高度
        // 3 重新测量控件
        LogUtils.d("widthMeasureSpec: "+widthMeasureSpec);

        // MeasureSpec.AT_MOST; 至多模式, 控件有多大显示多大, wrap_content
        // MeasureSpec.EXACTLY; 确定模式, 类似宽高写死成dip, match_parent
        // MeasureSpec.UNSPECIFIED; 未指定模式.
        
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);//获取宽度模式
        int width = MeasureSpec.getSize(widthMeasureSpec); // 获取宽度值

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);//获取高度模式
        int height = MeasureSpec.getSize(heightMeasureSpec); // 获取高度值

        //宽度确定,高度不确定,mRatio合法,才计算高度值
        if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY && mRatio > 0) {
            //图片宽度 = 控件宽度 - 左侧内边距 - 右侧内边距
            int imageWidth = width - getPaddingLeft() - getPaddingRight();

            //图片高度 = 图片宽度 / 宽高比例
            int imageHeight = (int) (imageWidth / mRatio + 0.5f);

            // 控件高度 = 图片高度 + 上侧内边距 + 下侧内边距
            height = imageHeight + getPaddingTop() + getPaddingBottom();

            //根据最新的高度重新生成 heightMeasureSpec (高度模式是确定模式)
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }
        //按照最新的高度测量控件
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FrameLayout 是 Android 中的一个布局容器,它可以用来放置一个或多个子 View,子 View 会按照添加的顺序依次叠放在 FrameLayout 中,并且默认情况下每个子 View 的大小都是填满整个 FrameLayoutFrameLayout 最常见的用法是用来放置一个单独的 View,例如一个 ImageView,通常还会设置 ImageView 的 scaleType 属性来控制图片的显示方式。另外,FrameLayout 也可以用来实现一些特殊的布局效果,例如重叠的 View 或者前景和背景的切换等。 下面是一个简单的 FrameLayout 的示例代码: ```xml <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/image" android:scaleType="centerCrop"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:textSize="24sp" android:textColor="#FFFFFF"/> </FrameLayout> ``` 在这个示例中,FrameLayout 包含了一个 ImageView 和一个 TextView,ImageView 用来显示一张图片,TextView 用来显示一段文本。由于 ImageView 和 TextView 都没有设置位置和大小,所以它们默认会叠放在一起,并且都填满整个 FrameLayout。 需要注意的是,由于 FrameLayout 中的子 View 是按照添加的顺序依次叠放的,所以后添加的子 View 会覆盖前面添加的子 View。如果需要调整子 View 的叠放顺序,可以使用 View 的 bringToFront() 方法或者 setZ() 方法来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值