am 54e5a825: Merge "Improve resolution of RTL related properties" into jb-mr1-dev

* commit '54e5a825f2f82839e63e37ec32dc1b0757e95dfe':
  Improve resolution of RTL related properties
This commit is contained in:
Fabrice Di Meglio
2012-08-17 10:12:18 -07:00
committed by Android Git Automerger
3 changed files with 177 additions and 69 deletions

View File

@@ -2789,6 +2789,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.ExportedProperty(category = "padding") @ViewDebug.ExportedProperty(category = "padding")
int mUserPaddingEnd; int mUserPaddingEnd;
/**
* Whether a left padding has been defined during layout inflation.
*
* @hide
*/
boolean mUserPaddingLeftDefined = false;
/**
* Whether a right padding has been defined during layout inflation.
*
* @hide
*/
boolean mUserPaddingRightDefined = false;
/** /**
* Default undefined padding * Default undefined padding
*/ */
@@ -3195,8 +3209,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean transformSet = false; boolean transformSet = false;
int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
int overScrollMode = mOverScrollMode; int overScrollMode = mOverScrollMode;
boolean initializeScrollbars = false;
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
final int N = a.getIndexCount(); final int N = a.getIndexCount();
for (int i = 0; i < N; i++) { for (int i = 0; i < N; i++) {
int attr = a.getIndex(i); int attr = a.getIndex(i);
@@ -3206,15 +3223,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
break; break;
case com.android.internal.R.styleable.View_padding: case com.android.internal.R.styleable.View_padding:
padding = a.getDimensionPixelSize(attr, -1); padding = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftDefined = true;
mUserPaddingRightDefined = true;
break; break;
case com.android.internal.R.styleable.View_paddingLeft: case com.android.internal.R.styleable.View_paddingLeft:
leftPadding = a.getDimensionPixelSize(attr, -1); leftPadding = a.getDimensionPixelSize(attr, -1);
mUserPaddingLeftDefined = true;
break; break;
case com.android.internal.R.styleable.View_paddingTop: case com.android.internal.R.styleable.View_paddingTop:
topPadding = a.getDimensionPixelSize(attr, -1); topPadding = a.getDimensionPixelSize(attr, -1);
break; break;
case com.android.internal.R.styleable.View_paddingRight: case com.android.internal.R.styleable.View_paddingRight:
rightPadding = a.getDimensionPixelSize(attr, -1); rightPadding = a.getDimensionPixelSize(attr, -1);
mUserPaddingRightDefined = true;
break; break;
case com.android.internal.R.styleable.View_paddingBottom: case com.android.internal.R.styleable.View_paddingBottom:
bottomPadding = a.getDimensionPixelSize(attr, -1); bottomPadding = a.getDimensionPixelSize(attr, -1);
@@ -3359,12 +3380,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (scrollbars != SCROLLBARS_NONE) { if (scrollbars != SCROLLBARS_NONE) {
viewFlagValues |= scrollbars; viewFlagValues |= scrollbars;
viewFlagMasks |= SCROLLBARS_MASK; viewFlagMasks |= SCROLLBARS_MASK;
initializeScrollbars(a); initializeScrollbars = true;
} }
break; break;
//noinspection deprecation //noinspection deprecation
case R.styleable.View_fadingEdge: case R.styleable.View_fadingEdge:
if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) { if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
// Ignore the attribute starting with ICS // Ignore the attribute starting with ICS
break; break;
} }
@@ -3496,12 +3517,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} }
} }
a.recycle();
setOverScrollMode(overScrollMode); setOverScrollMode(overScrollMode);
// Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
// layout direction). Those cached values will be used later during padding resolution. // the resolved layout direction). Those cached values will be used later during padding
// resolution.
mUserPaddingStart = startPadding; mUserPaddingStart = startPadding;
mUserPaddingEnd = endPadding; mUserPaddingEnd = endPadding;
@@ -3529,6 +3549,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setFlags(viewFlagValues, viewFlagMasks); setFlags(viewFlagValues, viewFlagMasks);
} }
if (initializeScrollbars) {
initializeScrollbars(a);
}
a.recycle();
// Needs to be called after mViewFlags is set // Needs to be called after mViewFlags is set
if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
recomputePadding(); recomputePadding();
@@ -5533,10 +5559,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Reset the current layout direction and the resolved one // Reset the current layout direction and the resolved one
mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK; mPrivateFlags2 &= ~LAYOUT_DIRECTION_MASK;
resetResolvedLayoutDirection(); resetResolvedLayoutDirection();
// Set the new layout direction (filtered) and ask for a layout pass // Reset padding resolution
mPrivateFlags2 &= ~PADDING_RESOLVED;
// Set the new layout direction (filtered)
mPrivateFlags2 |= mPrivateFlags2 |=
((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK); ((layoutDirection << LAYOUT_DIRECTION_MASK_SHIFT) & LAYOUT_DIRECTION_MASK);
resolvePadding(); resolveRtlProperties();
// ... and ask for a layout pass
requestLayout(); requestLayout();
} }
} }
@@ -5552,6 +5581,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
}) })
public int getResolvedLayoutDirection() { public int getResolvedLayoutDirection() {
final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
if (targetSdkVersion < JELLY_BEAN_MR1) {
mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
return LAYOUT_DIRECTION_LTR;
}
// The layout direction will be resolved only if needed // The layout direction will be resolved only if needed
if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) { if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
resolveLayoutDirection(); resolveLayoutDirection();
@@ -9657,12 +9691,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
throw new NullPointerException("Layout parameters cannot be null"); throw new NullPointerException("Layout parameters cannot be null");
} }
mLayoutParams = params; mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) { if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params); ((ViewGroup) mParent).onSetLayoutParams(this, params);
} }
requestLayout(); requestLayout();
} }
/**
* Resolve the layout parameters depending on the resolved layout direction
*/
private void resolveLayoutParams() {
if (mLayoutParams != null) {
mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
}
}
/** /**
* Set the scrolled position of your view. This will cause a call to * Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be * {@link #onScrollChanged(int, int, int, int)} and the view will be
@@ -11197,12 +11241,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
jumpDrawablesToCurrentState(); jumpDrawablesToCurrentState();
// Order is important here: LayoutDirection MUST be resolved before Padding resolveRtlProperties();
// and TextDirection
resolveLayoutDirection();
resolvePadding();
resolveTextDirection();
resolveTextAlignment();
clearAccessibilityFocus(); clearAccessibilityFocus();
if (isFocused()) { if (isFocused()) {
@@ -11215,6 +11254,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} }
} }
void resolveRtlProperties() {
// Order is important here: LayoutDirection MUST be resolved first...
resolveLayoutDirection();
// ... then we can resolve the others properties depending on the resolved LayoutDirection.
resolvePadding();
resolveLayoutParams();
resolveTextDirection();
resolveTextAlignment();
}
/** /**
* @see #onScreenStateChanged(int) * @see #onScreenStateChanged(int)
*/ */
@@ -11294,56 +11343,66 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void onResolvedLayoutDirectionChanged() { public void onResolvedLayoutDirectionChanged() {
} }
/**
* Return if padding has been resolved
*/
boolean isPaddingResolved() {
return (mPrivateFlags2 & PADDING_RESOLVED) != 0;
}
/** /**
* Resolve padding depending on layout direction. * Resolve padding depending on layout direction.
*/ */
public void resolvePadding() { public void resolvePadding() {
// If the user specified the absolute padding (either with android:padding or final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
// android:paddingLeft/Top/Right/Bottom), use this padding, otherwise if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
// use the default padding or the padding from the background drawable // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
// (stored at this point in mPadding*) // left / right padding are used if defined. If they are not defined and start / end
int resolvedLayoutDirection = getResolvedLayoutDirection(); // padding are defined (e.g. in Frameworks resources), then we use start / end and
switch (resolvedLayoutDirection) { // resolve them as left / right (layout direction is not taken into account).
case LAYOUT_DIRECTION_RTL: if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
// Start user padding override Right user padding. Otherwise, if Right user mUserPaddingLeft = mUserPaddingStart;
// padding is not defined, use the default Right padding. If Right user padding }
// is defined, just use it. if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
if (mUserPaddingStart != UNDEFINED_PADDING) { mUserPaddingRight = mUserPaddingEnd;
mUserPaddingRight = mUserPaddingStart; }
}
if (mUserPaddingRight == UNDEFINED_PADDING) { mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
mUserPaddingRight = mPaddingRight;
} internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
if (mUserPaddingEnd != UNDEFINED_PADDING) { mUserPaddingBottom);
mUserPaddingLeft = mUserPaddingEnd; } else {
} // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
if (mUserPaddingLeft == UNDEFINED_PADDING) { // If start / end padding are defined, they will be resolved (hence overriding) to
mUserPaddingLeft = mPaddingLeft; // left / right or right / left depending on the resolved layout direction.
} // If start / end padding are not defined, use the left / right ones.
break; int resolvedLayoutDirection = getResolvedLayoutDirection();
case LAYOUT_DIRECTION_LTR: switch (resolvedLayoutDirection) {
default: case LAYOUT_DIRECTION_RTL:
// Start user padding override Left user padding. Otherwise, if Left user if (mUserPaddingStart != UNDEFINED_PADDING) {
// padding is not defined, use the default left padding. If Left user padding mUserPaddingRight = mUserPaddingStart;
// is defined, just use it. }
if (mUserPaddingStart != UNDEFINED_PADDING) { if (mUserPaddingEnd != UNDEFINED_PADDING) {
mUserPaddingLeft = mUserPaddingStart; mUserPaddingLeft = mUserPaddingEnd;
} }
if (mUserPaddingLeft == UNDEFINED_PADDING) { break;
mUserPaddingLeft = mPaddingLeft; case LAYOUT_DIRECTION_LTR:
} default:
if (mUserPaddingEnd != UNDEFINED_PADDING) { if (mUserPaddingStart != UNDEFINED_PADDING) {
mUserPaddingRight = mUserPaddingEnd; mUserPaddingLeft = mUserPaddingStart;
} }
if (mUserPaddingRight == UNDEFINED_PADDING) { if (mUserPaddingEnd != UNDEFINED_PADDING) {
mUserPaddingRight = mPaddingRight; mUserPaddingRight = mUserPaddingEnd;
} }
}
mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
mUserPaddingBottom);
onPaddingChanged(resolvedLayoutDirection);
} }
mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
onPaddingChanged(resolvedLayoutDirection);
mPrivateFlags2 |= PADDING_RESOLVED; mPrivateFlags2 |= PADDING_RESOLVED;
} }
@@ -14016,6 +14075,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} }
background.setLayoutDirection(getResolvedLayoutDirection()); background.setLayoutDirection(getResolvedLayoutDirection());
if (background.getPadding(padding)) { if (background.getPadding(padding)) {
// Reset padding resolution
mPrivateFlags2 &= ~PADDING_RESOLVED;
switch (background.getLayoutDirection()) { switch (background.getLayoutDirection()) {
case LAYOUT_DIRECTION_RTL: case LAYOUT_DIRECTION_RTL:
internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
@@ -14112,13 +14173,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param bottom the bottom padding in pixels * @param bottom the bottom padding in pixels
*/ */
public void setPadding(int left, int top, int right, int bottom) { public void setPadding(int left, int top, int right, int bottom) {
// Reset padding resolution
mPrivateFlags2 &= ~PADDING_RESOLVED;
mUserPaddingStart = UNDEFINED_PADDING; mUserPaddingStart = UNDEFINED_PADDING;
mUserPaddingEnd = UNDEFINED_PADDING; mUserPaddingEnd = UNDEFINED_PADDING;
internalSetPadding(left, top, right, bottom); internalSetPadding(left, top, right, bottom);
} }
void internalSetPadding(int left, int top, int right, int bottom) { /**
* @hide
*/
protected void internalSetPadding(int left, int top, int right, int bottom) {
mUserPaddingLeft = left; mUserPaddingLeft = left;
mUserPaddingRight = right; mUserPaddingRight = right;
mUserPaddingBottom = bottom; mUserPaddingBottom = bottom;
@@ -14193,6 +14260,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param bottom the bottom padding in pixels * @param bottom the bottom padding in pixels
*/ */
public void setPaddingRelative(int start, int top, int end, int bottom) { public void setPaddingRelative(int start, int top, int end, int bottom) {
// Reset padding resolution
mPrivateFlags2 &= ~PADDING_RESOLVED;
mUserPaddingStart = start; mUserPaddingStart = start;
mUserPaddingEnd = end; mUserPaddingEnd = end;
@@ -14234,6 +14304,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the left padding in pixels * @return the left padding in pixels
*/ */
public int getPaddingLeft() { public int getPaddingLeft() {
if (!isPaddingResolved()) {
resolvePadding();
}
return mPaddingLeft; return mPaddingLeft;
} }
@@ -14245,6 +14318,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the start padding in pixels * @return the start padding in pixels
*/ */
public int getPaddingStart() { public int getPaddingStart() {
if (!isPaddingResolved()) {
resolvePadding();
}
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ? return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
mPaddingRight : mPaddingLeft; mPaddingRight : mPaddingLeft;
} }
@@ -14257,6 +14333,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the right padding in pixels * @return the right padding in pixels
*/ */
public int getPaddingRight() { public int getPaddingRight() {
if (!isPaddingResolved()) {
resolvePadding();
}
return mPaddingRight; return mPaddingRight;
} }
@@ -14268,6 +14347,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the end padding in pixels * @return the end padding in pixels
*/ */
public int getPaddingEnd() { public int getPaddingEnd() {
if (!isPaddingResolved()) {
resolvePadding();
}
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ? return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
mPaddingLeft : mPaddingRight; mPaddingLeft : mPaddingRight;
} }
@@ -14913,10 +14995,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags |= FORCE_LAYOUT; mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED; mPrivateFlags |= INVALIDATED;
if (mLayoutParams != null) {
mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
}
if (mParent != null && !mParent.isLayoutRequested()) { if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout(); mParent.requestLayout();
} }
@@ -14960,7 +15038,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// first clears the measured dimension flag // first clears the measured dimension flag
mPrivateFlags &= ~MEASURED_DIMENSION_SET; mPrivateFlags &= ~MEASURED_DIMENSION_SET;
if ((mPrivateFlags2 & PADDING_RESOLVED) == 0) { if (!isPaddingResolved()) {
resolvePadding(); resolvePadding();
} }

View File

@@ -2517,8 +2517,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
super.dispatchDetachedFromWindow(); super.dispatchDetachedFromWindow();
} }
/**
* @hide
*/
@Override @Override
void internalSetPadding(int left, int top, int right, int bottom) { protected void internalSetPadding(int left, int top, int right, int bottom) {
super.internalSetPadding(left, top, right, bottom); super.internalSetPadding(left, top, right, bottom);
if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingBottom) != 0) { if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingBottom) != 0) {
@@ -3372,6 +3375,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (child.hasTransientState()) { if (child.hasTransientState()) {
childHasTransientStateChanged(child, true); childHasTransientStateChanged(child, true);
} }
if (child.getLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
child.resetResolvedLayoutDirection();
child.resolveRtlProperties();
}
} }
private void addInArray(View child, int index) { private void addInArray(View child, int index) {
@@ -3597,6 +3605,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
childHasTransientStateChanged(view, false); childHasTransientStateChanged(view, false);
} }
view.resetResolvedLayoutDirection();
onViewRemoved(view); onViewRemoved(view);
needGlobalAttributesUpdate(false); needGlobalAttributesUpdate(false);

View File

@@ -151,7 +151,7 @@ public class CheckedTextView extends TextView implements Checkable {
mCheckMarkWidth = 0; mCheckMarkWidth = 0;
} }
mCheckMarkDrawable = d; mCheckMarkDrawable = d;
// Do padding resolution. This will call setPadding() and do a requestLayout() if needed. // Do padding resolution. This will call internalSetPadding() and do a requestLayout() if needed.
resolvePadding(); resolvePadding();
} }
@@ -169,6 +169,19 @@ public class CheckedTextView extends TextView implements Checkable {
return mCheckMarkDrawable; return mCheckMarkDrawable;
} }
/**
* @hide
*/
@Override
protected void internalSetPadding(int left, int top, int right, int bottom) {
super.internalSetPadding(left, top, right, bottom);
if (isLayoutRtl()) {
mBasePadding = mUserPaddingLeft;
} else {
mBasePadding = mUserPaddingRight;
}
}
@Override @Override
public void onPaddingChanged(int layoutDirection) { public void onPaddingChanged(int layoutDirection) {
int newPadding = (mCheckMarkDrawable != null) ? int newPadding = (mCheckMarkDrawable != null) ?
@@ -221,8 +234,15 @@ public class CheckedTextView extends TextView implements Checkable {
final int width = getWidth(); final int width = getWidth();
final int top = y; final int top = y;
final int bottom = top + height; final int bottom = top + height;
final int left = isLayoutRtl ? getPaddingEnd() : width - getPaddingEnd(); final int left;
final int right = left + mCheckMarkWidth; final int right;
if (isLayoutRtl) {
right = getPaddingEnd();
left = right - mCheckMarkWidth;
} else {
left = width - getPaddingEnd();
right = left + mCheckMarkWidth;
}
checkMarkDrawable.setBounds( left, top, right, bottom); checkMarkDrawable.setBounds( left, top, right, bottom);
checkMarkDrawable.draw(canvas); checkMarkDrawable.draw(canvas);
} }