diff options
| author | Fabrice Di Meglio <fdimeglio@google.com> | 2013-02-19 17:42:13 -0800 |
|---|---|---|
| committer | Fabrice Di Meglio <fdimeglio@google.com> | 2013-03-05 14:10:23 -0800 |
| commit | c44d880c508ded633b61930e1964df70876ec42f (patch) | |
| tree | eaa676ea41f44a52abdf04b9651bfd21e1b1b07d /core/java/android/widget/RelativeLayout.java | |
| parent | c7ede61f592a2389790ce0993b8ee0a16de54b5e (diff) | |
Fix bug #8217354 Suspicious behavior in RTL support for a RelativeLayout
- make rules resolution follow the same pattern as padding and other
RTL properties
Change-Id: Ia0f460f188063f950bc311b51765fdec2f96f542
Diffstat (limited to 'core/java/android/widget/RelativeLayout.java')
| -rw-r--r-- | core/java/android/widget/RelativeLayout.java | 146 |
1 files changed, 128 insertions, 18 deletions
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index deec41cf7eff..166e6f98fbf1 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -42,6 +42,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.RemoteViews.RemoteView; +import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static android.util.Log.d; /** @@ -1223,6 +1224,7 @@ public class RelativeLayout extends ViewGroup { private int mEnd = DEFAULT_RELATIVE; private boolean mRulesChanged = false; + private boolean mIsRtlCompatibilityMode = false; /** * When true, uses the parent as the anchor if the anchor doesn't exist or if @@ -1237,6 +1239,10 @@ public class RelativeLayout extends ViewGroup { TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.RelativeLayout_Layout); + final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion; + mIsRtlCompatibilityMode = (targetSdkVersion < JELLY_BEAN_MR1 || + !c.getApplicationInfo().hasRtlSupport()); + final int[] rules = mRules; //noinspection MismatchedReadAndWriteOfArray final int[] initialRules = mInitialRules; @@ -1405,28 +1411,132 @@ public class RelativeLayout extends ViewGroup { mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0); } + // The way we are resolving rules depends on the layout direction and if we are pre JB MR1 + // or not. + // + // If we are pre JB MR1 (said as "RTL compatibility mode"), "left"/"right" rules are having + // predominance over any "start/end" rules that could have been defined. A special case: + // if no "left"/"right" rule has been defined and "start"/"end" rules are defined then we + // resolve those "start"/"end" rules to "left"/"right" respectively. + // + // If we are JB MR1+, then "start"/"end" rules are having predominance over "left"/"right" + // rules. If no "start"/"end" rule is defined then we use "left"/"right" rules. + // + // In all cases, the result of the resolution should clear the "start"/"end" rules to leave + // only the "left"/"right" rules at the end. private void resolveRules(int layoutDirection) { final boolean isLayoutRtl = (layoutDirection == View.LAYOUT_DIRECTION_RTL); + // Reset to initial state System.arraycopy(mInitialRules, LEFT_OF, mRules, LEFT_OF, VERB_COUNT); - // Apply rules depending on direction - if (mRules[ALIGN_START] != 0) { - mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START]; - } - if (mRules[ALIGN_END] != 0) { - mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END]; - } - if (mRules[START_OF] != 0) { - mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF]; - } - if (mRules[END_OF] != 0) { - mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF]; - } - if (mRules[ALIGN_PARENT_START] != 0) { - mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START]; - } - if (mRules[ALIGN_PARENT_END] != 0) { - mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END]; + + // Apply rules depending on direction and if we are in RTL compatibility mode + if (mIsRtlCompatibilityMode) { + if (mRules[ALIGN_START] != 0) { + if (mRules[ALIGN_LEFT] == 0) { + // "left" rule is not defined but "start" rule is: use the "start" rule as + // the "left" rule + mRules[ALIGN_LEFT] = mRules[ALIGN_START]; + } + mRules[ALIGN_START] = 0; + } + + if (mRules[ALIGN_END] != 0) { + if (mRules[ALIGN_RIGHT] == 0) { + // "right" rule is not defined but "end" rule is: use the "end" rule as the + // "right" rule + mRules[ALIGN_RIGHT] = mRules[ALIGN_END]; + } + mRules[ALIGN_END] = 0; + } + + if (mRules[START_OF] != 0) { + if (mRules[LEFT_OF] == 0) { + // "left" rule is not defined but "start" rule is: use the "start" rule as + // the "left" rule + mRules[LEFT_OF] = mRules[START_OF]; + } + mRules[START_OF] = 0; + } + + if (mRules[END_OF] != 0) { + if (mRules[RIGHT_OF] == 0) { + // "right" rule is not defined but "end" rule is: use the "end" rule as the + // "right" rule + mRules[RIGHT_OF] = mRules[END_OF]; + } + mRules[END_OF] = 0; + } + + if (mRules[ALIGN_PARENT_START] != 0) { + if (mRules[ALIGN_PARENT_LEFT] == 0) { + // "left" rule is not defined but "start" rule is: use the "start" rule as + // the "left" rule + mRules[ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START]; + } + mRules[ALIGN_PARENT_START] = 0; + } + + if (mRules[ALIGN_PARENT_RIGHT] == 0) { + if (mRules[ALIGN_PARENT_RIGHT] == 0) { + // "right" rule is not defined but "end" rule is: use the "end" rule as the + // "right" rule + mRules[ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END]; + } + mRules[ALIGN_PARENT_END] = 0; + } + } else { + // JB MR1+ case + if ((mRules[ALIGN_START] != 0 || mRules[ALIGN_END] != 0) && + (mRules[ALIGN_LEFT] != 0 || mRules[ALIGN_RIGHT] != 0)) { + // "start"/"end" rules take precedence over "left"/"right" rules + mRules[ALIGN_LEFT] = 0; + mRules[ALIGN_RIGHT] = 0; + } + if (mRules[ALIGN_START] != 0) { + // "start" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START]; + mRules[ALIGN_START] = 0; + } + if (mRules[ALIGN_END] != 0) { + // "end" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END]; + mRules[ALIGN_END] = 0; + } + + if ((mRules[START_OF] != 0 || mRules[END_OF] != 0) && + (mRules[LEFT_OF] != 0 || mRules[RIGHT_OF] != 0)) { + // "start"/"end" rules take precedence over "left"/"right" rules + mRules[LEFT_OF] = 0; + mRules[RIGHT_OF] = 0; + } + if (mRules[START_OF] != 0) { + // "start" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF]; + mRules[START_OF] = 0; + } + if (mRules[END_OF] != 0) { + // "end" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF]; + mRules[END_OF] = 0; + } + + if ((mRules[ALIGN_PARENT_START] != 0 || mRules[ALIGN_PARENT_END] != 0) && + (mRules[ALIGN_PARENT_LEFT] != 0 || mRules[ALIGN_PARENT_RIGHT] != 0)) { + // "start"/"end" rules take precedence over "left"/"right" rules + mRules[ALIGN_PARENT_LEFT] = 0; + mRules[ALIGN_PARENT_RIGHT] = 0; + } + if (mRules[ALIGN_PARENT_START] != 0) { + // "start" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START]; + mRules[ALIGN_PARENT_START] = 0; + } + if (mRules[ALIGN_PARENT_END] != 0) { + // "end" rule resolved to "left" or "right" depending on the direction + mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END]; + mRules[ALIGN_PARENT_END] = 0; + } } mRulesChanged = false; } |
