Nitro's

Feb 3, 2015 - Comments - tech dev

Android View背景与Shape

某个view需要有点击、焦点、选中的背景反馈是一般使用selector设置各个状态时的背景色。每一个item设置纯色一般比较少见,比较多的是使用bitmap或者shape,如果是bitmap很好理解,状态变化时直接切换渲染的图片就OK,但比较好的方式是用shape自定义图形。 这样做有两点好处,第一能够减小APK包的大小,现在的App很多已经是20+M,对用户的更新造成诸多不便,所以保持App大小很重要,其次能够避免图片平铺拉伸的处理,虽然.9图片从一定程度上保证了屏幕尺寸的兼容。

Shape使用时要注意Padding标签。

在Shape XML中定义了Padding并且此Shape作为某个View的Background时,View就不需要再设置android:padding,因为两者会产生冲突。 源代码分析可见冲突点:

View.java
setBackgroundDrawable()主要读取Drawable的Padding来设置当前View的Padding
------
     if (background != null) {
            Rect padding = sThreadLocal.get();
            if (padding == null) {
                padding = new Rect();
                sThreadLocal.set(padding);
            }
            resetResolvedDrawables();
            background.setLayoutDirection(getLayoutDirection());
            if (background.getPadding(padding)) {   // 读取背景图的Padding
                resetResolvedPadding();             // 重置当前View的Padding
                switch (background.getLayoutDirection()) {
                    case LAYOUT_DIRECTION_RTL:
                        mUserPaddingLeftInitial = padding.right;  //重置View初始化Padding
                        mUserPaddingRightInitial = padding.left;
                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);                         //写入View Padding值
                        break;
                    case LAYOUT_DIRECTION_LTR:
                    default:
                        mUserPaddingLeftInitial = padding.left;
                        mUserPaddingRightInitial = padding.right;
                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                }
                mLeftPaddingDefined = false;    //将原有Padding置为false
                mRightPaddingDefined = false;
            }




View.java
---------- 
   public void setPadding(int left, int top, int right, int bottom) {//直接设置View的Padding
        resetResolvedPadding();        //重置View的Padding

        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;

        mUserPaddingLeftInitial = left;
        mUserPaddingRightInitial = right;

        mLeftPaddingDefined = true;
        mRightPaddingDefined = true;     //将Padding数据置为true

        internalSetPadding(left, top, right, bottom); //写入Padding值
    }

通过setBackground() 和setPadding()这两个方法的分析可以看到,Padding最终生效的值,取决于两个方法的调用顺序,按照View读取XML的顺序是先读取背景再读取Padding,与XML中标签的先后顺序无关,但如果在Java代码中就取决于两个方法的调用顺序了。

一里路一本书 微信扫码直接跳转前台实现

comments powered by Disqus