親測(cè),設(shè)置四個(gè)pading值,為負(fù)值,測(cè)試各種情況,不是所有情況有效?其原理不明白,望高手解答,謝啦
光陰似箭催人老,日月如移越少年。
In my understanding, setting padding to a negative value or setting it to 0 will not make any difference in display, so, what is the effect you want?
OK, I haven’t considered this issue during self-study before, now I’ll help you analyze it.
First of all, parsing the padding value from xml is done in the parent class View. You can see the following code in the constructor of 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);
....
}
As you can see from the above code, if you set android:padding
, then only when the padding value is greater than or equal to 0, it will be assigned to the upper, lower, left and right padding. This explains why the padding is negative in my experiment The value will not have any effect. At the same time, when calling the internalSetPadding()
method, the upper and lower padding values ??are judged whether it is a negative value to ensure that it is a positive value, so I use the parameters in your code, but change android:paddingTop
Even if it is set to a negative value, the text will not be invisible.
Next, how View draws in its own area is implemented by each View subclass. Not all View subclasses will have settings paddingLeft
that will truncate or even hide the content, at least After trying it now, I found that only TextView and its subclasses can do it. OK, let’s take a look at how TextView draws text:
@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();
}
....
}
As you can see from the onDraw method of the TextView class above, in
canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
In this sentence, the canvas object has been translated, but before this, compoundPaddingLeft
has not been judged as a negative value. Therefore, setting android:paddingLeft
to TextView will cause the content text to be cut off.
So, the "principle" the questioner wants is actually very simple, that is, how the content in each View subclass is drawn is determined by its onDraw()
method. (Of course there are also draw()
, dispatchDraw()
I won’t go into details about these.)
First of all, I have not tested this myself, but I guess your paddingleft and paddingtop should be effective. If you want to hide it, it depends on the distance between the control and the screen. If you set padding directly, there will be a conflict because I don’t know whether to hide it or not
You can test my guess yourself