android pading的四个值,为负值时,什么情况下,有效啊

亲测,设置四个pading值,为负值,测试各种情况,不是所有情况有效?其原理不明白,望高手解答,谢啦

阅读 9.7k
3 个回答

在我的理解中, 设置 padding 为负值和设置为0在显示上不会有什么区别, 所以, 你想要的效果是什么?

OK, 之前没有自习考虑这个问题, 现在帮你分析一下.

首先, 从 xml 中解析 padding 值是在父类 View 中进行的, 在 View 的 构造方法中可以看到下面的代码:

    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {

    ....
            int attr = a.getIndex(i);
            switch (attr) {
                case com.android.internal.R.styleable.View_background:
                    background = a.getDrawable(attr);
                    break;
                case com.android.internal.R.styleable.View_padding:
                    padding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftInitial = padding;
                    mUserPaddingRightInitial = padding;
                    leftPaddingDefined = true;
                    rightPaddingDefined = true;
                    break;
                 case com.android.internal.R.styleable.View_paddingLeft:
                    leftPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingLeftInitial = leftPadding;
                    leftPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingTop:
                    topPadding = a.getDimensionPixelSize(attr, -1);
                    break;
                case com.android.internal.R.styleable.View_paddingRight:
                    rightPadding = a.getDimensionPixelSize(attr, -1);
                    mUserPaddingRightInitial = rightPadding;
                    rightPaddingDefined = true;
                    break;
                case com.android.internal.R.styleable.View_paddingBottom:
                    bottomPadding = a.getDimensionPixelSize(attr, -1);
                    break;
                // ...
            }

        ....
        // setBackground above will record that padding is currently provided by the background.
        // If we have padding specified via xml, record that here instead and use it.
        mLeftPaddingDefined = leftPaddingDefined;
        mRightPaddingDefined = rightPaddingDefined;

        if (padding >= 0) {
            leftPadding = padding;
            topPadding = padding;
            rightPadding = padding;
            bottomPadding = padding;
            mUserPaddingLeftInitial = padding;
            mUserPaddingRightInitial = padding;
        }

        ....
        internalSetPadding(
                mUserPaddingLeftInitial,
                topPadding >= 0 ? topPadding : mPaddingTop,
                mUserPaddingRightInitial,
                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
        ....
    }

从上面的代码可以看到, 如果通过设置 android:padding 的方式, 那么只有当 padding 值大于等于0才会被赋值给上下左右的 padding. 这就解释了为什么我的实验中 padding 为负值并不会有影响. 同时在调用 internalSetPadding() 方法时, 上下 padding 值都对是否为负值做了判断, 以保证其为正值, 所以我使用你的代码中的参数, 但是将 android:paddingTop 设为负值也没有出现文字不可见的情况.

接下来, View 在自己的区域中如何进行绘制是由每一个 View 的子类自己实现的, 并不是所有的 View 子类都会有设置 paddingLeft 会使内容截断甚至隐藏的情况, 至少目前我试了以后发现只有 TextView 及其子类会. OK, 那看一下 TextView 是怎么绘制文字的:

    @Override
    protected void onDraw(Canvas canvas) {
        ....
        final int compoundPaddingLeft = getCompoundPaddingLeft();
        final int compoundPaddingTop = getCompoundPaddingTop();
        final int compoundPaddingRight = getCompoundPaddingRight();
        final int compoundPaddingBottom = getCompoundPaddingBottom();

        ....

        canvas.save();

        int extendedPaddingTop = getExtendedPaddingTop();
        int extendedPaddingBottom = getExtendedPaddingBottom();

        final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
        final int maxScrollY = mLayout.getHeight() - vspace;

        float clipLeft = compoundPaddingLeft + scrollX;
        ....

        if (mShadowRadius != 0) {
            clipLeft += Math.min(0, mShadowDx - mShadowRadius);
            ....
        }

        canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
        ....

        canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);

        ....
        mEditor.onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);

        ....
        canvas.restore();
    }

    ....

    public int getCompoundPaddingLeft() {
        final Drawables dr = mDrawables;
        if (dr == null || dr.mShowing[Drawables.LEFT] == null) {
            return mPaddingLeft;
        } else {
            return mPaddingLeft + dr.mDrawablePadding + dr.mDrawableSizeLeft;
        }
    }

    public int getExtendedPaddingTop() {
        if (mMaxMode != LINES) {
            return getCompoundPaddingTop();
        }
        ....
    }

从上面 TextView 类的 onDraw 方法中可以看到, 在

canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);

这一句中, 画布 canvas 对象进行了平移, 而在这之前并没有对 compoundPaddingLeft 进行负值判定, 因此, 对 TextView 设置 android:paddingLeft 是会使内容文字被截掉的.

所以, 题主想要的"原理"其实很简单, 那就是每一个 View 子类里面的内容怎么绘制是由它的 onDraw() 方法确定的. (当然还有 draw(), dispatchDraw() 这些, 不细说.)

首先声明 这个我还没有亲测 但我猜测你这个 paddingleft 与paddingtop 应该有效 你想隐藏也要看控件距屏幕的距离 如果直接设置padding 就会发生冲突 因为不知道到底要不要隐藏
你可以自己再去测试下我这种猜测

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题