美文网首页自定义控件
按比例缩放的Layout

按比例缩放的Layout

作者: 霄待雨夜 | 来源:发表于2017-03-15 13:58 被阅读0次

Android官方貌似没有按照比例计算自己大小的View,有个按照父控件计算自己大小的百分比View。而往往我们用到自身需要比例的时候还是比较多的,比如显示一张特定照片,宽度match_parent,高度是多少呢,交给ImageView自己测量,要么有白边,要么被部分切割。

其实计算View比例很简单,在View的生命周期中用来计算View大小的的方法是onMeasure,它有两个int参数widthMeasureSpec和heightMeasureSpec,每个分别表示长的大小和模式、宽的大小和模式。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

通过MeasureSpec.getModeMeasureSpec.getSize获取模式和值。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec(heightSize, heightMode));
    }

Mode分为MeasureSpec.EXACTLYMeasureSpec.AT_MOSTMeasureSpec.UNSPECIFIED三种,具体意思请百度。我们在布局中如果需要用比例必定长宽有一个是固定值(某dp或者match_parent),所以可以通过上面三种Mode中的MeasureSpec.EXACTLYMeasureSpec.AT_MOST来判别哪一边是固定值。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode != MeasureSpec.UNSPECIFIED) {
            //  宽是固定的
            heightSize = (int) (widthSize / widthScale * heightScale);
            heightMode = MeasureSpec.EXACTLY;
        } else if (heightMode != MeasureSpec.UNSPECIFIED) {
            //  高是固定的
            widthSize = (int) (heightSize / heightScale * widthScale);
            widthMode = MeasureSpec.EXACTLY;
        }
        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec(heightSize, heightMode));
    }

但是在Android Studio中预览并不是成比例的,真机正常,可能由于我不是很了解MeasureSpec.UNSPECIFIED,或者是AS预览的bug。然后我换了另一种方式,通过LayoutParams是否不是WRAP_CONTENT来判断是不是固定。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int widthParam  = getLayoutParams().width;
        int heightParam = getLayoutParams().height;

        if (widthScale > 0 && heightScale > 0) {
            if (widthParam != ViewGroup.LayoutParams.WRAP_CONTENT) {
                heightSize = (int) (widthSize / widthScale * heightScale);
                heightMode = MeasureSpec.EXACTLY;
            } else if (heightParam != ViewGroup.LayoutParams.WRAP_CONTENT) {
                widthSize = (int) (heightSize / heightScale * widthScale);
                widthMode = MeasureSpec.EXACTLY;
            }
        }
        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSize, widthMode), MeasureSpec.makeMeasureSpec(heightSize, heightMode));
    }

这样预览也正常了。

所以最终在布局中引用

<cn.xuzhijun.proportional.ProportionalFrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#123456"
        app:scaleHeight="9"
        app:scaleWidth="16">

        <!--You View-->

</cn.xuzhijun.proportional.ProportionalFrameLayout>

而且高度和宽度只要有一边是固定值或者match_parent就可以了。
很简单。

有需要的可以直接引用。

compile 'cn.xuzhijun:xproportional-layout:1.0.0'

相关文章

网友评论

    本文标题:按比例缩放的Layout

    本文链接:https://www.haomeiwen.com/subject/wbflnttx.html