adjustViewBounds说明

说明一下环境
就是要设置一个imageview 的src属性,这个图片要保证不能被拉伸,同时还要适配不同屏幕,所以我们一一般的做法就是设置imageview的lw,是match_parent,lh是wrap_content

这个时候 就出现了如图的效果


Snip20170721_1.png

图片是保持了包裹图片原有的大小,但是imageview为什么还多出来了上下两个部分?
这时候 聪明的大佬肯定就会说 sb,设置scaleType啊!
好的 大佬,我设置给你看(首先要知道,imageview默认的scaleType是fitcenter,),那么这种情况, 我愚钝只能设置成fitxy吧,如图

Snip20170721_2.png

好的 被拉伸了。
这个时候 我就像大佬那样,设置完 也不管拉伸与否,就提交上去了,后来我的老大jack就看出来了,给我指导一番,说出了imageview的神属性,adjustViewBounds 卧槽,真的一设置,就成了,而且 还不用设置了scaleType,真屌。

然后我就去谷歌这个属性,看博客,有人说的是设置了adjustViewBounds,还要必须设置maxWidth,maxHeight这两个属性,但是下面就是官网和源码上的setxxx这个属性的方法,看了注释的意思也很明确就是就是让iamageview符合内部图片的大小,但是网上别的文章就说 设置了adjustViewBounds,还要必须设置maxWidth,maxHeight这两个属性,跟这个不同,还是去看一下源码是怎么做到吧.

android:adjustViewBounds
Set this to true if you want the ImageView to adjust its bounds to preserve the aspect ratio of its drawable.
May be a boolean value, such as "true
" or "false
".

**Related methods:**
[setAdjustViewBounds(boolean)](https://developer.android.com/reference/android/widget/ImageView.html#setAdjustViewBounds(boolean))


/**
     * Set this to true if you want the ImageView to adjust its bounds
     * to preserve the aspect ratio of its drawable.
     *
     * <p><strong>Note:</strong> If the application targets API level 17 or lower,
     * adjustViewBounds will allow the drawable to shrink the view bounds, but not grow
     * to fill available measured space in all cases. This is for compatibility with
     * legacy {@link android.view.View.MeasureSpec MeasureSpec} and
     * {@link android.widget.RelativeLayout RelativeLayout} behavior.</p>
     *
     * @param adjustViewBounds Whether to adjust the bounds of this view
     * to preserve the original aspect ratio of the drawable.
     *
     * @see #getAdjustViewBounds()
     *
     * @attr ref android.R.styleable#ImageView_adjustViewBounds
     */
    @android.view.RemotableViewMethod
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        mAdjustViewBounds = adjustViewBounds;
        if (adjustViewBounds) {
            setScaleType(ScaleType.FIT_CENTER);
        }
    }

有人说会不会是背景颜色原因(并不是,我只是为了突出效果显示,其实你可以试试,把背景去掉)
那就去看看源码吧,理清一下思路
设置了adjustViewBounds那么imageview就会变得很听话,不设置,即使设置了scaleType还是没卵用,那么adjustViewBounds肯定有关键的作用,所以去imageview的源码里看看,
那就全局搜索adjustViewBounds
首先看到的是mAdjustViewBounds默认是false没有开启,
然后是set,get方法
然后是在onMeasure中用到了

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        resolveUri(); // 验证drawable的uri
        int w;
        int h;

        // Desired aspect ratio of the view's contents (not including padding)
        float desiredAspect = 0.0f;

        // We are allowed to change the view's width
        boolean resizeWidth = false;

        // We are allowed to change the view's height
        boolean resizeHeight = false;
//就正常自定义view那些东西
        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        if (mDrawable == null) {//drawable为空 就都是0了
            // If no drawable, its intrinsic size is 0.
            mDrawableWidth = -1;
            mDrawableHeight = -1;
            w = h = 0;
        } else {
            w = mDrawableWidth;
            h = mDrawableHeight;
            if (w <= 0) w = 1;
            if (h <= 0) h = 1;
//不为空,那么就进行赋值上drawable的大小
            // We are supposed to adjust view bounds to match the aspect
            // ratio of our drawable. See if that is possible.
//设置了adjustViewBounds,就会调整比例,将view的比例设置成
//drawable的比例,所以能够完美展示。同时注意resizeWidth,只有当view当测量模式不是Exactly,就是(match_parent,和精准当XXdp)
            if (mAdjustViewBounds) {
                resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

                desiredAspect = (float) w / (float) h;
            }
        }

        final int pleft = mPaddingLeft;
        final int pright = mPaddingRight;
        final int ptop = mPaddingTop;
        final int pbottom = mPaddingBottom;

        int widthSize;
        int heightSize;
//如果是精准当size,那么就得重新测量了,同时还需要设置adjustViewbounds属性才行,因为只有设置了adjustViewBounds属性了才能对reseiz这两个值进行赋值,别的地方没有赋值
        if (resizeWidth || resizeHeight) {

            /* If we get here, it means we want to resize to match the
                drawables aspect ratio, and we have the freedom to change at
                least one dimension.
            */

            // Get the max possible width given our constraints
            widthSize = resolveAdjustedSize(w + pleft + pright, mMaxWidth, widthMeasureSpec);

            // Get the max possible height given our constraints
            heightSize = resolveAdjustedSize(h + ptop + pbottom, mMaxHeight, heightMeasureSpec);
//如果设置了adjustViewBounds,然后根据比例对需要对宽高进行缩放,是等比例缩放。
            if (desiredAspect != 0.0f) {
                // See what our actual aspect ratio is
                final float actualAspect = (float)(widthSize - pleft - pright) /
                                        (heightSize - ptop - pbottom);

                if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {

                    boolean done = false;

                    // Try adjusting width to be proportional to height
                    if (resizeWidth) {
                        int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
                                pleft + pright;

                        // Allow the width to outgrow its original estimate if height is fixed.
                        if (!resizeHeight && !sCompatAdjustViewBounds) {
                            widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
                        }

                        if (newWidth <= widthSize) {
                            widthSize = newWidth;
                            done = true;
                        }
                    }

                    // Try adjusting height to be proportional to width
                    if (!done && resizeHeight) {
                        int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
                                ptop + pbottom;

                        // Allow the height to outgrow its original estimate if width is fixed.
                        if (!resizeWidth && !sCompatAdjustViewBounds) {
                            heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
                                    heightMeasureSpec);
                        }

                        if (newHeight <= heightSize) {
                            heightSize = newHeight;
                        }
                    }
                }
            }
        } else {
        //如果没有设置,那么久根据imageview的drawable的背景图片的大小作为imageview的最小尺寸
            /* We are either don't want to preserve the drawables aspect ratio,
               or we are not allowed to change view dimensions. Just measure in
               the normal way.
            */
            w += pleft + pright;
            h += ptop + pbottom;

            w = Math.max(w, getSuggestedMinimumWidth());
            h = Math.max(h, getSuggestedMinimumHeight());

            widthSize = resolveSizeAndState(w, widthMeasureSpec, 0);
            heightSize = resolveSizeAndState(h, heightMeasureSpec, 0);
        }

        setMeasuredDimension(widthSize, heightSize);
    }

总结

其实adjutViewBounds 的作用就是当Imageivew的宽或者设置成了At_Most模式后,会让imageview的大小等比缩放变成了drawable的大小.

那么为什么imageview设置成wrap_content,会多出来宽的呢?去看源码知道了,imageview的width,height是mDrawable的width,height,那么这个drawable的赋值是d.getIntrinsicHeight();,和d.getIntrinsicWidth();这个得来的,继续追,发现这个是bitmapdrawable,然后看源码


private void computeBitmapSize() {
        final Bitmap bitmap = mBitmapState.mBitmap;
        if (bitmap != null) {
            mBitmapWidth = bitmap.getScaledWidth(mTargetDensity);
            mBitmapHeight = bitmap.getScaledHeight(mTargetDensity);
        } else {
            mBitmapWidth = mBitmapHeight = -1;
        }
    }

这是赋值,他会根据mTargetDensity(屏幕的比例)这个属性对bitmap的宽高进行缩放,所以导致了上诉情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容