diff options
author | Fabrice Di Meglio <fdimeglio@google.com> | 2012-06-25 15:49:11 -0700 |
---|---|---|
committer | Fabrice Di Meglio <fdimeglio@google.com> | 2012-07-12 17:39:12 -0700 |
commit | cf1ba0298c48ae56608ed556dc715eb69c54f9b9 (patch) | |
tree | 4f0b83de4bb8585506fed122a215757e87503754 | |
parent | 92bd5f95ca078a795db7c2efd30e85d4260561de (diff) | |
download | frameworks_base-cf1ba0298c48ae56608ed556dc715eb69c54f9b9.zip frameworks_base-cf1ba0298c48ae56608ed556dc715eb69c54f9b9.tar.gz frameworks_base-cf1ba0298c48ae56608ed556dc715eb69c54f9b9.tar.bz2 |
Make ActionBar aware of layout direction
- see bug #5429822 UI should be mirrored for RTL locales (Arabic, Hebrew, farsi)
Change-Id: Iea8a512311ee99548f39bbbe342f21eabaffbe09
-rw-r--r-- | core/java/android/app/ActionBar.java | 9 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/AbsActionBarView.java | 20 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ActionBarContextView.java | 21 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ActionBarView.java | 127 | ||||
-rw-r--r-- | core/res/res/layout/action_bar_home.xml | 6 | ||||
-rw-r--r-- | core/res/res/layout/action_bar_title_item.xml | 2 |
6 files changed, 119 insertions, 66 deletions
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index cff16ff..2337790 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -918,6 +918,8 @@ public abstract class ActionBar { @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"), @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"), @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"), + @ViewDebug.IntToString(from = Gravity.START, to = "START"), + @ViewDebug.IntToString(from = Gravity.END, to = "END"), @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"), @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"), @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"), @@ -925,7 +927,7 @@ public abstract class ActionBar { @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"), @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL") }) - public int gravity = -1; + public int gravity = Gravity.NO_GRAVITY; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); @@ -933,13 +935,14 @@ public abstract class ActionBar { TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ActionBar_LayoutParams); gravity = a.getInt( - com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity, -1); + com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity, + Gravity.NO_GRAVITY); a.recycle(); } public LayoutParams(int width, int height) { super(width, height); - this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT; + this.gravity = Gravity.CENTER_VERTICAL | Gravity.START; } public LayoutParams(int width, int height, int gravity) { diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java index 25a9c54..860a8d9 100644 --- a/core/java/com/android/internal/widget/AbsActionBarView.java +++ b/core/java/com/android/internal/widget/AbsActionBarView.java @@ -219,24 +219,22 @@ public abstract class AbsActionBarView extends ViewGroup { return Math.max(0, availableWidth); } - protected int positionChild(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x, childTop, x + childWidth, childTop + childHeight); - - return childWidth; + static protected int next(int x, int val, boolean isRtl) { + return isRtl ? x - val : x + val; } - protected int positionChildInverse(View child, int x, int y, int contentHeight) { + protected int positionChild(View child, int x, int y, int contentHeight, boolean reverse) { int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); int childTop = y + (contentHeight - childHeight) / 2; - child.layout(x - childWidth, childTop, x, childTop + childHeight); + if (reverse) { + child.layout(x - childWidth, childTop, x, childTop + childHeight); + } else { + child.layout(x, childTop, x + childWidth, childTop + childHeight); + } - return childWidth; + return (reverse ? -childWidth : childWidth); } protected class VisibilityAnimListener implements Animator.AnimatorListener { diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index 16f08f5..8bc1081 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -454,15 +454,18 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - int x = getPaddingLeft(); + final boolean isLayoutRtl = isLayoutRtl(); + int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft(); final int y = getPaddingTop(); final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); if (mClose != null && mClose.getVisibility() != GONE) { MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams(); - x += lp.leftMargin; - x += positionChild(mClose, x, y, contentHeight); - x += lp.rightMargin; + final int startMargin = (isLayoutRtl ? lp.rightMargin : lp.leftMargin); + final int endMargin = (isLayoutRtl ? lp.leftMargin : lp.rightMargin); + x = next(x, startMargin, isLayoutRtl); + x += positionChild(mClose, x, y, contentHeight, isLayoutRtl); + x = next(x, endMargin, isLayoutRtl); if (mAnimateInOnLayout) { mAnimationMode = ANIMATE_IN; @@ -473,17 +476,17 @@ public class ActionBarContextView extends AbsActionBarView implements AnimatorLi } if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) { - x += positionChild(mTitleLayout, x, y, contentHeight); + x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl); } if (mCustomView != null) { - x += positionChild(mCustomView, x, y, contentHeight); + x += positionChild(mCustomView, x, y, contentHeight, isLayoutRtl); } - - x = r - l - getPaddingRight(); + + x = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight(); if (mMenuView != null) { - x -= positionChildInverse(mMenuView, x, y, contentHeight); + x += positionChild(mMenuView, x, y, contentHeight, !isLayoutRtl); } } diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 450f418..7da8d46 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -84,7 +84,7 @@ public class ActionBarView extends AbsActionBarView { ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_TITLE; - private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL; + private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL; private int mNavigationMode; private int mDisplayOptions = -1; @@ -872,7 +872,7 @@ public class ActionBarView extends AbsActionBarView { } homeLayout.measure(homeWidthSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset(); + final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset(); availableWidth = Math.max(0, availableWidth - homeWidth); leftOfCenter = Math.max(0, availableWidth - homeWidth); } @@ -1010,8 +1010,6 @@ public class ActionBarView extends AbsActionBarView { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - int x = getPaddingLeft(); - final int y = getPaddingTop(); final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); if (contentHeight <= 0) { @@ -1019,13 +1017,23 @@ public class ActionBarView extends AbsActionBarView { return; } + final boolean isLayoutRtl = isLayoutRtl(); + final int direction = isLayoutRtl ? +1 : -1; + int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight(); + // In LTR mode, we start from left padding and go to the right; in RTL mode, we start + // from the padding right and go to the left (in reverse way) + int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft(); + final int y = getPaddingTop(); + HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; boolean needsTouchDelegate = false; int homeSlop = mMaxHomeSlop; int homeRight = 0; if (homeLayout.getVisibility() != GONE) { - final int leftOffset = homeLayout.getLeftOffset(); - x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset; + final int startOffset = homeLayout.getStartOffset(); + x += positionChild(homeLayout, + next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl); + x = next(x, startOffset, isLayoutRtl); needsTouchDelegate = homeLayout == mHomeLayout; homeRight = x; } @@ -1034,7 +1042,7 @@ public class ActionBarView extends AbsActionBarView { final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; if (showTitle) { - x += positionChild(mTitleLayout, x, y, contentHeight); + x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl); } switch (mNavigationMode) { @@ -1042,31 +1050,34 @@ public class ActionBarView extends AbsActionBarView { break; case ActionBar.NAVIGATION_MODE_LIST: if (mListNavLayout != null) { - if (showTitle) x += mItemPadding; + if (showTitle) { + x = next(x, mItemPadding, isLayoutRtl); + } homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0)); - x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding; + x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl); + x = next(x, mItemPadding, isLayoutRtl); } break; case ActionBar.NAVIGATION_MODE_TABS: if (mTabScrollView != null) { - if (showTitle) x += mItemPadding; + if (showTitle) x = next(x, mItemPadding, isLayoutRtl); homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0)); - x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding; + x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl); + x = next(x, mItemPadding, isLayoutRtl); } break; } } - int menuLeft = r - l - getPaddingRight(); if (mMenuView != null && mMenuView.getParent() == this) { - positionChildInverse(mMenuView, menuLeft, y, contentHeight); - menuLeft -= mMenuView.getMeasuredWidth(); + positionChild(mMenuView, menuStart, y, contentHeight, !isLayoutRtl); + menuStart += direction * mMenuView.getMeasuredWidth(); } if (mIndeterminateProgressView != null && mIndeterminateProgressView.getVisibility() != GONE) { - positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight); - menuLeft -= mIndeterminateProgressView.getMeasuredWidth(); + positionChild(mIndeterminateProgressView, menuStart, y, contentHeight, !isLayoutRtl); + menuStart += direction * mIndeterminateProgressView.getMeasuredWidth(); } View customView = null; @@ -1077,51 +1088,64 @@ public class ActionBarView extends AbsActionBarView { customView = mCustomNavView; } if (customView != null) { + final int resolvedLayoutDirection = getResolvedLayoutDirection(); ViewGroup.LayoutParams lp = customView.getLayoutParams(); + lp.onResolveLayoutDirection(resolvedLayoutDirection); final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? (ActionBar.LayoutParams) lp : null; - final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY; final int navWidth = customView.getMeasuredWidth(); int topMargin = 0; int bottomMargin = 0; if (ablp != null) { - x += ablp.leftMargin; - menuLeft -= ablp.rightMargin; + x = next(x, ablp.getMarginStart(), isLayoutRtl); + menuStart += direction * ablp.getMarginEnd(); topMargin = ablp.topMargin; bottomMargin = ablp.bottomMargin; } - int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + int hgravity = gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK; // See if we actually have room to truly center; if not push against left or right. if (hgravity == Gravity.CENTER_HORIZONTAL) { final int centeredLeft = ((mRight - mLeft) - navWidth) / 2; - if (centeredLeft < x) { - hgravity = Gravity.LEFT; - } else if (centeredLeft + navWidth > menuLeft) { - hgravity = Gravity.RIGHT; + if (isLayoutRtl) { + final int centeredStart = centeredLeft + navWidth; + final int centeredEnd = centeredLeft; + if (centeredStart > x) { + hgravity = Gravity.RIGHT; + } else if (centeredEnd < menuStart) { + hgravity = Gravity.LEFT; + } + } else { + final int centeredStart = centeredLeft; + final int centeredEnd = centeredLeft + navWidth; + if (centeredStart < x) { + hgravity = Gravity.LEFT; + } else if (centeredEnd > menuStart) { + hgravity = Gravity.RIGHT; + } } - } else if (gravity == -1) { - hgravity = Gravity.LEFT; + } else if (gravity == Gravity.NO_GRAVITY) { + hgravity = Gravity.START; } int xpos = 0; - switch (hgravity) { + switch (Gravity.getAbsoluteGravity(hgravity, resolvedLayoutDirection)) { case Gravity.CENTER_HORIZONTAL: xpos = ((mRight - mLeft) - navWidth) / 2; break; case Gravity.LEFT: - xpos = x; + xpos = isLayoutRtl ? menuStart : x; break; case Gravity.RIGHT: - xpos = menuLeft - navWidth; + xpos = isLayoutRtl ? x - navWidth : menuStart - navWidth; break; } int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; - if (gravity == -1) { + if (gravity == Gravity.NO_GRAVITY) { vgravity = Gravity.CENTER_VERTICAL; } @@ -1144,7 +1168,7 @@ public class ActionBarView extends AbsActionBarView { customView.layout(xpos, ypos, xpos + customWidth, ypos + customView.getMeasuredHeight()); homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0)); - x += customWidth; + x = next(x, customWidth, isLayoutRtl); } if (mProgressView != null) { @@ -1290,7 +1314,7 @@ public class ActionBarView extends AbsActionBarView { mIconView = (ImageView) findViewById(com.android.internal.R.id.home); } - public int getLeftOffset() { + public int getStartOffset() { return mUpView.getVisibility() == GONE ? mUpWidth : 0; } @@ -1340,25 +1364,50 @@ public class ActionBarView extends AbsActionBarView { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int vCenter = (b - t) / 2; - int width = r - l; + final boolean isLayoutRtl = isLayoutRtl(); + final int layoutDirection = getResolvedLayoutDirection(); + final int width = getWidth(); int upOffset = 0; if (mUpView.getVisibility() != GONE) { final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); final int upHeight = mUpView.getMeasuredHeight(); final int upWidth = mUpView.getMeasuredWidth(); - final int upTop = vCenter - upHeight / 2; - mUpView.layout(0, upTop, upWidth, upTop + upHeight); upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; - width -= upOffset; - l += upOffset; + final int upTop = vCenter - upHeight / 2; + final int upBottom = upTop + upHeight; + final int upRight; + final int upLeft; + if (isLayoutRtl) { + upRight = width; + upLeft = upRight - upWidth; + r -= upOffset; + } else { + upRight = upWidth; + upLeft = 0; + l += upOffset; + } + mUpView.layout(upLeft, upTop, upRight, upBottom); } + final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + iconLp.onResolveLayoutDirection(layoutDirection); final int iconHeight = mIconView.getMeasuredHeight(); final int iconWidth = mIconView.getMeasuredWidth(); final int hCenter = (r - l) / 2; - final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2); final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2); - mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); + final int iconBottom = iconTop + iconHeight; + final int iconLeft; + final int iconRight; + int marginStart = iconLp.getMarginStart(); + final int delta = Math.max(marginStart, hCenter - iconWidth / 2); + if (isLayoutRtl) { + iconRight = width - upOffset - delta; + iconLeft = iconRight - iconWidth; + } else { + iconLeft = upOffset + delta; + iconRight = iconLeft + iconWidth; + } + mIconView.layout(iconLeft, iconTop, iconRight, iconBottom); } } diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml index 96467d0..91af7e9 100644 --- a/core/res/res/layout/action_bar_home.xml +++ b/core/res/res/layout/action_bar_home.xml @@ -21,15 +21,15 @@ android:background="?android:attr/actionBarItemBackground" > <ImageView android:id="@android:id/up" android:src="?android:attr/homeAsUpIndicator" - android:layout_gravity="center_vertical|left" + android:layout_gravity="center_vertical|start" android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginRight="-8dip" /> + android:layout_marginEnd="-8dip" /> <ImageView android:id="@android:id/home" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginRight="8dip" + android:layout_marginEnd="8dip" android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding" android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding" android:layout_gravity="center" diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml index 2e21383..35c1264 100644 --- a/core/res/res/layout/action_bar_title_item.xml +++ b/core/res/res/layout/action_bar_title_item.xml @@ -31,7 +31,7 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical|left" + android:layout_gravity="center_vertical|start" android:orientation="vertical"> <TextView android:id="@+id/action_bar_title" android:layout_width="wrap_content" |