android 自定义属性,分享一个自适应容器,多用于显示图片,保证图片不变形

本文介绍了在Android开发中如何创建一个自适应容器,特别适用于展示图片且保持图片比例不变形。通过自定义属性,可以方便地复用代码,提高开发效率。

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

自适应容器需要用到自定义属性,先简单了解自定义属性

TextView View Button 都有一些属性,例如 android:layout_width,这些都是系统定义的属性,可以直接用,当然这些属性在有些时候不能满足我们的需求,最常见的是在自定义控件的时候,网上的开源框架很多都有自定义控件,使用到自定义属性,这些自定义属性可以改变控件的样式等,方便使用者修改,
先看下系统的定义的属性,这些属性都是在别人的博客看到的
<declare-styleable name="View">
    <attr name="id" format="reference" />
    <attr name="background" format="reference|color" />
    <attr name="padding" format="dimension" />
     ...
    <attr name="focusable" format="boolean" />
     ...
</declare-styleable>

<declare-styleable name="TextView">
    <attr name="text" format="string" localization="suggested" />
    <attr name="hint" format="string" />
    <attr name="textColor" />
    <attr name="textColorHighlight" />
    <attr name="textColorHint" />
     ...
</declare-styleable>

<declare-styleable name="ViewGroup_Layout">
    <attr name="layout_width" format="dimension">
        <enum name="fill_parent" value="-1" />
        <enum name="match_parent" value="-1" />
        <enum name="wrap_content" value="-2" />
    </attr>
    <attr name="layout_height" format="dimension">
        <enum name="fill_parent" value="-1" />
        <enum name="match_parent" value="-1" />
        <enum name="wrap_content" value="-2" />
    </attr>
</declare-styleable>

<declare-styleable name="LinearLayout_Layout">
    <attr name="layout_width" />
    <attr name="layout_height" />
    <attr name="layout_weight" format="float" />
    <attr name="layout_gravity" />
</declare-styleable>

<declare-styleable name="RelativeLayout_Layout">
    <attr name="layout_centerInParent" format="boolean" />
    <attr name="layout_centerHorizontal" format="boolean" />
    <attr name="layout_centerVertical" format="boolean" />
     ...
</declare-styleable>
可以看到一些控件都有自己的属性,TextView是继承自view同时也有View的属性,name是属性的名字,format表示该属性能接受到值的类型
类型有很多种就不说了,在写自定属性的时候自动会提示的
接下来开始写自定义属性了
首先在res->values创建一个存放自定义属性的xml(attrs.xml),下面是要用到的属性
<resources>
    <declare-styleable name="self_adaption">
        <attr name="proportion" format="float"/>
    </declare-styleable>
</resources>
自定义控件
**
 * 自适应的容器
 */

public class HomeAdvertThreeImage extends FrameLayout {
    //宽高比例
    private float mPicRatio;// = 2.02f;

    public HomeAdvertThreeImage(Context context, AttributeSet attrs) {
        super(context, attrs);
        //读取自定义的属性
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.self_adaption);
        mPicRatio = array.getFloat(R.styleable.self_adaption_proportion, 0.0f);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //得到模式,根据宽度动态计算高度
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        //得到模式,根据高度动态计算宽度
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (widthMode == MeasureSpec.EXACTLY) {
            //得到自身的宽度
            int selfWidth = MeasureSpec.getSize(widthMeasureSpec);
            //根据比例值获取高度
            int selfHeight = (int) (selfWidth / mPicRatio + .5f);
            //保存测量结果
            setMeasuredDimension(selfWidth, selfHeight);

            //孩子的宽和高
            int childWidth = selfWidth - getPaddingLeft() - getPaddingRight();
            int childHeight = selfHeight - getPaddingBottom() - getPaddingTop();
            //孩子确切的宽和高
            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
            int childHeightMeauseSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
            //测量孩子
            measureChildren(childWidthMeasureSpec, childHeightMeauseSpec);

        } else if (heightMode == MeasureSpec.EXACTLY){
            //得到自身的高度
            int selfHeight = MeasureSpec.getSize(heightMeasureSpec);
            //根据比例值获取高度
            int selfWidth = (int) (selfHeight / mPicRatio + .5f);
            //保存测量结果
            setMeasuredDimension(selfWidth, selfHeight);

            //孩子的宽和高
            int childWidth = selfWidth - getPaddingLeft() - getPaddingRight();
            int childHeight = selfHeight - getPaddingBottom() - getPaddingTop();
            //孩子确切的宽和高
            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
            int childHeightMeauseSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
            //测量孩子
            measureChildren(childWidthMeasureSpec, childHeightMeauseSpec);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

使用自定义控件
<com.cad.view.HomeAdvertThreeImage
    app:proportion="2.02"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <android.support.v4.view.ViewPager
        android:id="@id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:layout_gravity="bottom"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        android:orientation="horizontal">
    </LinearLayout>
</com.cad.view.HomeAdvertThreeImage>
其中app:proprotion="2.02"就是上面定义的属性,接受的值是float类型

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.self_adaption);
mPicRatio = array.getFloat(R.styleable.self_adaption_proportion, 0.0f);
这两行代码就是读取到xml中使用的自定义属性的值,然后赋值给宽高比例,这样这个最重要的比例值就可以在xml定义了,相当于对外暴露了方法可写可不写,不写的话必须要有默认值,这样就完成了自适应容器了(注释全网最清晰),有那里不对的可以回复我,我再修改修改

我自己写的做记录,方便以后用到直接复制就ok了

在来个自定义属性的介绍详细的链接



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值