去掉一个view的background并没有还原成设置之前的情况,setBackgroundResource(0),谷歌给我们挖的坑

来源:互联网 发布:淘宝 一键转让 编辑:程序博客网 时间:2024/05/20 09:45

今天发现了一个比较坑爹的bug,得出的结论如下,不要轻易相信android的api。

当你调用setBackgroundResource(id)的时候实际上是调用的setBackgroundDrawable(d)

源码如下:

    /**     * Set the background to a given resource. The resource should refer to     * a Drawable object or 0 to remove the background.     * @param resid The identifier of the resource.     * @attr ref android.R.styleable#View_background     */    @RemotableViewMethod    public void setBackgroundResource(int resid) {        if (resid != 0 && resid == mBackgroundResource) {            return;        }        Drawable d= null;        if (resid != 0) {            d = mResources.getDrawable(resid);        }        setBackgroundDrawable(d);        mBackgroundResource = resid;    }

然后在setBackgroundDrawable(d)的时候,实际上它是将backgroundDrawable的padding设置成了这个view的padding的。

源码如下:

/**     * Set the background to a given Drawable, or remove the background. If the     * background has padding, this View's padding is set to the background's     * padding. However, when a background is removed, this View's padding isn't     * touched. If setting the padding is desired, please use     * {@link #setPadding(int, int, int, int)}.     *     * @param d The Drawable to use as the background, or null to remove the     *        background     */    public void setBackgroundDrawable(Drawable d) {        if (d == mBGDrawable) {            return;        }        boolean requestLayout = false;        mBackgroundResource = 0;        /*         * Regardless of whether we're setting a new background or not, we want         * to clear the previous drawable.         */        if (mBGDrawable != null) {            mBGDrawable.setCallback(null);            unscheduleDrawable(mBGDrawable);        }        if (d != null) {            Rect padding = sThreadLocal.get();            if (padding == null) {                padding = new Rect();                sThreadLocal.set(padding);            }            if (d.getPadding(padding)) {                switch (d.getResolvedLayoutDirectionSelf()) {                    case LAYOUT_DIRECTION_RTL:                        setPadding(padding.right, padding.top, padding.left, padding.bottom);                        break;                    case LAYOUT_DIRECTION_LTR:                    default:                        setPadding(padding.left, padding.top, padding.right, padding.bottom);                }            }            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or            // if it has a different minimum size, we should layout again            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {                requestLayout = true;            }            d.setCallback(this);            if (d.isStateful()) {                d.setState(getDrawableState());            }            d.setVisible(getVisibility() == VISIBLE, false);            mBGDrawable = d;            if ((mPrivateFlags & SKIP_DRAW) != 0) {                mPrivateFlags &= ~SKIP_DRAW;                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;                requestLayout = true;            }        } else {            /* Remove the background */            mBGDrawable = null;            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {                /*                 * This view ONLY drew the background before and we're removing                 * the background, so now it won't draw anything                 * (hence we SKIP_DRAW)                 */                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;                mPrivateFlags |= SKIP_DRAW;            }            /*             * When the background is set, we try to apply its padding to this             * View. When the background is removed, we don't touch this View's             * padding. This is noted in the Javadocs. Hence, we don't need to             * requestLayout(), the invalidate() below is sufficient.             */            // The old background's minimum size could have affected this            // View's layout, so let's requestLayout            requestLayout = true;        }        computeOpaqueFlags();        if (requestLayout) {            requestLayout();        }        mBackgroundSizeChanged = true;        invalidate(true);    }

再回去看第一段源码的红色那行,你还标注了让人传个参数0就是去掉背景,TM的你就将mBackgroundResource设置成0就拍拍屁股走人了,之前你做过的操作你干嘛不还原呢?你默默地把padding改了,但是你不敢默默地把padding改回去,你偷懒写代码,连函数说明都懒得注明这情况


在此使劲拍你一砖


原创粉丝点击