在开发中我们一般会把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);
}
}
- 使用控件
<?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>