summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2013-06-24 19:22:25 -0700
committerFabrice Di Meglio <fdimeglio@google.com>2013-08-01 15:15:10 -0700
commit3f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aa (patch)
tree666fee2554ad0f795380960d425606804e8b7ede
parent851761574a775c6447ab2393d1ba42568ba08c1b (diff)
downloadframeworks_base-3f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aa.zip
frameworks_base-3f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aa.tar.gz
frameworks_base-3f5a90b2fbba2a83a8a2c5babd5d466a5e0ad2aa.tar.bz2
Add automatic Drawable mirroring capability when in RTL layout direction
- default value is "no mirroring" - introduce android:autoMirrored as a new attribute for Drawable, BitmapDrawable, LayerDrawable, StateListDrawable and NinePatchDrawable - setting android:autoMirrored="true" means that the drawable will be mirrored when the layout direction is RTL (right-to-left) - also fix an issue with ImageView drawable layout direction not updated correctly when RTL properties were changed See bug #7034321 Need Drawable RTL support Change-Id: If595ee5106c786f38e786d3a032e182f784a9d97
-rw-r--r--api/current.txt11
-rw-r--r--core/java/android/util/LayoutDirection.java44
-rw-r--r--core/java/android/view/View.java9
-rw-r--r--core/java/android/widget/ImageView.java9
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/res/res/values/attrs.xml16
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java70
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java19
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java17
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java22
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java41
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java3
13 files changed, 254 insertions, 11 deletions
diff --git a/api/current.txt b/api/current.txt
index ce55489..6c41433 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -291,6 +291,7 @@ package android {
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
field public static final int autoLink = 16842928; // 0x10100b0
+ field public static final int autoMirrored = 16843752; // 0x10103e8
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -9891,6 +9892,7 @@ package android.graphics.drawable {
method public android.graphics.Shader.TileMode getTileModeY();
method public boolean hasAntiAlias();
method public boolean hasMipMap();
+ method public final boolean isAutoMirrored();
method public void setAlpha(int);
method public void setAntiAlias(boolean);
method public void setColorFilter(android.graphics.ColorFilter);
@@ -9957,6 +9959,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 isAutoMirrored();
method public boolean isStateful();
method public final boolean isVisible();
method public void jumpToCurrentState();
@@ -9967,6 +9970,7 @@ package android.graphics.drawable {
method public static int resolveOpacity(int, int);
method public void scheduleSelf(java.lang.Runnable, long);
method public abstract void setAlpha(int);
+ method public void setAutoMirrored(boolean);
method public void setBounds(int, int, int, int);
method public void setBounds(android.graphics.Rect);
method public final void setCallback(android.graphics.drawable.Drawable.Callback);
@@ -25138,6 +25142,13 @@ package android.util {
method public android.util.JsonWriter value(java.lang.Number) throws java.io.IOException;
}
+ public abstract interface LayoutDirection {
+ field public static final int INHERIT = 2; // 0x2
+ field public static final int LOCALE = 3; // 0x3
+ field public static final int LTR = 0; // 0x0
+ field public static final int RTL = 1; // 0x1
+ }
+
public final class Log {
method public static int d(java.lang.String, java.lang.String);
method public static int d(java.lang.String, java.lang.String, java.lang.Throwable);
diff --git a/core/java/android/util/LayoutDirection.java b/core/java/android/util/LayoutDirection.java
new file mode 100644
index 0000000..e37d2f2
--- /dev/null
+++ b/core/java/android/util/LayoutDirection.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 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.util;
+
+/**
+ * An interface for defining layout directions. A layout direction can be left-to-right (LTR)
+ * or right-to-left (RTL). It can also be inherited (from a parent) or deduced from the default
+ * language script of a locale.
+ */
+public interface LayoutDirection {
+ /**
+ * Horizontal layout direction is from Left to Right.
+ */
+ public static final int LTR = 0;
+
+ /**
+ * Horizontal layout direction is from Right to Left.
+ */
+ public static final int RTL = 1;
+
+ /**
+ * Horizontal layout direction is inherited.
+ */
+ public static final int INHERIT = 2;
+
+ /**
+ * Horizontal layout direction is deduced from the default language script for the locale.
+ */
+ public static final int LOCALE = 3;
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 299c4a2..7624b56 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -51,6 +51,7 @@ import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatProperty;
+import android.util.LayoutDirection;
import android.util.Log;
import android.util.LongSparseLongArray;
import android.util.Pools.SynchronizedPool;
@@ -1801,25 +1802,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Horizontal layout direction of this view is from Left to Right.
* Use with {@link #setLayoutDirection}.
*/
- public static final int LAYOUT_DIRECTION_LTR = 0;
+ public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
/**
* Horizontal layout direction of this view is from Right to Left.
* Use with {@link #setLayoutDirection}.
*/
- public static final int LAYOUT_DIRECTION_RTL = 1;
+ public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
/**
* Horizontal layout direction of this view is inherited from its parent.
* Use with {@link #setLayoutDirection}.
*/
- public static final int LAYOUT_DIRECTION_INHERIT = 2;
+ public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
/**
* Horizontal layout direction of this view is from deduced from the default language
* script for the locale. Use with {@link #setLayoutDirection}.
*/
- public static final int LAYOUT_DIRECTION_LOCALE = 3;
+ public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
/**
* Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 33fd8ce..3e53b91 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -732,6 +732,15 @@ public class ImageView extends View {
}
}
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+
+ if (mDrawable != null) {
+ mDrawable.setLayoutDirection(layoutDirection);
+ }
+ }
+
private static final Matrix.ScaleToFit[] sS2FArray = {
Matrix.ScaleToFit.FILL,
Matrix.ScaleToFit.START,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 816bb18..3181164 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2042,6 +2042,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
dr.mDrawableRightInitial = right;
}
+ resetResolvedDrawables();
+ resolveDrawables();
invalidate();
requestLayout();
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2096f66..67a32fd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3905,6 +3905,10 @@
value is false. See
{@link android.graphics.drawable.Drawable#setVisible}. -->
<attr name="visible" format="boolean" />
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). See
+ {@link android.graphics.drawable.Drawable#setAutoMirrored}. -->
+ <attr name="autoMirrored" format="boolean" />
</declare-styleable>
<!-- Drawable used to render several states. Each state is represented by
@@ -3932,6 +3936,9 @@
<attr name="enterFadeDuration" format="integer" />
<!-- Amount of time (in milliseconds) to fade out an old state drawable. -->
<attr name="exitFadeDuration" format="integer" />
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). -->
+ <attr name="autoMirrored"/>
</declare-styleable>
<!-- Drawable used to render several animated frames. -->
@@ -4083,6 +4090,9 @@
<!-- The layer has translucent pixels. -->
<enum name="translucent" value="-3" />
</attr>
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). -->
+ <attr name="autoMirrored" />
</declare-styleable>
<!-- Describes an item (or child) of a LayerDrawable. -->
@@ -4172,6 +4182,9 @@
{@link android.graphics.Bitmap#setHasMipMap(boolean)} for more information.
Default value is false. -->
<attr name="mipMap" format="boolean" />
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). -->
+ <attr name="autoMirrored" />
</declare-styleable>
<!-- Drawable used to draw 9-patches. -->
@@ -4182,6 +4195,9 @@
same pixel configuration as the screen (for instance: a ARGB 8888 bitmap with
an RGB 565 screen). -->
<attr name="dither" />
+ <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+ RTL (right-to-left). -->
+ <attr name="autoMirrored" />
</declare-styleable>
<!-- Drawable used to draw a single color. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0eaab65..80c9184 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2071,4 +2071,6 @@
<public type="attr" name="category" />
<public type="attr" name="isAsciiCapable" />
<public type="attr" name="customRoots" />
+ <public type="attr" name="autoMirrored" />
+
</resources>
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 8689261..5ceab36 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -23,12 +23,14 @@ import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.LayoutDirection;
import android.view.Gravity;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -72,7 +74,10 @@ public class BitmapDrawable extends Drawable {
// These are scaled to match the target density.
private int mBitmapWidth;
private int mBitmapHeight;
-
+
+ // Mirroring matrix for using with Shaders
+ private Matrix mMirrorMatrix;
+
/**
* Create an empty drawable, not dealing with density.
* @deprecated Use {@link #BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap)}
@@ -399,14 +404,51 @@ public class BitmapDrawable extends Drawable {
}
@Override
+ public void setAutoMirrored(boolean mirrored) {
+ if (mBitmapState.mAutoMirrored != mirrored) {
+ mBitmapState.mAutoMirrored = mirrored;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public final boolean isAutoMirrored() {
+ return mBitmapState.mAutoMirrored;
+ }
+
+ @Override
public int getChangingConfigurations() {
return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations;
}
-
+
+ private boolean needMirroring() {
+ return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
+ }
+
+ private void updateMirrorMatrix(float dx) {
+ if (mMirrorMatrix == null) {
+ mMirrorMatrix = new Matrix();
+ }
+ mMirrorMatrix.setTranslate(dx, 0);
+ mMirrorMatrix.preScale(-1.0f, 1.0f);
+ }
+
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mApplyGravity = true;
+ Shader shader = mBitmapState.mPaint.getShader();
+ if (shader != null) {
+ if (needMirroring()) {
+ updateMirrorMatrix(bounds.right - bounds.left);
+ shader.setLocalMatrix(mMirrorMatrix);
+ } else {
+ if (mMirrorMatrix != null) {
+ mMirrorMatrix = null;
+ shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
+ }
+ }
+ }
}
@Override
@@ -430,6 +472,7 @@ public class BitmapDrawable extends Drawable {
}
Shader shader = state.mPaint.getShader();
+ final boolean needMirroring = needMirroring();
if (shader == null) {
if (mApplyGravity) {
final int layoutDirection = getLayoutDirection();
@@ -437,12 +480,31 @@ public class BitmapDrawable extends Drawable {
getBounds(), mDstRect, layoutDirection);
mApplyGravity = false;
}
+ if (needMirroring) {
+ canvas.save();
+ // Mirror the bitmap
+ canvas.translate(mDstRect.right - mDstRect.left, 0);
+ canvas.scale(-1.0f, 1.0f);
+ }
canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint);
+ if (needMirroring) {
+ canvas.restore();
+ }
} else {
if (mApplyGravity) {
copyBounds(mDstRect);
mApplyGravity = false;
}
+ if (needMirroring) {
+ // Mirror the bitmap
+ updateMirrorMatrix(mDstRect.right - mDstRect.left);
+ shader.setLocalMatrix(mMirrorMatrix);
+ } else {
+ if (mMirrorMatrix != null) {
+ mMirrorMatrix = null;
+ shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
+ }
+ }
canvas.drawRect(mDstRect, state.mPaint);
}
}
@@ -505,6 +567,8 @@ public class BitmapDrawable extends Drawable {
setTargetDensity(r.getDisplayMetrics());
setMipMap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_mipMap,
bitmap.hasMipMap()));
+ setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_autoMirrored,
+ false));
final Paint paint = mBitmapState.mPaint;
paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
@@ -567,6 +631,7 @@ public class BitmapDrawable extends Drawable {
Shader.TileMode mTileModeY = null;
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
boolean mRebuildShader;
+ boolean mAutoMirrored;
BitmapState(Bitmap bitmap) {
mBitmap = bitmap;
@@ -581,6 +646,7 @@ public class BitmapDrawable extends Drawable {
mTargetDensity = bitmapState.mTargetDensity;
mPaint = new Paint(bitmapState.mPaint);
mRebuildShader = bitmapState.mRebuildShader;
+ mAutoMirrored = bitmapState.mAutoMirrored;
}
@Override
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index c8fce9e..8135716 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -572,6 +572,25 @@ public abstract class Drawable {
}
/**
+ * Set whether this Drawable is automatically mirrored when its layout direction is RTL
+ * (right-to left). See {@link android.util.LayoutDirection}.
+ *
+ * @param mirrored Set to true if the Drawable should be mirrored, false if not.
+ */
+ public void setAutoMirrored(boolean mirrored) {
+ }
+
+ /**
+ * Tells if this Drawable will be automatically mirrored when its layout direction is RTL
+ * right-to-left. See {@link android.util.LayoutDirection}.
+ *
+ * @return boolean Returns true if this Drawable will be automatically mirrored.
+ */
+ public boolean isAutoMirrored() {
+ return false;
+ }
+
+ /**
* Return the opacity/transparency of this Drawable. The returned value is
* one of the abstract format constants in
* {@link android.graphics.PixelFormat}:
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index f9cd4e2..e350e8d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -173,6 +173,19 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
}
@Override
+ public void setAutoMirrored(boolean mirrored) {
+ mDrawableContainerState.mAutoMirrored = mirrored;
+ if (mCurrDrawable != null) {
+ mCurrDrawable.mutate().setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+ }
+ }
+
+ @Override
+ public boolean isAutoMirrored() {
+ return mDrawableContainerState.mAutoMirrored;
+ }
+
+ @Override
public void jumpToCurrentState() {
boolean changed = false;
if (mLastDrawable != null) {
@@ -334,6 +347,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
d.setLevel(getLevel());
d.setBounds(getBounds());
d.setLayoutDirection(getLayoutDirection());
+ d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
}
} else {
mCurrDrawable = null;
@@ -471,6 +485,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
int mEnterFadeDuration;
int mExitFadeDuration;
+ boolean mAutoMirrored;
+
DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
mOwner = owner;
@@ -490,6 +506,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mLayoutDirection = orig.mLayoutDirection;
mEnterFadeDuration = orig.mEnterFadeDuration;
mExitFadeDuration = orig.mExitFadeDuration;
+ mAutoMirrored = orig.mAutoMirrored;
// Cloning the following values may require creating futures.
mConstantPadding = orig.getConstantPadding();
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 206897b..81cc11b 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -119,6 +119,9 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
mOpacityOverride = a.getInt(com.android.internal.R.styleable.LayerDrawable_opacity,
PixelFormat.UNKNOWN);
+ setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.LayerDrawable_autoMirrored,
+ false));
+
a.recycle();
final int innerDepth = parser.getDepth() + 1;
@@ -200,6 +203,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
st.mChildren[i] = childDrawable;
childDrawable.mId = id;
childDrawable.mDrawable = layer;
+ childDrawable.mDrawable.setAutoMirrored(isAutoMirrored());
childDrawable.mInsetL = left;
childDrawable.mInsetT = top;
childDrawable.mInsetR = right;
@@ -448,6 +452,21 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public void setAutoMirrored(boolean mirrored) {
+ mLayerState.mAutoMirrored = mirrored;
+ final ChildDrawable[] array = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i=0; i<N; i++) {
+ array[i].mDrawable.setAutoMirrored(mirrored);
+ }
+ }
+
+ @Override
+ public boolean isAutoMirrored() {
+ return mLayerState.mAutoMirrored;
+ }
+
+ @Override
public boolean isStateful() {
return mLayerState.isStateful();
}
@@ -630,6 +649,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
private boolean mCheckedConstantState;
private boolean mCanConstantState;
+ private boolean mAutoMirrored;
+
LayerState(LayerState orig, LayerDrawable owner, Resources res) {
if (orig != null) {
final ChildDrawable[] origChildDrawable = orig.mChildren;
@@ -663,6 +684,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
mHaveStateful = orig.mHaveStateful;
mStateful = orig.mStateful;
mCheckedConstantState = mCanConstantState = true;
+ mAutoMirrored = orig.mAutoMirrored;
} else {
mNum = 0;
mChildren = null;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 86e4bad..720494b 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -30,6 +30,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.LayoutDirection;
import android.util.TypedValue;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -132,6 +133,7 @@ public class NinePatchDrawable extends Drawable {
// lazy allocation of a paint
setDither(state.mDither);
}
+ setAutoMirrored(state.mAutoMirrored);
if (mNinePatch != null) {
computeBitmapSize();
}
@@ -216,7 +218,19 @@ public class NinePatchDrawable extends Drawable {
@Override
public void draw(Canvas canvas) {
- mNinePatch.draw(canvas, getBounds(), mPaint);
+ final Rect bounds = getBounds();
+ final boolean needMirroring = isAutoMirrored() &&
+ getLayoutDirection() == LayoutDirection.RTL;
+ if (needMirroring) {
+ canvas.save();
+ // Mirror the 9patch
+ canvas.translate(bounds.right - bounds.left, 0);
+ canvas.scale(-1.0f, 1.0f);
+ }
+ mNinePatch.draw(canvas, bounds, mPaint);
+ if (needMirroring) {
+ canvas.restore();
+ }
}
@Override
@@ -279,6 +293,16 @@ public class NinePatchDrawable extends Drawable {
}
@Override
+ public void setAutoMirrored(boolean mirrored) {
+ mNinePatchState.mAutoMirrored = mirrored;
+ }
+
+ @Override
+ public boolean isAutoMirrored() {
+ return mNinePatchState.mAutoMirrored;
+ }
+
+ @Override
public void setFilterBitmap(boolean filter) {
getPaint().setFilterBitmap(filter);
invalidateSelf();
@@ -328,8 +352,11 @@ public class NinePatchDrawable extends Drawable {
": <nine-patch> requires a valid 9-patch source image");
}
+ final boolean automirrored = a.getBoolean(
+ com.android.internal.R.styleable.NinePatchDrawable_autoMirrored, false);
+
setNinePatchState(new NinePatchState(new NinePatch(bitmap, bitmap.getNinePatchChunk()),
- padding, opticalInsets, dither), r);
+ padding, opticalInsets, dither, automirrored), r);
mNinePatchState.mTargetDensity = mTargetDensity;
a.recycle();
@@ -407,20 +434,23 @@ public class NinePatchDrawable extends Drawable {
final boolean mDither;
int mChangingConfigurations;
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+ boolean mAutoMirrored;
NinePatchState(NinePatch ninePatch, Rect padding) {
- this(ninePatch, padding, new Rect(), DEFAULT_DITHER);
+ this(ninePatch, padding, new Rect(), DEFAULT_DITHER, false);
}
NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets) {
- this(ninePatch, padding, opticalInsets, DEFAULT_DITHER);
+ this(ninePatch, padding, opticalInsets, DEFAULT_DITHER, false);
}
- NinePatchState(NinePatch ninePatch, Rect rect, Rect opticalInsets, boolean dither) {
+ NinePatchState(NinePatch ninePatch, Rect rect, Rect opticalInsets, boolean dither,
+ boolean autoMirror) {
mNinePatch = ninePatch;
mPadding = rect;
mOpticalInsets = Insets.of(opticalInsets);
mDither = dither;
+ mAutoMirrored = autoMirror;
}
// Copy constructor
@@ -434,6 +464,7 @@ public class NinePatchDrawable extends Drawable {
mDither = state.mDither;
mChangingConfigurations = state.mChangingConfigurations;
mTargetDensity = state.mTargetDensity;
+ mAutoMirrored = state.mAutoMirrored;
}
@Override
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index e3c7bc5..48d66b7 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -132,6 +132,9 @@ public class StateListDrawable extends DrawableContainer {
setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither,
DEFAULT_DITHER));
+ setAutoMirrored(a.getBoolean(
+ com.android.internal.R.styleable.StateListDrawable_autoMirrored, false));
+
a.recycle();
int type;