am 7676e403: Merge changes I4c215676,Ib476302c,I0aede288,I9241dec7,Ibe7167a6, ... into mnc-dev

* commit '7676e403bd65435eb3d2f34e7e0174fd37f6e818':
  Update status bar time.
  Fix imports.
  Add MockView constructor used by LayoutInflater.
  Poor implementation of Path.approximate()
  Include EpicenterTranslateClipReveal in LayoutLib
  Fix theme namespace in tests.
  LayoutLib: fix layout when nav bar is absent.
  LayoutLib: Fix Status/Navigation Bar color.
This commit is contained in:
Deepanshu Gupta
2015-07-30 22:07:27 +00:00
committed by Android Git Automerger
9 changed files with 112 additions and 44 deletions

View File

@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.NonNull;
import android.graphics.Path.Direction; import android.graphics.Path.Direction;
import android.graphics.Path.FillType; import android.graphics.Path.FillType;
@ -30,10 +31,12 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator; import java.awt.geom.PathIterator;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
/** /**
* Delegate implementing the native methods of android.graphics.Path * Delegate implementing the native methods of android.graphics.Path
@ -56,7 +59,7 @@ public final class Path_Delegate {
// ---- delegate data ---- // ---- delegate data ----
private FillType mFillType = FillType.WINDING; private FillType mFillType = FillType.WINDING;
private GeneralPath mPath = new GeneralPath(); private Path2D mPath = new Path2D.Double();
private float mLastX = 0; private float mLastX = 0;
private float mLastY = 0; private float mLastY = 0;
@ -486,8 +489,54 @@ public final class Path_Delegate {
@LayoutlibDelegate @LayoutlibDelegate
/*package*/ static float[] native_approximate(long nPath, float error) { /*package*/ static float[] native_approximate(long nPath, float error) {
Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not supported", null); Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not fully supported",
null);
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return null;
}
PathIterator pathIterator = pathDelegate.mPath.getPathIterator(null);
float[] tmp = new float[6];
float[] coords = new float[6];
boolean isFirstPoint = true;
while (!pathIterator.isDone()) {
int type = pathIterator.currentSegment(tmp);
switch (type) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_LINETO:
store(coords, tmp, 1, isFirstPoint);
break;
case PathIterator.SEG_QUADTO:
store(coords, tmp, 2, isFirstPoint);
break;
case PathIterator.SEG_CUBICTO:
store(coords, tmp, 3, isFirstPoint);
break;
case PathIterator.SEG_CLOSE:
// No points returned.
}
isFirstPoint = false;
pathIterator.next();
}
if (isFirstPoint) {
// No points found
return new float[0]; return new float[0];
} else {
return coords;
}
}
private static void store(float[] src, float[] dst, int count, boolean isFirst) {
if (isFirst) {
dst[0] = 0;
dst[1] = src[0];
dst[2] = src[1];
}
if (count > 1 || !isFirst) {
dst[3] = 1;
dst[4] = src[2 * count];
dst[5] = src[2 * count + 1];
}
} }
// ---- Private helper methods ---- // ---- Private helper methods ----
@ -522,6 +571,7 @@ public final class Path_Delegate {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@NonNull
private static Direction getDirection(int direction) { private static Direction getDirection(int direction) {
for (Direction d : Direction.values()) { for (Direction d : Direction.values()) {
if (direction == d.nativeInt) { if (direction == d.nativeInt) {

View File

@ -30,6 +30,10 @@ import android.widget.TextView;
*/ */
public class MockView extends TextView { public class MockView extends TextView {
public MockView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MockView(Context context, AttributeSet attrs, int defStyle) { public MockView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs, defStyle, 0); this(context, attrs, defStyle, 0);
} }

View File

@ -18,14 +18,12 @@ package com.android.layoutlib.bridge.android.support;
import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.view.View; import android.view.View;
import java.lang.reflect.Method;
import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
@ -53,10 +51,7 @@ public class DesignLibUtil {
return; return;
} }
try { try {
Method setTitle = getMethod(view.getClass(), "setTitle", CharSequence.class); invoke(getMethod(view.getClass(), "setTitle", CharSequence.class), view, title);
if (setTitle != null) {
invoke(setTitle, view, title);
}
} catch (ReflectionException e) { } catch (ReflectionException e) {
Bridge.getLog().warning(LayoutLog.TAG_INFO, Bridge.getLog().warning(LayoutLog.TAG_INFO,
"Error occurred while trying to set title.", e); "Error occurred while trying to set title.", e);

View File

@ -21,16 +21,13 @@ import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.util.ReflectionUtils; import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import java.lang.reflect.Method;
import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause; import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause;
import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod; import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke; import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
@ -98,8 +95,7 @@ public class RecyclerViewUtil {
@Nullable @Nullable
private static Object getLayoutManager(View recyclerView) throws ReflectionException { private static Object getLayoutManager(View recyclerView) throws ReflectionException {
Method getLayoutManager = getMethod(recyclerView.getClass(), "getLayoutManager"); return invoke(getMethod(recyclerView.getClass(), "getLayoutManager"), recyclerView);
return getLayoutManager != null ? invoke(getLayoutManager, recyclerView) : null;
} }
@Nullable @Nullable
@ -127,10 +123,7 @@ public class RecyclerViewUtil {
private static void setProperty(@NonNull Object object, @NonNull Class<?> propertyClass, private static void setProperty(@NonNull Object object, @NonNull Class<?> propertyClass,
@Nullable Object propertyValue, @NonNull String propertySetter) @Nullable Object propertyValue, @NonNull String propertySetter)
throws ReflectionException { throws ReflectionException {
Method setter = getMethod(object.getClass(), propertySetter, propertyClass); invoke(getMethod(object.getClass(), propertySetter, propertyClass), object, propertyValue);
if (setter != null) {
invoke(setter, object, propertyValue);
}
} }
/** /**

View File

@ -74,8 +74,8 @@ public class Config {
} }
public static String getTime(int platformVersion) { public static String getTime(int platformVersion) {
if (isGreaterOrEqual(platformVersion, LOLLIPOP_MR1)) { if (isGreaterOrEqual(platformVersion, MNC)) {
return "5:10"; return "6:00";
} }
if (platformVersion < GINGERBREAD) { if (platformVersion < GINGERBREAD) {
return "2:20"; return "2:20";
@ -95,6 +95,9 @@ public class Config {
if (platformVersion < LOLLIPOP_MR1) { if (platformVersion < LOLLIPOP_MR1) {
return "5:00"; return "5:00";
} }
if (platformVersion < MNC) {
return "5:10";
}
// Should never happen. // Should never happen.
return "4:04"; return "4:04";
} }

View File

@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.bars; package com.android.layoutlib.bridge.bars;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.ide.common.rendering.api.StyleResourceValue;
@ -258,8 +259,21 @@ abstract class CustomBar extends LinearLayout {
ResourceValue resource = renderResources.findItemInTheme(attr, true); ResourceValue resource = renderResources.findItemInTheme(attr, true);
// Form @color/bar to the #AARRGGBB // Form @color/bar to the #AARRGGBB
resource = renderResources.resolveResValue(resource); resource = renderResources.resolveResValue(resource);
if (resource != null && ResourceType.COLOR.equals(resource.getResourceType())) { if (resource != null) {
ResourceType type = resource.getResourceType();
if (type == null || type == ResourceType.COLOR) {
// if no type is specified, the value may have been specified directly in the style
// file, rather than referencing a color resource value.
try {
return ResourceHelper.getColor(resource.getValue()); return ResourceHelper.getColor(resource.getValue());
} catch (NumberFormatException e) {
// Conversion failed.
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
"Theme attribute @android:" + attr +
" does not reference a color, instead is '" +
resource.getValue() + "'.", resource);
}
}
} }
return 0; return 0;
} }

View File

@ -45,6 +45,7 @@ import android.widget.RelativeLayout;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.LinearLayout.VERTICAL; import static android.widget.LinearLayout.VERTICAL;
import static com.android.layoutlib.bridge.impl.ResourceHelper.getBooleanThemeValue;
/** /**
* The Layout used to create the system decor. * The Layout used to create the system decor.
@ -165,13 +166,13 @@ class Layout extends RelativeLayout {
FrameLayout contentRoot = new FrameLayout(getContext()); FrameLayout contentRoot = new FrameLayout(getContext());
LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT); LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
if (mBuilder.solidBars()) { if (mBuilder.hasNavBar() && mBuilder.solidBars()) {
params.addRule(rule, getId(ID_NAV_BAR)); params.addRule(rule, getId(ID_NAV_BAR));
} }
int below = -1; int below = -1;
if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) { if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) {
below = getId(ID_TITLE_BAR); below = getId(ID_TITLE_BAR);
} else if (mBuilder.solidBars()) { } else if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
below = getId(ID_STATUS_BAR); below = getId(ID_STATUS_BAR);
} }
if (below != -1) { if (below != -1) {
@ -238,10 +239,10 @@ class Layout extends RelativeLayout {
} }
LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT); LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
if (mBuilder.solidBars()) { if (mBuilder.hasNavBar() && mBuilder.solidBars()) {
layoutParams.addRule(rule, getId(ID_NAV_BAR)); layoutParams.addRule(rule, getId(ID_NAV_BAR));
} }
if (mBuilder.solidBars()) { if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
layoutParams.addRule(BELOW, getId(ID_STATUS_BAR)); layoutParams.addRule(BELOW, getId(ID_STATUS_BAR));
} }
actionBar.getRootView().setLayoutParams(layoutParams); actionBar.getRootView().setLayoutParams(layoutParams);
@ -254,7 +255,7 @@ class Layout extends RelativeLayout {
int simulatedPlatformVersion) { int simulatedPlatformVersion) {
TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion); TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize); LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize);
if (mBuilder.solidBars()) { if (mBuilder.hasStatusBar() && mBuilder.solidBars()) {
params.addRule(BELOW, getId(ID_STATUS_BAR)); params.addRule(BELOW, getId(ID_STATUS_BAR));
} }
if (mBuilder.isNavBarVertical() && mBuilder.solidBars()) { if (mBuilder.isNavBarVertical() && mBuilder.solidBars()) {
@ -325,7 +326,7 @@ class Layout extends RelativeLayout {
mParams = params; mParams = params;
mContext = context; mContext = context;
mResources = mParams.getResources(); mResources = mParams.getResources();
mWindowIsFloating = ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true); mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
findBackground(); findBackground();
findStatusBar(); findStatusBar();
@ -333,10 +334,6 @@ class Layout extends RelativeLayout {
findNavBar(); findNavBar();
} }
public boolean isNavBarVertical() {
return mNavBarOrientation == VERTICAL;
}
private void findBackground() { private void findBackground() {
if (!mParams.isBgColorOverridden()) { if (!mParams.isBgColorOverridden()) {
mWindowBackground = mResources.findItemInTheme(ATTR_WINDOW_BACKGROUND, true); mWindowBackground = mResources.findItemInTheme(ATTR_WINDOW_BACKGROUND, true);
@ -346,11 +343,11 @@ class Layout extends RelativeLayout {
private void findStatusBar() { private void findStatusBar() {
boolean windowFullScreen = boolean windowFullScreen =
ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false); getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false);
if (!windowFullScreen && !mWindowIsFloating) { if (!windowFullScreen && !mWindowIsFloating) {
mStatusBarSize = mStatusBarSize =
getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT); getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT);
mTranslucentStatus = ResourceHelper.getBooleanThemeValue(mResources, mTranslucentStatus = getBooleanThemeValue(mResources,
ATTR_WINDOW_TRANSLUCENT_STATUS, true, false); ATTR_WINDOW_TRANSLUCENT_STATUS, true, false);
} }
} }
@ -360,14 +357,14 @@ class Layout extends RelativeLayout {
return; return;
} }
// Check if an actionbar is needed // Check if an actionbar is needed
boolean windowActionBar = ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
!isThemeAppCompat(), true); !isThemeAppCompat(), true);
if (windowActionBar) { if (windowActionBar) {
mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT); mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
} else { } else {
// Maybe the gingerbread era title bar is needed // Maybe the gingerbread era title bar is needed
boolean windowNoTitle = boolean windowNoTitle =
ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false); getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false);
if (!windowNoTitle) { if (!windowNoTitle) {
mTitleBarSize = mTitleBarSize =
getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT); getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
@ -395,7 +392,7 @@ class Layout extends RelativeLayout {
mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL; mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL;
mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH, mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH,
true, DEFAULT_NAV_BAR_SIZE); true, DEFAULT_NAV_BAR_SIZE);
mTranslucentNav = ResourceHelper.getBooleanThemeValue(mResources, mTranslucentNav = getBooleanThemeValue(mResources,
ATTR_WINDOW_TRANSLUCENT_NAV, true, false); ATTR_WINDOW_TRANSLUCENT_NAV, true, false);
} }
} }
@ -444,16 +441,27 @@ class Layout extends RelativeLayout {
} }
/** /**
* Return if both status bar and nav bar are solid (content doesn't overlap with these * Return true if the status bar or nav bar are present, they are not translucent (i.e
* bars). * content doesn't overlap with them).
*/ */
private boolean solidBars() { private boolean solidBars() {
return hasNavBar() && !mTranslucentNav && !mTranslucentStatus && mStatusBarSize > 0; return !(hasNavBar() && mTranslucentNav) && !(hasStatusBar() && mTranslucentStatus);
} }
private boolean hasNavBar() { private boolean hasNavBar() {
return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) && return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) &&
hasSoftwareButtons() && mNavBarSize > 0; hasSoftwareButtons() && mNavBarSize > 0;
} }
private boolean hasStatusBar() {
return mStatusBarSize > 0;
}
/**
* Return true if the nav bar is present and is vertical.
*/
private boolean isNavBarVertical() {
return hasNavBar() && mNavBarOrientation == VERTICAL;
}
} }
} }

View File

@ -285,7 +285,7 @@ public class Main {
ConfigGenerator.getEnumMap(attrs), getLayoutLog()); ConfigGenerator.getEnumMap(attrs), getLayoutLog());
} }
/** Text activity.xml */ /** Test activity.xml */
@Test @Test
public void testActivity() throws ClassNotFoundException { public void testActivity() throws ClassNotFoundException {
renderAndVerify("activity.xml", "activity.png"); renderAndVerify("activity.xml", "activity.png");
@ -404,7 +404,7 @@ public class Main {
ResourceResolver resourceResolver = ResourceResolver resourceResolver =
ResourceResolver.create(sProjectResources.getConfiguredResources(config), ResourceResolver.create(sProjectResources.getConfiguredResources(config),
sFrameworkRepo.getConfiguredResources(config), sFrameworkRepo.getConfiguredResources(config),
themeName, true); themeName, false);
return new SessionParams( return new SessionParams(
layoutParser, layoutParser,

View File

@ -119,6 +119,7 @@ public class Main {
"android.icu.**", // needed by LayoutLib "android.icu.**", // needed by LayoutLib
"android.annotation.NonNull", // annotations "android.annotation.NonNull", // annotations
"android.annotation.Nullable", // annotations "android.annotation.Nullable", // annotations
"com.android.internal.transition.EpicenterTranslateClipReveal",
}, },
excludeClasses, excludeClasses,
new String[] { new String[] {