按比例自适应手机尺寸listview的item项控件

针对不同屏幕宽度可能导致图片拉伸变形的问题,本文介绍了如何设计一个RatioLayout,该控件能根据屏幕宽度自适应地调整高宽比,避免图片变形,保持美观。通过在attrs.xml中定义ratio属性,并重写测量视图的宽高来实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开发中我们一般会把listview的item高度写死,而宽度匹配屏幕宽度,那么问题来了?
有的屏幕宽有的屏幕窄,图片的宽度就会有被拉伸的可能高宽比会发生变化,拉伸图片就会变形影响美观,下面我们就定义一个随宽度变化高成比例缩放的控件RatioLayout 。

自定义属性有3部曲:
1.在attrs.xml中自定义属性:ratio 宽高比

<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!-- 可以获取在xml中定义的ratio的float类型的值 -->
<declare-styleable name="RatioLayout">
<attr name="ratio" format="float"/>
</declare-styleable>
</resources>

2.重新测量view的宽高

public class RatioLayout extends FrameLayout {

    private float ratio;

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

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

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

    private void initRatio(AttributeSet attrs,Context context) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioLayout);
        ratio = typedArray.getFloat(R.styleable.RatioLayout_ratio, 0.0f);
    }

    //测量控件的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //widthMeasureSpec分为两部分组成:模式,大小
        //32 0,1  前两位为模式   30 大小的值
//      MeasureSpec.getMode(measureSpec);
//      MeasureSpec.getSize(measureSpec);

//      MeasureSpec.AT_MOST     至多的模式     200
//      MeasureSpec.EXACTLY     确切模式         50
//      MeasureSpec.UNSPECIFIED 未定义          

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);


        //如果高度为确切模式的话
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        int imageHeight = height-getPaddingBottom()-getPaddingTop();

        int imageWidth = width-getPaddingLeft()-getPaddingRight();

        if(widthMode == MeasureSpec.EXACTLY && heightMode!=MeasureSpec.EXACTLY && ratio!=0.0f){
            heightMeasureSpec = (int) (imageWidth/ratio+getPaddingTop()+getPaddingBottom());
            //告知当前控件绘画高度的模式和大小值
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeasureSpec, MeasureSpec.EXACTLY);
        }else 

        //如果为高度确定计算宽度的时候,才有以下代码
        if(widthMode != MeasureSpec.EXACTLY && heightMode==MeasureSpec.EXACTLY && ratio!=0.0f){
            widthMeasureSpec = (int) (imageHeight*ratio+getPaddingLeft()+getPaddingRight());
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY);
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
  1. 使用控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    android:padding="5dp">
    <LinearLayout 
        android:background="@drawable/list_item_bg"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <包名.RatioLayout
         xmlns:app="http://schemas.android.com/apk/res/包名"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            app:ratio="2.43">
            <ImageView 
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </包名.RatioLayout>
        <TextView 
            android:id="@+id/tv"
            android:text="哈哈哈哈哈哈啊哈"
            android:singleLine="true"
            android:ellipsize="end"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值