summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt13
-rw-r--r--core/java/android/view/Gravity.java97
-rw-r--r--core/java/android/view/View.java11
-rw-r--r--core/java/android/view/WindowManager.java4
-rw-r--r--core/java/android/widget/FrameLayout.java10
-rw-r--r--core/java/android/widget/GridView.java27
-rw-r--r--core/java/android/widget/ImageView.java5
-rw-r--r--core/java/android/widget/LinearLayout.java24
-rw-r--r--core/java/android/widget/ProgressBar.java6
-rw-r--r--core/java/android/widget/RelativeLayout.java35
-rw-r--r--core/java/android/widget/TableRow.java3
-rw-r--r--core/java/android/widget/TextView.java31
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuItemView.java2
-rw-r--r--core/java/com/android/internal/widget/TextProgressBar.java3
-rwxr-xr-xcore/res/res/values/attrs.xml8
-rw-r--r--core/tests/coretests/src/android/view/GravityTest.java72
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java24
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java2
20 files changed, 311 insertions, 70 deletions
diff --git a/api/current.txt b/api/current.txt
index dffb868..7dcb714 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8331,6 +8331,7 @@ package android.graphics.drawable {
method public android.graphics.Region getTransparentRegion();
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
+ method public boolean isLayoutRtlSelf();
method public boolean isStateful();
method public final boolean isVisible();
method public void jumpToCurrentState();
@@ -8361,6 +8362,10 @@ package android.graphics.drawable {
method public abstract void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
+ public static abstract interface Drawable.Callback2 implements android.graphics.drawable.Drawable.Callback {
+ method public abstract boolean isLayoutRtl(android.graphics.drawable.Drawable);
+ }
+
public static abstract class Drawable.ConstantState {
ctor public Drawable.ConstantState();
method public abstract int getChangingConfigurations();
@@ -20136,14 +20141,17 @@ package android.view {
method public static void apply(int, int, int, android.graphics.Rect, android.graphics.Rect);
method public static void apply(int, int, int, android.graphics.Rect, int, int, android.graphics.Rect);
method public static void applyDisplay(int, android.graphics.Rect, android.graphics.Rect);
+ method public static int getAbsoluteGravity(int, boolean);
method public static boolean isHorizontal(int);
method public static boolean isVertical(int);
+ field public static final int AFTER = 8388613; // 0x800005
field public static final int AXIS_CLIP = 8; // 0x8
field public static final int AXIS_PULL_AFTER = 4; // 0x4
field public static final int AXIS_PULL_BEFORE = 2; // 0x2
field public static final int AXIS_SPECIFIED = 1; // 0x1
field public static final int AXIS_X_SHIFT = 0; // 0x0
field public static final int AXIS_Y_SHIFT = 4; // 0x4
+ field public static final int BEFORE = 8388611; // 0x800003
field public static final int BOTTOM = 80; // 0x50
field public static final int CENTER = 17; // 0x11
field public static final int CENTER_HORIZONTAL = 1; // 0x1
@@ -20158,6 +20166,8 @@ package android.view {
field public static final int HORIZONTAL_GRAVITY_MASK = 7; // 0x7
field public static final int LEFT = 3; // 0x3
field public static final int NO_GRAVITY = 0; // 0x0
+ field public static final int RELATIVE_HORIZONTAL_DIRECTION = 8388608; // 0x800000
+ field public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = 8388615; // 0x800007
field public static final int RIGHT = 5; // 0x5
field public static final int TOP = 48; // 0x30
field public static final int VERTICAL_GRAVITY_MASK = 112; // 0x70
@@ -21136,7 +21146,7 @@ package android.view {
method public void recycle();
}
- public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
+ public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback2 android.view.KeyEvent.Callback {
ctor public View(android.content.Context);
ctor public View(android.content.Context, android.util.AttributeSet);
ctor public View(android.content.Context, android.util.AttributeSet, int);
@@ -21322,6 +21332,7 @@ package android.view {
method public boolean isInTouchMode();
method public boolean isLayoutRequested();
method public boolean isLayoutRtl();
+ method public boolean isLayoutRtl(android.graphics.drawable.Drawable);
method public boolean isLongClickable();
method public boolean isOpaque();
method protected boolean isPaddingOffsetRequired();
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index cf79638..176c487 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -80,9 +80,12 @@ public class Gravity
/** Flag to clip the edges of the object to its container along the
* horizontal axis. */
public static final int CLIP_HORIZONTAL = AXIS_CLIP<<AXIS_X_SHIFT;
-
+
+ /** Raw bit controlling whether the horizontal direction is relative (before/after) or not. */
+ public static final int RELATIVE_HORIZONTAL_DIRECTION = 0x00800000;
+
/**
- * Binary mask to get the horizontal gravity of a gravity.
+ * Binary mask to get the absolute horizontal gravity of a gravity.
*/
public static final int HORIZONTAL_GRAVITY_MASK = (AXIS_SPECIFIED |
AXIS_PULL_BEFORE | AXIS_PULL_AFTER) << AXIS_X_SHIFT;
@@ -106,8 +109,19 @@ public class Gravity
*/
public static final int DISPLAY_CLIP_HORIZONTAL = 0x01000000;
+ /** Push object to x-axis position before its container, not changing its size. */
+ public static final int BEFORE = RELATIVE_HORIZONTAL_DIRECTION | LEFT;
+
+ /** Push object to x-axis position after its container, not changing its size. */
+ public static final int AFTER = RELATIVE_HORIZONTAL_DIRECTION | RIGHT;
+
/**
- * Apply a gravity constant to an object.
+ * Binary mask for the horizontal gravity and script specific direction bit.
+ */
+ public static final int RELATIVE_HORIZONTAL_GRAVITY_MASK = BEFORE | AFTER;
+
+ /**
+ * Apply a gravity constant to an object. This suppose that the layout direction is LTR.
*
* @param gravity The desired placement of the object, as defined by the
* constants in this class.
@@ -119,12 +133,33 @@ public class Gravity
* @param outRect Receives the computed frame of the object in its
* container.
*/
- public static void apply(int gravity, int w, int h, Rect container,
- Rect outRect) {
+ public static void apply(int gravity, int w, int h, Rect container, Rect outRect) {
apply(gravity, w, h, container, 0, 0, outRect);
}
/**
+ * Apply a gravity constant to an object and take care if layout direction is RTL or not.
+ *
+ * @param gravity The desired placement of the object, as defined by the
+ * constants in this class.
+ * @param w The horizontal size of the object.
+ * @param h The vertical size of the object.
+ * @param container The frame of the containing space, in which the object
+ * will be placed. Should be large enough to contain the
+ * width and height of the object.
+ * @param outRect Receives the computed frame of the object in its
+ * container.
+ * @param isRtl Whether the layout is right-to-left.
+ *
+ * @hide
+ */
+ public static void apply(int gravity, int w, int h, Rect container,
+ Rect outRect, boolean isRtl) {
+ int absGravity = getAbsoluteGravity(gravity, isRtl);
+ apply(absGravity, w, h, container, 0, 0, outRect);
+ }
+
+ /**
* Apply a gravity constant to an object.
*
* @param gravity The desired placement of the object, as defined by the
@@ -146,7 +181,7 @@ public class Gravity
* container.
*/
public static void apply(int gravity, int w, int h, Rect container,
- int xAdj, int yAdj, Rect outRect) {
+ int xAdj, int yAdj, Rect outRect) {
switch (gravity&((AXIS_PULL_BEFORE|AXIS_PULL_AFTER)<<AXIS_X_SHIFT)) {
case 0:
outRect.left = container.left
@@ -301,6 +336,54 @@ public class Gravity
* @return true if the supplied gravity has an horizontal pull
*/
public static boolean isHorizontal(int gravity) {
- return gravity > 0 && (gravity & HORIZONTAL_GRAVITY_MASK) != 0;
+ return gravity > 0 && (gravity & RELATIVE_HORIZONTAL_GRAVITY_MASK) != 0;
+ }
+
+ /**
+ * <p>Convert script specific gravity to absolute horizontal value.</p>
+ *
+ * if horizontal direction is LTR, then BEFORE will set LEFT and AFTER will set RIGHT.
+ * if horizontal direction is RTL, then BEFORE will set RIGHT and AFTER will set LEFT.
+ *
+ * If no horizontal direction is found, then just add LEFT to the existing gravity
+ *
+ * @param gravity The gravity to convert to absolute (horizontal) values.
+ * @param isRtl Whether the layout is right-to-left.
+ * @return gravity converted to absolute (horizontal) values.
+ */
+ public static int getAbsoluteGravity(int gravity, boolean isRtl) {
+ int result = gravity;
+ // Set default gravity, if no horizontal gravity is specified
+ if ((result & HORIZONTAL_GRAVITY_MASK) == 0) {
+ result |= Gravity.LEFT;
+ }
+ // If layout is script specific and gravity is horizontal relative (BEFORE or AFTER)
+ if ((result & RELATIVE_HORIZONTAL_DIRECTION) > 0) {
+ if ((result & Gravity.BEFORE) == Gravity.BEFORE) {
+ // Remove the BEFORE bit
+ result &= ~BEFORE;
+ if (isRtl) {
+ // Set the RIGHT bit
+ result |= RIGHT;
+ } else {
+ // Set the LEFT bit
+ result |= LEFT;
+ }
+ } else if ((result & Gravity.AFTER) == Gravity.AFTER) {
+ // Remove the AFTER bit
+ result &= ~AFTER;
+ if (isRtl) {
+ // Set the LEFT bit
+ result |= LEFT;
+ } else {
+ // Set the RIGHT bit
+ result |= RIGHT;
+ }
+ }
+ // Don't need the script specific bit any more, so remove it as we are converting to
+ // absolute values (LEFT or RIGHT)
+ result &= ~RELATIVE_HORIZONTAL_DIRECTION;
+ }
+ return result;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e54046d..017e5e3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -631,7 +631,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
*
* @see android.view.ViewGroup
*/
-public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
+public class View implements Drawable.Callback2, KeyEvent.Callback, AccessibilityEventSource {
private static final boolean DBG = false;
/**
@@ -10238,6 +10238,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
}
+ /**
+ * Check if a given Drawable is in RTL layout direction.
+ *
+ * @param who the recipient of the action
+ */
+ public boolean isLayoutRtl(Drawable who) {
+ return (who == mBGDrawable) && isLayoutRtl();
+ }
+
/**
* If your view subclass is displaying its own Drawable objects, it should
* override this function and return true for any Drawable it is
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9395d5c..a1ddd08 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -77,8 +77,8 @@ public interface WindowManager extends ViewManager {
implements Parcelable {
/**
* X position for this window. With the default gravity it is ignored.
- * When using {@link Gravity#LEFT} or {@link Gravity#RIGHT} it provides
- * an offset from the given edge.
+ * When using {@link Gravity#LEFT} or {@link Gravity#BEFORE} or {@link Gravity#RIGHT} or
+ * {@link Gravity#AFTER} it provides an offset from the given edge.
*/
@ViewDebug.ExportedProperty
public int x;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 0659063..2a1398d 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -115,7 +115,7 @@ public class FrameLayout extends ViewGroup {
}
/**
- * Describes how the foreground is positioned. Defaults to FILL.
+ * Describes how the foreground is positioned. Defaults to BEFORE and TOP.
*
* @param foregroundGravity See {@link android.view.Gravity}
*
@@ -124,8 +124,8 @@ public class FrameLayout extends ViewGroup {
@android.view.RemotableViewMethod
public void setForegroundGravity(int foregroundGravity) {
if (mForegroundGravity != foregroundGravity) {
- if ((foregroundGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- foregroundGravity |= Gravity.LEFT;
+ if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+ foregroundGravity |= Gravity.BEFORE;
}
if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
@@ -364,7 +364,7 @@ public class FrameLayout extends ViewGroup {
gravity = DEFAULT_CHILD_GRAVITY;
}
- final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int horizontalGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
switch (horizontalGravity) {
@@ -436,7 +436,7 @@ public class FrameLayout extends ViewGroup {
}
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
- foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
+ foreground.getIntrinsicHeight(), selfBounds, overlayBounds, isLayoutRtl());
foreground.setBounds(overlayBounds);
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 0383b5c..732cedc 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1408,19 +1408,20 @@ public class GridView extends AbsListView {
int childLeft;
final int childTop = flow ? y : y - h;
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- childLeft = childrenLeft;
- break;
- case Gravity.CENTER_HORIZONTAL:
- childLeft = childrenLeft + ((mColumnWidth - w) / 2);
- break;
- case Gravity.RIGHT:
- childLeft = childrenLeft + mColumnWidth - w;
- break;
- default:
- childLeft = childrenLeft;
- break;
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity,isLayoutRtl());
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ case Gravity.LEFT:
+ childLeft = childrenLeft;
+ break;
+ case Gravity.CENTER_HORIZONTAL:
+ childLeft = childrenLeft + ((mColumnWidth - w) / 2);
+ break;
+ case Gravity.RIGHT:
+ childLeft = childrenLeft + mColumnWidth - w;
+ break;
+ default:
+ childLeft = childrenLeft;
+ break;
}
if (needToMeasure) {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index d8068f9..2a0a2f3 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -187,6 +187,11 @@ public class ImageView extends View {
}
@Override
+ public boolean isLayoutRtl(Drawable dr) {
+ return ((dr == mDrawable) && isLayoutRtl()) || super.isLayoutRtl(dr);
+ }
+
+ @Override
protected boolean onSetAlpha(int alpha) {
if (getBackground() == null) {
int scale = alpha + (alpha >> 7);
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 6f30452..8d449e0 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -110,6 +110,8 @@ public class LinearLayout extends ViewGroup {
@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.BEFORE, to = "BEFORE"),
+ @ViewDebug.IntToString(from = Gravity.AFTER, to = "AFTER"),
@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"),
@@ -117,7 +119,7 @@ public class LinearLayout extends ViewGroup {
@ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
@ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
})
- private int mGravity = Gravity.LEFT | Gravity.TOP;
+ private int mGravity = Gravity.BEFORE | Gravity.TOP;
@ViewDebug.ExportedProperty(category = "measurement")
private int mTotalLength;
@@ -1394,7 +1396,7 @@ public class LinearLayout extends ViewGroup {
final int count = getVirtualChildCount();
final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
- final int minorGravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
switch (majorGravity) {
case Gravity.BOTTOM:
@@ -1428,7 +1430,7 @@ public class LinearLayout extends ViewGroup {
if (gravity < 0) {
gravity = minorGravity;
}
-
+ gravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
childLeft = paddingLeft + ((childSpace - childWidth) / 2)
@@ -1483,7 +1485,7 @@ public class LinearLayout extends ViewGroup {
final int count = getVirtualChildCount();
- final int majorGravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int majorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
final int minorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
final boolean baselineAligned = mBaselineAligned;
@@ -1491,7 +1493,7 @@ public class LinearLayout extends ViewGroup {
final int[] maxAscent = mMaxAscent;
final int[] maxDescent = mMaxDescent;
- switch (majorGravity) {
+ switch (Gravity.getAbsoluteGravity(majorGravity, isLayoutRtl())) {
case Gravity.RIGHT:
// mTotalLength contains the padding already
childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
@@ -1630,8 +1632,8 @@ public class LinearLayout extends ViewGroup {
@android.view.RemotableViewMethod
public void setGravity(int gravity) {
if (mGravity != gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
+ if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+ gravity |= Gravity.BEFORE;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
@@ -1645,9 +1647,9 @@ public class LinearLayout extends ViewGroup {
@android.view.RemotableViewMethod
public void setHorizontalGravity(int horizontalGravity) {
- final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK) | gravity;
+ final int gravity = horizontalGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
+ if ((mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) {
+ mGravity = (mGravity & ~Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity;
requestLayout();
}
}
@@ -1724,6 +1726,8 @@ public class LinearLayout extends ViewGroup {
@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.BEFORE, to = "BEFORE"),
+ @ViewDebug.IntToString(from = Gravity.AFTER, to = "AFTER"),
@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"),
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 30374af..373a177 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -916,6 +916,12 @@ public class ProgressBar extends View {
}
@Override
+ public boolean isLayoutRtl(Drawable who) {
+ return ((who == mProgressDrawable || who == mIndeterminateDrawable) && isLayoutRtl()) ||
+ super.isLayoutRtl(who);
+ }
+
+ @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
updateDrawableBounds(w, h);
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 9069283..acd8539 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -16,32 +16,32 @@
package android.widget;
-import com.android.internal.R;
-
import android.content.Context;
-import android.content.res.TypedArray;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.util.Poolable;
import android.util.Pool;
-import android.util.Pools;
+import android.util.Poolable;
import android.util.PoolableManager;
-import static android.util.Log.d;
+import android.util.Pools;
+import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
+import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.LinkedList;
-import java.util.HashSet;
-import java.util.ArrayList;
+
+import static android.util.Log.d;
/**
* A Layout where the positions of the children can be described in relation to each other or to the
@@ -221,8 +221,8 @@ public class RelativeLayout extends ViewGroup {
@android.view.RemotableViewMethod
public void setGravity(int gravity) {
if (mGravity != gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
+ if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+ gravity |= Gravity.BEFORE;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
@@ -236,9 +236,9 @@ public class RelativeLayout extends ViewGroup {
@android.view.RemotableViewMethod
public void setHorizontalGravity(int horizontalGravity) {
- final int gravity = horizontalGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != gravity) {
- mGravity = (mGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK) | gravity;
+ final int gravity = horizontalGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
+ if ((mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) {
+ mGravity = (mGravity & ~Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity;
requestLayout();
}
}
@@ -339,7 +339,7 @@ public class RelativeLayout extends ViewGroup {
mHasBaselineAlignedChild = false;
View ignore = null;
- int gravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
final boolean horizontalGravity = gravity != Gravity.LEFT && gravity != 0;
gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;
@@ -494,7 +494,8 @@ public class RelativeLayout extends ViewGroup {
height - mPaddingBottom);
final Rect contentBounds = mContentBounds;
- Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds);
+ Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,
+ isLayoutRtl());
final int horizontalOffset = contentBounds.left - left;
final int verticalOffset = contentBounds.top - top;
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index b612004..5f20c85 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -224,7 +224,8 @@ public class TableRow extends LinearLayout {
final int childWidth = child.getMeasuredWidth();
lp.mOffset[LayoutParams.LOCATION_NEXT] = columnWidth - childWidth;
- switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
// don't offset on X axis
break;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 67b99da..a73a6cf 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2093,8 +2093,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_gravity
*/
public void setGravity(int gravity) {
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
- gravity |= Gravity.LEFT;
+ if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
+ gravity |= Gravity.BEFORE;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
gravity |= Gravity.TOP;
@@ -2102,8 +2102,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean newLayout = false;
- if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) !=
- (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK)) {
+ if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) !=
+ (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK)) {
newLayout = true;
}
@@ -4142,6 +4142,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
@Override
+ public boolean isLayoutRtl(Drawable who) {
+ if (who == null) return false;
+ final TextView.Drawables drawables = mDrawables;
+ if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight ||
+ who == drawables.mDrawableTop || who == drawables.mDrawableBottom) {
+ return isLayoutRtl();
+ }
+ return super.isLayoutRtl(who);
+ }
+
+ @Override
protected boolean onSetAlpha(int alpha) {
// Alpha is supported if and only if the drawing can be done in one pass.
// TODO text with spans with a background color currently do not respect this alpha.
@@ -4380,9 +4391,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
}
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
if (mEllipsize == TextUtils.TruncateAt.MARQUEE) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
- (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
+ (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
getCompoundPaddingLeft() - getCompoundPaddingRight()), 0.0f);
}
@@ -5528,7 +5540,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
Layout.Alignment alignment;
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
alignment = Layout.Alignment.ALIGN_CENTER;
break;
@@ -7563,7 +7576,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return 0.0f;
}
} else if (getLineCount() == 1) {
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
return 0.0f;
case Gravity.RIGHT:
@@ -7586,7 +7600,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final Marquee marquee = mMarquee;
return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
} else if (getLineCount() == 1) {
- switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, isLayoutRtl());
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
getCompoundPaddingRight();
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index afa8a01..c337a5d 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -282,7 +282,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie
getLineBounds(0, tmpRect);
mPositionIconAvailable.set(0, 0, getWidth(), tmpRect.top);
Gravity.apply(Gravity.CENTER_VERTICAL | Gravity.LEFT, mIcon.getIntrinsicWidth(), mIcon
- .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput);
+ .getIntrinsicHeight(), mPositionIconAvailable, mPositionIconOutput, isLayoutRtl());
mIcon.setBounds(mPositionIconOutput);
}
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
index aee7b76..e113dd8 100644
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -86,7 +86,8 @@ public class TextProgressBar extends RelativeLayout implements OnChronometerTick
// Check if Chronometer should move with with ProgressBar
mChronometerFollow = (params.width == ViewGroup.LayoutParams.WRAP_CONTENT);
- mChronometerGravity = (mChronometer.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK);
+ mChronometerGravity = (mChronometer.getGravity() &
+ Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK);
} else if (childId == PROGRESSBAR_ID && child instanceof ProgressBar) {
mProgressBar = (ProgressBar) child;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f854e93..b82a2d2 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1128,6 +1128,10 @@
The clip will be based on the horizontal gravity: a left gravity will clip the right
edge, a right gravity will clip the left edge, and neither will clip both edges. -->
<flag name="clip_horizontal" value="0x08" />
+ <!-- Push object to the beginning of its container, not changing its size. -->
+ <flag name="before" value="0x00800003" />
+ <!-- Push object to the end of its container, not changing its size. -->
+ <flag name="after" value="0x00800005" />
</attr>
<!-- Controls whether links such as urls and email addresses are
@@ -1184,6 +1188,10 @@
The clip will be based on the horizontal gravity: a left gravity will clip the right
edge, a right gravity will clip the left edge, and neither will clip both edges. -->
<flag name="clip_horizontal" value="0x08" />
+ <!-- Push object to the beginning of its container, not changing its size. -->
+ <flag name="before" value="0x00800003" />
+ <!-- Push object to the end of its container, not changing its size. -->
+ <flag name="after" value="0x00800005" />
</attr>
<!-- Standard orientation constant. -->
diff --git a/core/tests/coretests/src/android/view/GravityTest.java b/core/tests/coretests/src/android/view/GravityTest.java
new file mode 100644
index 0000000..010127f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/GravityTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class GravityTest extends AndroidTestCase {
+
+ @SmallTest
+ public void testGetAbsoluteGravity() throws Exception {
+ assertOneGravity(Gravity.LEFT, Gravity.LEFT, false);
+ assertOneGravity(Gravity.LEFT, Gravity.LEFT, true);
+
+ assertOneGravity(Gravity.RIGHT, Gravity.RIGHT, false);
+ assertOneGravity(Gravity.RIGHT, Gravity.RIGHT, true);
+
+ assertOneGravity(Gravity.TOP|Gravity.LEFT, Gravity.TOP, false);
+ assertOneGravity(Gravity.TOP|Gravity.LEFT, Gravity.TOP, true);
+
+ assertOneGravity(Gravity.BOTTOM|Gravity.LEFT, Gravity.BOTTOM, false);
+ assertOneGravity(Gravity.BOTTOM|Gravity.LEFT, Gravity.BOTTOM, true);
+
+ assertOneGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT, Gravity.CENTER_VERTICAL, false);
+ assertOneGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT, Gravity.CENTER_VERTICAL, true);
+
+ assertOneGravity(Gravity.CENTER_HORIZONTAL, Gravity.CENTER_HORIZONTAL, false);
+ assertOneGravity(Gravity.CENTER_HORIZONTAL, Gravity.CENTER_HORIZONTAL, true);
+
+ assertOneGravity(Gravity.CENTER, Gravity.CENTER, false);
+ assertOneGravity(Gravity.CENTER, Gravity.CENTER, true);
+
+ assertOneGravity(Gravity.FILL_VERTICAL|Gravity.LEFT, Gravity.FILL_VERTICAL, false);
+ assertOneGravity(Gravity.FILL_VERTICAL|Gravity.LEFT, Gravity.FILL_VERTICAL, true);
+
+ assertOneGravity(Gravity.FILL_HORIZONTAL, Gravity.FILL_HORIZONTAL, false);
+ assertOneGravity(Gravity.FILL_HORIZONTAL, Gravity.FILL_HORIZONTAL, true);
+
+ assertOneGravity(Gravity.FILL, Gravity.FILL, false);
+ assertOneGravity(Gravity.FILL, Gravity.FILL, true);
+
+ assertOneGravity(Gravity.CLIP_HORIZONTAL|Gravity.LEFT, Gravity.CLIP_HORIZONTAL, false);
+ assertOneGravity(Gravity.CLIP_HORIZONTAL|Gravity.LEFT, Gravity.CLIP_HORIZONTAL, true);
+
+ assertOneGravity(Gravity.CLIP_VERTICAL|Gravity.LEFT, Gravity.CLIP_VERTICAL, false);
+ assertOneGravity(Gravity.CLIP_VERTICAL|Gravity.LEFT, Gravity.CLIP_VERTICAL, true);
+
+ assertOneGravity(Gravity.LEFT, Gravity.BEFORE, false);
+ assertOneGravity(Gravity.RIGHT, Gravity.BEFORE, true);
+
+ assertOneGravity(Gravity.RIGHT, Gravity.AFTER, false);
+ assertOneGravity(Gravity.LEFT, Gravity.AFTER, true);
+ }
+
+ private void assertOneGravity(int expected, int initial, boolean isRtl) {
+ assertEquals(expected, Gravity.getAbsoluteGravity(initial, isRtl));
+ }
+}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index c9c9fd7..311f024 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -387,7 +387,7 @@ public class BitmapDrawable extends Drawable {
if (shader == null) {
if (mApplyGravity) {
Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
- getBounds(), mDstRect);
+ getBounds(), mDstRect, isLayoutRtlSelf());
mApplyGravity = false;
}
canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint);
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index b333e01..83020aa 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -209,7 +209,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
if ((mClipState.mOrientation & VERTICAL) != 0) {
h -= (h - ih) * (10000 - level) / 10000;
}
- Gravity.apply(mClipState.mGravity, w, h, bounds, r);
+ Gravity.apply(mClipState.mGravity, w, h, bounds, r, isLayoutRtlSelf());
if (w > 0 && h > 0) {
canvas.save();
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 159f371e..8994efc 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -288,6 +288,18 @@ public abstract class Drawable {
}
/**
+ * Implement this interface if you want to create an drawable that is RTL aware
+ */
+ public static interface Callback2 extends Callback {
+ /**
+ * A Drawable can call this to know whether the <var>who</var> is in RTL layout direction.
+ *
+ * @param who The drawable being unscheduled.
+ */
+ public boolean isLayoutRtl(Drawable who);
+ }
+
+ /**
* Bind a {@link Callback} object to this Drawable. Required for clients
* that want to support animated drawables.
*
@@ -364,6 +376,18 @@ public abstract class Drawable {
}
/**
+ * Use the current {@link android.graphics.drawable.Drawable.Callback2} implementation to know
+ * if this Drawable is having a layout in RTL direction.
+ */
+ public boolean isLayoutRtlSelf() {
+ final Callback callback = getCallback();
+ if (callback == null || !(callback instanceof Callback2)) {
+ return false;
+ }
+ return ((Callback2) callback).isLayoutRtl(this);
+ }
+
+ /**
* Specify an alpha value for the drawable. 0 means fully transparent, and
* 255 means fully opaque.
*/
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index a7ed0d0..cbe1f2d 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -221,7 +221,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
}
- Gravity.apply(mScaleState.mGravity, w, h, bounds, r);
+ Gravity.apply(mScaleState.mGravity, w, h, bounds, r, isLayoutRtlSelf());
if (w > 0 && h > 0) {
mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);