* commit '97c88368e0036665507c8cd84c71d26953784c85': Fix layout rendering for RTL locales
This commit is contained in:
@ -7,5 +7,6 @@
|
||||
<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
|
||||
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
|
||||
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
|
||||
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -22,6 +22,7 @@ LOCAL_JAVA_RESOURCE_DIRS := resources
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := \
|
||||
kxml2-2.3.0 \
|
||||
icu4j \
|
||||
layoutlib_api-prebuilt \
|
||||
tools-common-prebuilt
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 904 B |
Binary file not shown.
After Width: | Height: | Size: 533 B |
Binary file not shown.
After Width: | Height: | Size: 617 B |
Binary file not shown.
After Width: | Height: | Size: 423 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 552 B |
@ -35,6 +35,7 @@ import com.android.resources.ResourceType;
|
||||
import com.android.tools.layoutlib.create.MethodAdapter;
|
||||
import com.android.tools.layoutlib.create.OverrideMethod;
|
||||
import com.android.util.Pair;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
import android.content.res.BridgeAssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
@ -64,6 +65,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
|
||||
private static final String ICU_LOCALE_DIRECTION_RTL = "right-to-left";
|
||||
|
||||
public static class StaticMethodNotImplementedException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -211,7 +214,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
Capability.ANIMATED_VIEW_MANIPULATION,
|
||||
Capability.ADAPTER_BINDING,
|
||||
Capability.EXTENDED_VIEWINFO,
|
||||
Capability.FIXED_SCALABLE_NINE_PATCH);
|
||||
Capability.FIXED_SCALABLE_NINE_PATCH,
|
||||
Capability.RTL);
|
||||
|
||||
|
||||
BridgeAssetManager.initSystem();
|
||||
@ -411,6 +415,20 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
throw new IllegalArgumentException("viewObject is not a View");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRtl(String locale) {
|
||||
return isLocaleRtl(locale);
|
||||
}
|
||||
|
||||
public static boolean isLocaleRtl(String locale) {
|
||||
if (locale == null) {
|
||||
locale = "";
|
||||
}
|
||||
ULocale uLocale = new ULocale(locale);
|
||||
return uLocale.getCharacterOrientation().equals(ICU_LOCALE_DIRECTION_RTL) ?
|
||||
true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lock for the bridge
|
||||
*/
|
||||
|
@ -132,7 +132,8 @@ public final class BridgeContext extends Context {
|
||||
RenderResources renderResources,
|
||||
IProjectCallback projectCallback,
|
||||
Configuration config,
|
||||
int targetSdkVersion) {
|
||||
int targetSdkVersion,
|
||||
boolean hasRtlSupport) {
|
||||
mProjectKey = projectKey;
|
||||
mMetrics = metrics;
|
||||
mProjectCallback = projectCallback;
|
||||
@ -142,6 +143,9 @@ public final class BridgeContext extends Context {
|
||||
|
||||
mApplicationInfo = new ApplicationInfo();
|
||||
mApplicationInfo.targetSdkVersion = targetSdkVersion;
|
||||
if (hasRtlSupport) {
|
||||
mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL;
|
||||
}
|
||||
|
||||
mWindowManager = new WindowManagerImpl(mMetrics);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
import com.android.layoutlib.bridge.impl.ParserFactory;
|
||||
import com.android.layoutlib.bridge.impl.ResourceHelper;
|
||||
import com.android.resources.Density;
|
||||
import com.android.resources.LayoutDirection;
|
||||
import com.android.resources.ResourceType;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@ -86,38 +87,53 @@ abstract class CustomBar extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut,
|
||||
boolean tryOtherDensities) {
|
||||
private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction,
|
||||
String[] pathOut, boolean tryOtherDensities) {
|
||||
// current density
|
||||
Density density = densityInOut[0];
|
||||
|
||||
// bitmap url relative to this class
|
||||
if (direction != null) {
|
||||
pathOut[0] = "/bars/" + direction.getResourceValue() + "-" + density.getResourceValue()
|
||||
+ "/" + iconName;
|
||||
} else {
|
||||
pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
|
||||
}
|
||||
|
||||
InputStream stream = getClass().getResourceAsStream(pathOut[0]);
|
||||
if (stream == null && tryOtherDensities) {
|
||||
for (Density d : Density.values()) {
|
||||
if (d != density) {
|
||||
densityInOut[0] = d;
|
||||
stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/);
|
||||
stream = getIcon(iconName, densityInOut, direction, pathOut,
|
||||
false /*tryOtherDensities*/);
|
||||
if (stream != null) {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
// couldn't find resource with direction qualifier. try without.
|
||||
if (direction != null) {
|
||||
return getIcon(iconName, densityInOut, null, pathOut, true);
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
protected void loadIcon(int index, String iconName, Density density) {
|
||||
loadIcon(index, iconName, density, false);
|
||||
}
|
||||
|
||||
protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
|
||||
View child = getChildAt(index);
|
||||
if (child instanceof ImageView) {
|
||||
ImageView imageView = (ImageView) child;
|
||||
|
||||
String[] pathOut = new String[1];
|
||||
Density[] densityInOut = new Density[] { density };
|
||||
InputStream stream = getIcon(iconName, densityInOut, pathOut,
|
||||
LayoutDirection dir = isRtl ? LayoutDirection.RTL : LayoutDirection.LTR;
|
||||
InputStream stream = getIcon(iconName, densityInOut, dir, pathOut,
|
||||
true /*tryOtherDensities*/);
|
||||
density = densityInOut[0];
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.android.layoutlib.bridge.bars;
|
||||
|
||||
import com.android.resources.Density;
|
||||
import com.android.layoutlib.bridge.Bridge;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@ -26,7 +27,8 @@ import android.widget.TextView;
|
||||
|
||||
public class NavigationBar extends CustomBar {
|
||||
|
||||
public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException {
|
||||
public NavigationBar(Context context, Density density, int orientation, boolean isRtl,
|
||||
boolean rtlEnabled) throws XmlPullParserException {
|
||||
super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
|
||||
|
||||
setBackgroundColor(0xFF000000);
|
||||
@ -37,14 +39,15 @@ public class NavigationBar extends CustomBar {
|
||||
// 0 is a spacer.
|
||||
int back = 1;
|
||||
int recent = 3;
|
||||
if (orientation == LinearLayout.VERTICAL) {
|
||||
if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) {
|
||||
// If RTL is enabled, then layoutlib mirrors the layout for us.
|
||||
back = 3;
|
||||
recent = 1;
|
||||
}
|
||||
|
||||
loadIcon(back, "ic_sysbar_back.png", density);
|
||||
loadIcon(2, "ic_sysbar_home.png", density);
|
||||
loadIcon(recent, "ic_sysbar_recent.png", density);
|
||||
loadIcon(back, "ic_sysbar_back.png", density, isRtl);
|
||||
loadIcon(2, "ic_sysbar_home.png", density, isRtl);
|
||||
loadIcon(recent, "ic_sysbar_recent.png", density, isRtl);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +30,10 @@ import android.widget.TextView;
|
||||
|
||||
public class StatusBar extends CustomBar {
|
||||
|
||||
public StatusBar(Context context, Density density) throws XmlPullParserException {
|
||||
public StatusBar(Context context, Density density, int direction, boolean RtlEnabled)
|
||||
throws XmlPullParserException {
|
||||
// FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
|
||||
|
||||
super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
|
||||
|
||||
// FIXME: use FILL_H?
|
||||
|
@ -121,7 +121,8 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
|
||||
|
||||
// build the context
|
||||
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
|
||||
mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
|
||||
mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
|
||||
mParams.isRtlSupported());
|
||||
|
||||
setUp();
|
||||
|
||||
|
@ -224,13 +224,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
SessionParams params = getParams();
|
||||
HardwareConfig hardwareConfig = params.getHardwareConfig();
|
||||
BridgeContext context = getContext();
|
||||
|
||||
boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
|
||||
int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
|
||||
|
||||
// the view group that receives the window background.
|
||||
ViewGroup backgroundView = null;
|
||||
|
||||
if (mWindowIsFloating || params.isForceNoDecor()) {
|
||||
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
|
||||
mViewRoot.setLayoutDirection(direction);
|
||||
} else {
|
||||
if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
|
||||
/*
|
||||
@ -252,12 +254,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
the bottom
|
||||
*/
|
||||
LinearLayout topLayout = new LinearLayout(context);
|
||||
topLayout.setLayoutDirection(direction);
|
||||
mViewRoot = topLayout;
|
||||
topLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
try {
|
||||
NavigationBar navigationBar = new NavigationBar(context,
|
||||
hardwareConfig.getDensity(), LinearLayout.VERTICAL);
|
||||
hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
|
||||
params.isRtlSupported());
|
||||
navigationBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
mNavigationBarSize,
|
||||
@ -289,6 +293,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
|
||||
LinearLayout topLayout = new LinearLayout(context);
|
||||
topLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
topLayout.setLayoutDirection(direction);
|
||||
// if we don't already have a view root this is it
|
||||
if (mViewRoot == null) {
|
||||
mViewRoot = topLayout;
|
||||
@ -300,13 +305,22 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
|
||||
// this is the case of soft buttons + vertical bar.
|
||||
// this top layout is the first layout in the horizontal layout. see above)
|
||||
if (isRtl && params.isRtlSupported()) {
|
||||
// If RTL is enabled, layoutlib will mirror the layouts. So, add the
|
||||
// topLayout to the right of Navigation Bar and layoutlib will draw it
|
||||
// to the left.
|
||||
mViewRoot.addView(topLayout);
|
||||
} else {
|
||||
// Add the top layout to the left of the Navigation Bar.
|
||||
mViewRoot.addView(topLayout, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (mStatusBarSize > 0) {
|
||||
// system bar
|
||||
try {
|
||||
StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
|
||||
StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
|
||||
direction, params.isRtlSupported());
|
||||
systemBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mStatusBarSize));
|
||||
@ -365,7 +379,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
// system bar
|
||||
try {
|
||||
NavigationBar navigationBar = new NavigationBar(context,
|
||||
hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
|
||||
hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
|
||||
params.isRtlSupported());
|
||||
navigationBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mNavigationBarSize));
|
||||
|
Reference in New Issue
Block a user