@@ -2789,6 +2789,20 @@ static class TransformationInfo {
27892789 @ViewDebug.ExportedProperty(category = "padding")
27902790 int mUserPaddingEnd;
27912791
2792+ /**
2793+ * Whether a left padding has been defined during layout inflation.
2794+ *
2795+ * @hide
2796+ */
2797+ boolean mUserPaddingLeftDefined = false;
2798+
2799+ /**
2800+ * Whether a right padding has been defined during layout inflation.
2801+ *
2802+ * @hide
2803+ */
2804+ boolean mUserPaddingRightDefined = false;
2805+
27922806 /**
27932807 * Default undefined padding
27942808 */
@@ -3195,8 +3209,11 @@ public View(Context context, AttributeSet attrs, int defStyle) {
31953209 boolean transformSet = false;
31963210
31973211 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3198-
31993212 int overScrollMode = mOverScrollMode;
3213+ boolean initializeScrollbars = false;
3214+
3215+ final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3216+
32003217 final int N = a.getIndexCount();
32013218 for (int i = 0; i < N; i++) {
32023219 int attr = a.getIndex(i);
@@ -3206,15 +3223,19 @@ public View(Context context, AttributeSet attrs, int defStyle) {
32063223 break;
32073224 case com.android.internal.R.styleable.View_padding:
32083225 padding = a.getDimensionPixelSize(attr, -1);
3226+ mUserPaddingLeftDefined = true;
3227+ mUserPaddingRightDefined = true;
32093228 break;
32103229 case com.android.internal.R.styleable.View_paddingLeft:
32113230 leftPadding = a.getDimensionPixelSize(attr, -1);
3231+ mUserPaddingLeftDefined = true;
32123232 break;
32133233 case com.android.internal.R.styleable.View_paddingTop:
32143234 topPadding = a.getDimensionPixelSize(attr, -1);
32153235 break;
32163236 case com.android.internal.R.styleable.View_paddingRight:
32173237 rightPadding = a.getDimensionPixelSize(attr, -1);
3238+ mUserPaddingRightDefined = true;
32183239 break;
32193240 case com.android.internal.R.styleable.View_paddingBottom:
32203241 bottomPadding = a.getDimensionPixelSize(attr, -1);
@@ -3359,12 +3380,12 @@ public View(Context context, AttributeSet attrs, int defStyle) {
33593380 if (scrollbars != SCROLLBARS_NONE) {
33603381 viewFlagValues |= scrollbars;
33613382 viewFlagMasks |= SCROLLBARS_MASK;
3362- initializeScrollbars(a) ;
3383+ initializeScrollbars = true ;
33633384 }
33643385 break;
33653386 //noinspection deprecation
33663387 case R.styleable.View_fadingEdge:
3367- if (context.getApplicationInfo(). targetSdkVersion >= ICE_CREAM_SANDWICH) {
3388+ if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
33683389 // Ignore the attribute starting with ICS
33693390 break;
33703391 }
@@ -3496,12 +3517,11 @@ public void onClick(View v) {
34963517 }
34973518 }
34983519
3499- a.recycle();
3500-
35013520 setOverScrollMode(overScrollMode);
35023521
3503- // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
3504- // layout direction). Those cached values will be used later during padding resolution.
3522+ // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3523+ // the resolved layout direction). Those cached values will be used later during padding
3524+ // resolution.
35053525 mUserPaddingStart = startPadding;
35063526 mUserPaddingEnd = endPadding;
35073527
@@ -3529,6 +3549,12 @@ public void onClick(View v) {
35293549 setFlags(viewFlagValues, viewFlagMasks);
35303550 }
35313551
3552+ if (initializeScrollbars) {
3553+ initializeScrollbars(a);
3554+ }
3555+
3556+ a.recycle();
3557+
35323558 // Needs to be called after mViewFlags is set
35333559 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
35343560 recomputePadding();
@@ -5533,10 +5559,13 @@ public void setLayoutDirection(int layoutDirection) {
55335559 // Reset the current layout direction and the resolved one
55345560 mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
55355561 resetResolvedLayoutDirection();
5536- // Set the new layout direction (filtered) and ask for a layout pass
5562+ // Reset padding resolution
5563+ mPrivateFlags2 &= ~PADDING_RESOLVED;
5564+ // Set the new layout direction (filtered)
55375565 mPrivateFlags2 |=
55385566 ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
5539- resolvePadding();
5567+ resolveRtlProperties();
5568+ // ... and ask for a layout pass
55405569 requestLayout();
55415570 }
55425571 }
@@ -5552,6 +5581,11 @@ public void setLayoutDirection(int layoutDirection) {
55525581 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
55535582 })
55545583 public int getResolvedLayoutDirection() {
5584+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5585+ if (targetSdkVersion < JELLY_BEAN_MR1) {
5586+ mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
5587+ return LAYOUT_DIRECTION_LTR;
5588+ }
55555589 // The layout direction will be resolved only if needed
55565590 if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
55575591 resolveLayoutDirection();
@@ -9657,12 +9691,22 @@ public void setLayoutParams(ViewGroup.LayoutParams params) {
96579691 throw new NullPointerException("Layout parameters cannot be null");
96589692 }
96599693 mLayoutParams = params;
9694+ resolveLayoutParams();
96609695 if (mParent instanceof ViewGroup) {
96619696 ((ViewGroup) mParent).onSetLayoutParams(this, params);
96629697 }
96639698 requestLayout();
96649699 }
96659700
9701+ /**
9702+ * Resolve the layout parameters depending on the resolved layout direction
9703+ */
9704+ private void resolveLayoutParams() {
9705+ if (mLayoutParams != null) {
9706+ mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
9707+ }
9708+ }
9709+
96669710 /**
96679711 * Set the scrolled position of your view. This will cause a call to
96689712 * {@link #onScrollChanged(int, int, int, int)} and the view will be
@@ -11197,12 +11241,7 @@ protected void onAttachedToWindow() {
1119711241
1119811242 jumpDrawablesToCurrentState();
1119911243
11200- // Order is important here: LayoutDirection MUST be resolved before Padding
11201- // and TextDirection
11202- resolveLayoutDirection();
11203- resolvePadding();
11204- resolveTextDirection();
11205- resolveTextAlignment();
11244+ resolveRtlProperties();
1120611245
1120711246 clearAccessibilityFocus();
1120811247 if (isFocused()) {
@@ -11215,6 +11254,16 @@ protected void onAttachedToWindow() {
1121511254 }
1121611255 }
1121711256
11257+ void resolveRtlProperties() {
11258+ // Order is important here: LayoutDirection MUST be resolved first...
11259+ resolveLayoutDirection();
11260+ // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11261+ resolvePadding();
11262+ resolveLayoutParams();
11263+ resolveTextDirection();
11264+ resolveTextAlignment();
11265+ }
11266+
1121811267 /**
1121911268 * @see #onScreenStateChanged(int)
1122011269 */
@@ -11294,56 +11343,66 @@ public void resolveLayoutDirection() {
1129411343 public void onResolvedLayoutDirectionChanged() {
1129511344 }
1129611345
11346+ /**
11347+ * Return if padding has been resolved
11348+ */
11349+ boolean isPaddingResolved() {
11350+ return (mPrivateFlags2 & PADDING_RESOLVED) != 0;
11351+ }
11352+
1129711353 /**
1129811354 * Resolve padding depending on layout direction.
1129911355 */
1130011356 public void resolvePadding() {
11301- // If the user specified the absolute padding (either with android:padding or
11302- // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
11303- // use the default padding or the padding from the background drawable
11304- // (stored at this point in mPadding*)
11305- int resolvedLayoutDirection = getResolvedLayoutDirection();
11306- switch (resolvedLayoutDirection) {
11307- case LAYOUT_DIRECTION_RTL:
11308- // Start user padding override Right user padding. Otherwise, if Right user
11309- // padding is not defined, use the default Right padding. If Right user padding
11310- // is defined, just use it.
11311- if (mUserPaddingStart != UNDEFINED_PADDING) {
11312- mUserPaddingRight = mUserPaddingStart;
11313- }
11314- if (mUserPaddingRight == UNDEFINED_PADDING) {
11315- mUserPaddingRight = mPaddingRight;
11316- }
11317- if (mUserPaddingEnd != UNDEFINED_PADDING) {
11318- mUserPaddingLeft = mUserPaddingEnd;
11319- }
11320- if (mUserPaddingLeft == UNDEFINED_PADDING) {
11321- mUserPaddingLeft = mPaddingLeft;
11322- }
11323- break;
11324- case LAYOUT_DIRECTION_LTR:
11325- default:
11326- // Start user padding override Left user padding. Otherwise, if Left user
11327- // padding is not defined, use the default left padding. If Left user padding
11328- // is defined, just use it.
11329- if (mUserPaddingStart != UNDEFINED_PADDING) {
11330- mUserPaddingLeft = mUserPaddingStart;
11331- }
11332- if (mUserPaddingLeft == UNDEFINED_PADDING) {
11333- mUserPaddingLeft = mPaddingLeft;
11334- }
11335- if (mUserPaddingEnd != UNDEFINED_PADDING) {
11336- mUserPaddingRight = mUserPaddingEnd;
11337- }
11338- if (mUserPaddingRight == UNDEFINED_PADDING) {
11339- mUserPaddingRight = mPaddingRight;
11340- }
11341- }
11357+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11358+ if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
11359+ // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
11360+ // left / right padding are used if defined. If they are not defined and start / end
11361+ // padding are defined (e.g. in Frameworks resources), then we use start / end and
11362+ // resolve them as left / right (layout direction is not taken into account).
11363+ if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
11364+ mUserPaddingLeft = mUserPaddingStart;
11365+ }
11366+ if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
11367+ mUserPaddingRight = mUserPaddingEnd;
11368+ }
1134211369
11343- mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11370+ mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11371+
11372+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11373+ mUserPaddingBottom);
11374+ } else {
11375+ // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11376+ // If start / end padding are defined, they will be resolved (hence overriding) to
11377+ // left / right or right / left depending on the resolved layout direction.
11378+ // If start / end padding are not defined, use the left / right ones.
11379+ int resolvedLayoutDirection = getResolvedLayoutDirection();
11380+ switch (resolvedLayoutDirection) {
11381+ case LAYOUT_DIRECTION_RTL:
11382+ if (mUserPaddingStart != UNDEFINED_PADDING) {
11383+ mUserPaddingRight = mUserPaddingStart;
11384+ }
11385+ if (mUserPaddingEnd != UNDEFINED_PADDING) {
11386+ mUserPaddingLeft = mUserPaddingEnd;
11387+ }
11388+ break;
11389+ case LAYOUT_DIRECTION_LTR:
11390+ default:
11391+ if (mUserPaddingStart != UNDEFINED_PADDING) {
11392+ mUserPaddingLeft = mUserPaddingStart;
11393+ }
11394+ if (mUserPaddingEnd != UNDEFINED_PADDING) {
11395+ mUserPaddingRight = mUserPaddingEnd;
11396+ }
11397+ }
11398+
11399+ mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11400+
11401+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11402+ mUserPaddingBottom);
11403+ onPaddingChanged(resolvedLayoutDirection);
11404+ }
1134411405
11345- internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
11346- onPaddingChanged(resolvedLayoutDirection);
1134711406 mPrivateFlags2 |= PADDING_RESOLVED;
1134811407 }
1134911408
@@ -14016,6 +14075,8 @@ public void setBackgroundDrawable(Drawable background) {
1401614075 }
1401714076 background.setLayoutDirection(getResolvedLayoutDirection());
1401814077 if (background.getPadding(padding)) {
14078+ // Reset padding resolution
14079+ mPrivateFlags2 &= ~PADDING_RESOLVED;
1401914080 switch (background.getLayoutDirection()) {
1402014081 case LAYOUT_DIRECTION_RTL:
1402114082 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
@@ -14112,13 +14173,19 @@ public Drawable getBackground() {
1411214173 * @param bottom the bottom padding in pixels
1411314174 */
1411414175 public void setPadding(int left, int top, int right, int bottom) {
14176+ // Reset padding resolution
14177+ mPrivateFlags2 &= ~PADDING_RESOLVED;
14178+
1411514179 mUserPaddingStart = UNDEFINED_PADDING;
1411614180 mUserPaddingEnd = UNDEFINED_PADDING;
1411714181
1411814182 internalSetPadding(left, top, right, bottom);
1411914183 }
1412014184
14121- void internalSetPadding(int left, int top, int right, int bottom) {
14185+ /**
14186+ * @hide
14187+ */
14188+ protected void internalSetPadding(int left, int top, int right, int bottom) {
1412214189 mUserPaddingLeft = left;
1412314190 mUserPaddingRight = right;
1412414191 mUserPaddingBottom = bottom;
@@ -14193,6 +14260,9 @@ void internalSetPadding(int left, int top, int right, int bottom) {
1419314260 * @param bottom the bottom padding in pixels
1419414261 */
1419514262 public void setPaddingRelative(int start, int top, int end, int bottom) {
14263+ // Reset padding resolution
14264+ mPrivateFlags2 &= ~PADDING_RESOLVED;
14265+
1419614266 mUserPaddingStart = start;
1419714267 mUserPaddingEnd = end;
1419814268
@@ -14234,6 +14304,9 @@ public int getPaddingBottom() {
1423414304 * @return the left padding in pixels
1423514305 */
1423614306 public int getPaddingLeft() {
14307+ if (!isPaddingResolved()) {
14308+ resolvePadding();
14309+ }
1423714310 return mPaddingLeft;
1423814311 }
1423914312
@@ -14245,6 +14318,9 @@ public int getPaddingLeft() {
1424514318 * @return the start padding in pixels
1424614319 */
1424714320 public int getPaddingStart() {
14321+ if (!isPaddingResolved()) {
14322+ resolvePadding();
14323+ }
1424814324 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
1424914325 mPaddingRight : mPaddingLeft;
1425014326 }
@@ -14257,6 +14333,9 @@ public int getPaddingStart() {
1425714333 * @return the right padding in pixels
1425814334 */
1425914335 public int getPaddingRight() {
14336+ if (!isPaddingResolved()) {
14337+ resolvePadding();
14338+ }
1426014339 return mPaddingRight;
1426114340 }
1426214341
@@ -14268,6 +14347,9 @@ public int getPaddingRight() {
1426814347 * @return the end padding in pixels
1426914348 */
1427014349 public int getPaddingEnd() {
14350+ if (!isPaddingResolved()) {
14351+ resolvePadding();
14352+ }
1427114353 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
1427214354 mPaddingLeft : mPaddingRight;
1427314355 }
@@ -14913,10 +14995,6 @@ public void requestLayout() {
1491314995 mPrivateFlags |= FORCE_LAYOUT;
1491414996 mPrivateFlags |= INVALIDATED;
1491514997
14916- if (mLayoutParams != null) {
14917- mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
14918- }
14919-
1492014998 if (mParent != null && !mParent.isLayoutRequested()) {
1492114999 mParent.requestLayout();
1492215000 }
@@ -14960,7 +15038,7 @@ public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
1496015038 // first clears the measured dimension flag
1496115039 mPrivateFlags &= ~MEASURED_DIMENSION_SET;
1496215040
14963- if ((mPrivateFlags2 & PADDING_RESOLVED) == 0 ) {
15041+ if (!isPaddingResolved() ) {
1496415042 resolvePadding();
1496515043 }
1496615044
0 commit comments