import org.xmlpull.v1.XmlPullParserException;
import android.annotation.NonNull;
-import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
setGravity(Gravity.CENTER_HORIZONTAL);
}
- LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
XmlPullParser parser;
try {
protected void setStyle(String themeEntryName) {
- BridgeContext bridgeContext = (BridgeContext) mContext;
+ BridgeContext bridgeContext = getContext();
RenderResources res = bridgeContext.getRenderResources();
ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
}
}
+ @Override
+ public BridgeContext getContext() {
+ return (BridgeContext) mContext;
+ }
+
/**
- * Given a theme attribute name, get the color referenced by it. The theme attribute may be
- * used in a layout like "?attr/foo".
+ * Find the background color for this bar from the theme attributes. Only relevant to StatusBar
+ * and NavigationBar.
* <p/>
* Returns 0 if not found.
*
+ * @param colorAttrName the attribute name for the background color
+ * @param translucentAttrName the attribute name for the translucency property of the bar.
+ *
* @throws NumberFormatException if color resolved to an invalid string.
*/
- protected int getThemeAttrColor(@NonNull String attrName, boolean isFramework) {
+ protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
return 0;
}
- assert mContext instanceof BridgeContext;
- BridgeContext context = ((BridgeContext) mContext);
- RenderResources renderResources = context.getRenderResources();
- // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
- ResourceValue resource = renderResources.findItemInTheme(attrName, isFramework);
- if (resource != null) {
- // Form @color/bar to the #AARRGGBB
- resource = renderResources.resolveResValue(resource);
+ RenderResources renderResources = getContext().getRenderResources();
+ // First check if the bar is translucent.
+ boolean translucent = ResourceHelper.getBooleanThemeValue(renderResources,
+ translucentAttrName, true, false);
+ if (translucent) {
+ // Keep in sync with R.color.system_bar_background_semi_transparent from system ui.
+ return 0x66000000; // 40% black.
+ }
+ boolean transparent = ResourceHelper.getBooleanThemeValue(renderResources,
+ "windowDrawsSystemBarBackgrounds", true, false);
+ if (transparent) {
+ return getColor(renderResources, colorAttrName);
}
+ return 0;
+ }
+
+ private static int getColor(RenderResources renderResources, String attr) {
+ // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
+ ResourceValue resource = renderResources.findItemInTheme(attr, true);
+ // Form @color/bar to the #AARRGGBB
+ resource = renderResources.resolveResValue(resource);
if (resource != null && ResourceType.COLOR.equals(resource.getResourceType())) {
return ResourceHelper.getColor(resource.getValue());
}
}
private ResourceValue getResourceValue(String reference) {
- BridgeContext bridgeContext = (BridgeContext) mContext;
- RenderResources res = bridgeContext.getRenderResources();
+ RenderResources res = getContext().getRenderResources();
// find the resource
ResourceValue value = res.findResValue(reference, false);
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.bars.AppCompatActionBar;
private static final String ATTR_ACTION_BAR_SIZE = "actionBarSize";
private static final String ATTR_WINDOW_NO_TITLE = "windowNoTitle";
private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize";
+ private static final String ATTR_WINDOW_TRANSLUCENT_STATUS = StatusBar.ATTR_TRANSLUCENT;
+ private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT;
private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
// Default sizes
boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale());
NavigationBar navBar = null;
- if (Config.showOnScreenNavBar(simulatedPlatformVersion) && mBuilder.hasSoftwareButtons() &&
- builder.isNavBarVertical()) {
+ if (mBuilder.hasNavBar()) {
navBar = createNavBar(getContext(), density, isRtl, getParams().isRtlSupported(),
simulatedPlatformVersion);
}
@NonNull
private FrameLayout createContentFrame() {
FrameLayout contentRoot = new FrameLayout(getContext());
- LayoutParams params =
- new LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.mNavBarSize > 0) {
+ if (mBuilder.solidBars()) {
params.addRule(rule, getId(ID_NAV_BAR));
}
int below = -1;
if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) {
below = getId(ID_TITLE_BAR);
- } else if (mBuilder.mStatusBarSize > 0) {
+ } else if (mBuilder.solidBars()) {
below = getId(ID_STATUS_BAR);
}
if (below != -1) {
params.addRule(BELOW, below);
}
-
+ contentRoot.setLayoutParams(params);
return contentRoot;
}
@NonNull
+ private LayoutParams createLayoutParams(int width, int height) {
+ DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+ if (width > 0) {
+ width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics);
+ }
+ if (height > 0) {
+ height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics);
+ }
+ return new LayoutParams(width, height);
+ }
+
+ @NonNull
public FrameLayout getContentRoot() {
return mContentRoot;
}
boolean isRtlSupported, int simulatedPlatformVersion) {
StatusBar statusBar =
new StatusBar(context, density, isRtl, isRtlSupported, simulatedPlatformVersion);
- LayoutParams params = new LayoutParams(MATCH_PARENT, mBuilder.mStatusBarSize);
+ LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mStatusBarSize);
if (mBuilder.isNavBarVertical()) {
params.addRule(START_OF, getId(ID_NAV_BAR));
}
} else {
actionBar = new FrameworkActionBar(context, params);
}
- LayoutParams layoutParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.mNavBarSize > 0) {
+ if (mBuilder.solidBars()) {
layoutParams.addRule(rule, getId(ID_NAV_BAR));
}
- if (mBuilder.mStatusBarSize > 0) {
+ if (mBuilder.solidBars()) {
layoutParams.addRule(BELOW, getId(ID_STATUS_BAR));
}
actionBar.getRootView().setLayoutParams(layoutParams);
return actionBar;
}
-
@NonNull
private TitleBar createTitleBar(BridgeContext context, String title,
int simulatedPlatformVersion) {
TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
- LayoutParams params = new LayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize);
- if (mBuilder.mStatusBarSize > 0) {
+ LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize);
+ if (mBuilder.solidBars()) {
params.addRule(BELOW, getId(ID_STATUS_BAR));
}
- if (mBuilder.isNavBarVertical()) {
+ if (mBuilder.isNavBarVertical() && mBuilder.solidBars()) {
params.addRule(START_OF, getId(ID_NAV_BAR));
}
titleBar.setLayoutParams(params);
boolean isVertical = mBuilder.isNavBarVertical();
int w = isVertical ? size : MATCH_PARENT;
int h = isVertical ? MATCH_PARENT : size;
- LayoutParams params = new LayoutParams(w, h);
+ LayoutParams params = createLayoutParams(w, h);
params.addRule(isVertical ? ALIGN_PARENT_END : ALIGN_PARENT_BOTTOM);
navBar.setLayoutParams(params);
navBar.setId(getId(ID_NAV_BAR));
private int mNavBarOrientation;
private int mActionBarSize;
private int mTitleBarSize;
+ private boolean mTranslucentStatus;
+ private boolean mTranslucentNav;
private Boolean mIsThemeAppCompat;
mParams = params;
mContext = context;
mResources = mParams.getResources();
- mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
+ mWindowIsFloating = ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
findBackground();
findStatusBar();
private void findStatusBar() {
boolean windowFullScreen =
- getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false);
+ ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false);
if (!windowFullScreen && !mWindowIsFloating) {
mStatusBarSize =
getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT);
+ mTranslucentStatus = ResourceHelper.getBooleanThemeValue(mResources,
+ ATTR_WINDOW_TRANSLUCENT_STATUS, true, false);
}
}
return;
}
// Check if an actionbar is needed
- boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
- isThemeAppCompat(), true);
+ boolean windowActionBar = ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
+ !isThemeAppCompat(), true);
if (windowActionBar) {
mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
} else {
// Maybe the gingerbread era title bar is needed
boolean windowNoTitle =
- getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false);
+ ResourceHelper.getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false);
if (!windowNoTitle) {
mTitleBarSize =
getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL;
mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH,
true, DEFAULT_NAV_BAR_SIZE);
+ mTranslucentNav = ResourceHelper.getBooleanThemeValue(mResources,
+ ATTR_WINDOW_TRANSLUCENT_NAV, true, false);
}
}
return defaultValue;
}
- /**
- * Looks for an attribute in the current theme.
- *
- * @param resources the render resources
- * @param name the name of the attribute
- * @param defaultValue the default value.
- * @param isFrameworkAttr if the attribute is in android namespace
- * @return the value of the attribute or the default one if not found.
- */
- static boolean getBooleanThemeValue(@NonNull RenderResources resources, String name,
- boolean isFrameworkAttr, boolean defaultValue) {
- ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr);
- value = resources.resolveResValue(value);
- if (value == null) {
- return defaultValue;
- }
- return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
- }
-
private boolean hasSoftwareButtons() {
return mParams.getHardwareConfig().hasSoftwareButtons();
}
mIsThemeAppCompat = isThemeAppCompat;
return isThemeAppCompat;
}
+
+ /**
+ * Return if both status bar and nav bar are solid (content doesn't overlap with these
+ * bars).
+ */
+ private boolean solidBars() {
+ return hasNavBar() && !mTranslucentNav && !mTranslucentStatus && mStatusBarSize > 0;
+ }
+
+ private boolean hasNavBar() {
+ return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) &&
+ hasSoftwareButtons() && mNavBarSize > 0;
+ }
}
}