看源码理解几种设置View背景的区别

QuibblerQuibbler 2019-12-24 约 9 分钟 2591 次阅读

看源码理解几种设置View背景的区别

在写代码的时候给一个布局View设置背景,一开始使用的是setsetBackgroundResource()由于某种原因没有效果,换成setBackground()就可以了。很好奇,这其中的原理,虽然这些都是用来给View设置背景的,最大的不同无外乎参数不同:

  • setBackground(Drawable background):其参数为一个Drawable对象,目的是设置view的背景图片,Drawable对象可以这样获取getResources().getDrawable(R.drawable.xx),还可以是Context.getResource().getColor(R.color.white)

  • setBackgroundColor(int color):其参数为一个颜色值,其目的是设置一个view的背景颜色

  • setBackgroundDrawable(Drawable background):和SetBackground有异曲同工之妙,都是通过传入一个Drawable对象设置view控件的背景图片

  • setBackgroundResource(int resid):它也是设置一个view的背景图片,只不过传入的是一个drawable的id值或者color颜色值

先来看第一个setBackground(Drawable background)的源码,内部调用setBackgroundDrawable(Drawable background)方法

/**
     * 将背景设置为给定的Drawable,或删除背景。 如果
     * 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 background The Drawable to use as the background, or null to remove the
     *        background
     */
    public void setBackground(Drawable background) {
        //noinspection deprecation
        setBackgroundDrawable(background);
    }

再看setBackgroundDrawable(Drawable background)的内部实现,很复杂,这里没有全部列出来。虽然已经被标记为deprecated,不建议当做API直接调用,猜测可能Google想把这个API最终hide或者private作为内部实现方法,因为其它几个设置背景的最终都是通过这个来实现的:

/**
     * @deprecated use {@link #setBackground(Drawable)} instead
     */
    @Deprecated
    public void setBackgroundDrawable(Drawable background) {
        computeOpaqueFlags();
        if (background == mBackground) {
            return;
        }
        ... ...
    }

设置视图的背景色 方法setBackgroundColor(@ColorInt int color)也会调用到setBackground->setBackgroundDrawable

/**
     * 设置此视图的背景色。
     * @param color the color of the background
     */
    @RemotableViewMethod
    public void setBackgroundColor(@ColorInt int color) {
        if (mBackground instanceof ColorDrawable) {
            ((ColorDrawable) mBackground.mutate()).setColor(color);
            computeOpaqueFlags();
            mBackgroundResource = 0;
        } else {
            setBackground(new ColorDrawable(color));
        }
    }

setBackgroundResource(@DrawableRes int resid)是设置view的背景图片,内部实现也是通过调用链:setBackground->setBackgroundDrawable来实现的。不过需要注意的是如果设置的资源和上次一样就不会重新设置而是直接返回,除了再次设置的resid和上一次设置的不一样才会通过资源id获取到Drawable对象再调用setBackground进行设置。【这就不难解释之前为什么用setBackgroundResource方法不管用,因为两次设置了同样的资源ID】

/**
     * 将背景设置为给定的资源。 资源应引用Drawable对象或0以删除背景。
     * @param resid The identifier of the resource.
     *
     * @attr ref android.R.styleable#View_background
     */
    @RemotableViewMethod
    public void setBackgroundResource(@DrawableRes int resid) {
        if (resid != 0 && resid == mBackgroundResource) {
            return;
        }
        Drawable d = null;
        if (resid != 0) {
            d = mContext.getDrawable(resid);
        }
        setBackground(d);
        mBackgroundResource = resid;
    }

参考博客:

        《setBackground(),setBackgroundResource(),setBackgroundColor(),setBackgroundDrawable()的区别和用法》

        《setBackgroundDrawable跟setBackgroundResource的区别》

        《setBackgroundDrawable跟setBackgroundResource的区别》

相关推荐