Loading tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -584,6 +584,7 @@ public final class BridgeTypedArray extends TypedArray { if (value == null) { if (value == null) { return defValue; return defValue; } } value = value.trim(); // if the value is just an integer, return it. // if the value is just an integer, return it. try { try { Loading @@ -595,6 +596,11 @@ public final class BridgeTypedArray extends TypedArray { // pass // pass } } if (value.startsWith("#")) { // this looks like a color, do not try to parse it return defValue; } // Handle the @id/<name>, @+id/<name> and @android:id/<name> // Handle the @id/<name>, @+id/<name> and @android:id/<name> // We need to return the exact value that was compiled (from the various R classes), // We need to return the exact value that was compiled (from the various R classes), // as these values can be reused internally with calls to findViewById(). // as these values can be reused internally with calls to findViewById(). Loading tools/layoutlib/bridge/src/android/view/BridgeInflater.java +63 −19 Original line number Original line Diff line number Diff line Loading @@ -42,9 +42,24 @@ import android.util.AttributeSet; import android.widget.NumberPicker; import android.widget.NumberPicker; import java.io.File; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map; import java.util.Set; import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW; import static com.android.SdkConstants.BUTTON; import static com.android.SdkConstants.CHECKED_TEXT_VIEW; import static com.android.SdkConstants.CHECK_BOX; import static com.android.SdkConstants.EDIT_TEXT; import static com.android.SdkConstants.IMAGE_BUTTON; import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW; import static com.android.SdkConstants.RADIO_BUTTON; import static com.android.SdkConstants.SEEK_BAR; import static com.android.SdkConstants.SPINNER; import static com.android.SdkConstants.TEXT_VIEW; import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; /** /** Loading @@ -53,6 +68,13 @@ import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; public final class BridgeInflater extends LayoutInflater { public final class BridgeInflater extends LayoutInflater { private final LayoutlibCallback mLayoutlibCallback; private final LayoutlibCallback mLayoutlibCallback; /** * If true, the inflater will try to replace the framework widgets with the AppCompat versions. * Ideally, this should be based on the activity being an AppCompat activity but since that is * not trivial to check from layoutlib, we currently base the decision on the current theme * being an AppCompat theme. */ private boolean mLoadAppCompatViews; private boolean mIsInMerge = false; private boolean mIsInMerge = false; private ResourceReference mResourceReference; private ResourceReference mResourceReference; private Map<View, String> mOpenDrawerLayouts; private Map<View, String> mOpenDrawerLayouts; Loading @@ -60,6 +82,15 @@ public final class BridgeInflater extends LayoutInflater { // Keep in sync with the same value in LayoutInflater. // Keep in sync with the same value in LayoutInflater. private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; private static final String APPCOMPAT_WIDGET_PREFIX = "android.support.v7.widget.AppCompat"; /** List of platform widgets that have an AppCompat version */ private static final Set<String> APPCOMPAT_VIEWS = Collections.unmodifiableSet( new HashSet<>( Arrays.asList(TEXT_VIEW, "ImageSwitcher", BUTTON, EDIT_TEXT, SPINNER, IMAGE_BUTTON, CHECK_BOX, RADIO_BUTTON, CHECKED_TEXT_VIEW, AUTO_COMPLETE_TEXT_VIEW, MULTI_AUTO_COMPLETE_TEXT_VIEW, "RatingBar", SEEK_BAR))); /** /** * List of class prefixes which are tried first by default. * List of class prefixes which are tried first by default. * <p/> * <p/> Loading @@ -75,13 +106,15 @@ public final class BridgeInflater extends LayoutInflater { return sClassPrefixList; return sClassPrefixList; } } protected BridgeInflater(LayoutInflater original, Context newContext) { private BridgeInflater(LayoutInflater original, Context newContext) { super(original, newContext); super(original, newContext); newContext = getBaseContext(newContext); newContext = getBaseContext(newContext); if (newContext instanceof BridgeContext) { if (newContext instanceof BridgeContext) { mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback(); mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback(); mLoadAppCompatViews = ((BridgeContext) newContext).isAppCompatTheme(); } else { } else { mLayoutlibCallback = null; mLayoutlibCallback = null; mLoadAppCompatViews = false; } } } } Loading @@ -91,10 +124,11 @@ public final class BridgeInflater extends LayoutInflater { * @param context The Android application context. * @param context The Android application context. * @param layoutlibCallback the {@link LayoutlibCallback} object. * @param layoutlibCallback the {@link LayoutlibCallback} object. */ */ public BridgeInflater(Context context, LayoutlibCallback layoutlibCallback) { public BridgeInflater(BridgeContext context, LayoutlibCallback layoutlibCallback) { super(context); super(context); mLayoutlibCallback = layoutlibCallback; mLayoutlibCallback = layoutlibCallback; mConstructorArgs[0] = context; mConstructorArgs[0] = context; mLoadAppCompatViews = context.isAppCompatTheme(); } } @Override @Override Loading @@ -102,6 +136,15 @@ public final class BridgeInflater extends LayoutInflater { View view = null; View view = null; try { try { if (mLoadAppCompatViews && APPCOMPAT_VIEWS.contains(name)) { // We are using an AppCompat theme so try to load the appcompat views view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs); if (view == null) { mLoadAppCompatViews = false; // Do not try anymore } } else { // First try to find a class using the default Android prefixes // First try to find a class using the default Android prefixes for (String prefix : sClassPrefixList) { for (String prefix : sClassPrefixList) { try { try { Loading @@ -123,6 +166,7 @@ public final class BridgeInflater extends LayoutInflater { } catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) { // Ignore. We'll try again using the custom view loader below. // Ignore. We'll try again using the custom view loader below. } } } // Finally try again using the custom view loader // Finally try again using the custom view loader if (view == null) { if (view == null) { Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,7 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP */ */ @SuppressWarnings("deprecation") // For use of Pair. @SuppressWarnings("deprecation") // For use of Pair. public final class BridgeContext extends Context { public final class BridgeContext extends Context { private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; /** The map adds cookies to each view so that IDE can link xml tags to views. */ /** The map adds cookies to each view so that IDE can link xml tags to views. */ private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); Loading Loading @@ -153,6 +154,7 @@ public final class BridgeContext extends Context { private ClassLoader mClassLoader; private ClassLoader mClassLoader; private IBinder mBinder; private IBinder mBinder; private PackageManager mPackageManager; private PackageManager mPackageManager; private Boolean mIsThemeAppCompat; /** /** * Some applications that target both pre API 17 and post API 17, set the newer attrs to * Some applications that target both pre API 17 and post API 17, set the newer attrs to Loading Loading @@ -479,6 +481,36 @@ public final class BridgeContext extends Context { return Pair.of(null, Boolean.FALSE); return Pair.of(null, Boolean.FALSE); } } /** * Returns whether the current selected theme is based on AppCompat */ public boolean isAppCompatTheme() { // If a cached value exists, return it. if (mIsThemeAppCompat != null) { return mIsThemeAppCompat; } // Ideally, we should check if the corresponding activity extends // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme(); // We can't simply check for parent using resources.themeIsParentOf() since the // inheritance structure isn't really what one would expect. The first common parent // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). boolean isThemeAppCompat = false; for (int i = 0; i < 50; i++) { if (defaultTheme == null) { break; } // for loop ensures that we don't run into cyclic theme inheritance. if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { isThemeAppCompat = true; break; } defaultTheme = mRenderResources.getParent(defaultTheme); } mIsThemeAppCompat = isThemeAppCompat; return isThemeAppCompat; } @SuppressWarnings("deprecation") @SuppressWarnings("deprecation") private ILayoutPullParser getParser(ResourceReference resource) { private ILayoutPullParser getParser(ResourceReference resource) { ILayoutPullParser parser; ILayoutPullParser parser; Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java +2 −33 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ import com.android.ide.common.rendering.api.HardwareConfig; 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.SessionParams; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.StyleResourceValue; 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; Loading Loading @@ -94,7 +93,6 @@ class Layout extends RelativeLayout { private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize"; 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_STATUS = StatusBar.ATTR_TRANSLUCENT; private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; // Default sizes // Default sizes private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; Loading Loading @@ -236,7 +234,7 @@ class Layout extends RelativeLayout { boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); BridgeActionBar actionBar; BridgeActionBar actionBar; if (mBuilder.isThemeAppCompat() && !isMenu) { if (context.isAppCompatTheme() && !isMenu) { actionBar = new AppCompatActionBar(context, params); actionBar = new AppCompatActionBar(context, params); } else { } else { actionBar = new FrameworkActionBar(context, params); actionBar = new FrameworkActionBar(context, params); Loading Loading @@ -324,8 +322,6 @@ class Layout extends RelativeLayout { private boolean mTranslucentStatus; private boolean mTranslucentStatus; private boolean mTranslucentNav; private boolean mTranslucentNav; private Boolean mIsThemeAppCompat; public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { mParams = params; mParams = params; mContext = context; mContext = context; Loading Loading @@ -365,7 +361,7 @@ class Layout extends RelativeLayout { } } // Check if an actionbar is needed // Check if an actionbar is needed boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, !isThemeAppCompat(), true); !mContext.isAppCompatTheme(), 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 { Loading Loading @@ -420,33 +416,6 @@ class Layout extends RelativeLayout { return mParams.getHardwareConfig().hasSoftwareButtons(); return mParams.getHardwareConfig().hasSoftwareButtons(); } } private boolean isThemeAppCompat() { // If a cached value exists, return it. if (mIsThemeAppCompat != null) { return mIsThemeAppCompat; } // Ideally, we should check if the corresponding activity extends // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. StyleResourceValue defaultTheme = mResources.getDefaultTheme(); // We can't simply check for parent using resources.themeIsParentOf() since the // inheritance structure isn't really what one would expect. The first common parent // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). boolean isThemeAppCompat = false; for (int i = 0; i < 50; i++) { if (defaultTheme == null) { break; } // for loop ensures that we don't run into cyclic theme inheritance. if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { isThemeAppCompat = true; break; } defaultTheme = mResources.getParent(defaultTheme); } mIsThemeAppCompat = isThemeAppCompat; return isThemeAppCompat; } /** /** * Return true if the status bar or nav bar are present, they are not translucent (i.e * Return true if the status bar or nav bar are present, they are not translucent (i.e * content doesn't overlap with them). * content doesn't overlap with them). Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,7 @@ public final class ResourceHelper { */ */ public static int getColor(String value) { public static int getColor(String value) { if (value != null) { if (value != null) { value = value.trim(); if (!value.startsWith("#")) { if (!value.startsWith("#")) { if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { throw new NumberFormatException(String.format( throw new NumberFormatException(String.format( Loading Loading
tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -584,6 +584,7 @@ public final class BridgeTypedArray extends TypedArray { if (value == null) { if (value == null) { return defValue; return defValue; } } value = value.trim(); // if the value is just an integer, return it. // if the value is just an integer, return it. try { try { Loading @@ -595,6 +596,11 @@ public final class BridgeTypedArray extends TypedArray { // pass // pass } } if (value.startsWith("#")) { // this looks like a color, do not try to parse it return defValue; } // Handle the @id/<name>, @+id/<name> and @android:id/<name> // Handle the @id/<name>, @+id/<name> and @android:id/<name> // We need to return the exact value that was compiled (from the various R classes), // We need to return the exact value that was compiled (from the various R classes), // as these values can be reused internally with calls to findViewById(). // as these values can be reused internally with calls to findViewById(). Loading
tools/layoutlib/bridge/src/android/view/BridgeInflater.java +63 −19 Original line number Original line Diff line number Diff line Loading @@ -42,9 +42,24 @@ import android.util.AttributeSet; import android.widget.NumberPicker; import android.widget.NumberPicker; import java.io.File; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map; import java.util.Set; import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW; import static com.android.SdkConstants.BUTTON; import static com.android.SdkConstants.CHECKED_TEXT_VIEW; import static com.android.SdkConstants.CHECK_BOX; import static com.android.SdkConstants.EDIT_TEXT; import static com.android.SdkConstants.IMAGE_BUTTON; import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW; import static com.android.SdkConstants.RADIO_BUTTON; import static com.android.SdkConstants.SEEK_BAR; import static com.android.SdkConstants.SPINNER; import static com.android.SdkConstants.TEXT_VIEW; import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; /** /** Loading @@ -53,6 +68,13 @@ import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext; public final class BridgeInflater extends LayoutInflater { public final class BridgeInflater extends LayoutInflater { private final LayoutlibCallback mLayoutlibCallback; private final LayoutlibCallback mLayoutlibCallback; /** * If true, the inflater will try to replace the framework widgets with the AppCompat versions. * Ideally, this should be based on the activity being an AppCompat activity but since that is * not trivial to check from layoutlib, we currently base the decision on the current theme * being an AppCompat theme. */ private boolean mLoadAppCompatViews; private boolean mIsInMerge = false; private boolean mIsInMerge = false; private ResourceReference mResourceReference; private ResourceReference mResourceReference; private Map<View, String> mOpenDrawerLayouts; private Map<View, String> mOpenDrawerLayouts; Loading @@ -60,6 +82,15 @@ public final class BridgeInflater extends LayoutInflater { // Keep in sync with the same value in LayoutInflater. // Keep in sync with the same value in LayoutInflater. private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme }; private static final String APPCOMPAT_WIDGET_PREFIX = "android.support.v7.widget.AppCompat"; /** List of platform widgets that have an AppCompat version */ private static final Set<String> APPCOMPAT_VIEWS = Collections.unmodifiableSet( new HashSet<>( Arrays.asList(TEXT_VIEW, "ImageSwitcher", BUTTON, EDIT_TEXT, SPINNER, IMAGE_BUTTON, CHECK_BOX, RADIO_BUTTON, CHECKED_TEXT_VIEW, AUTO_COMPLETE_TEXT_VIEW, MULTI_AUTO_COMPLETE_TEXT_VIEW, "RatingBar", SEEK_BAR))); /** /** * List of class prefixes which are tried first by default. * List of class prefixes which are tried first by default. * <p/> * <p/> Loading @@ -75,13 +106,15 @@ public final class BridgeInflater extends LayoutInflater { return sClassPrefixList; return sClassPrefixList; } } protected BridgeInflater(LayoutInflater original, Context newContext) { private BridgeInflater(LayoutInflater original, Context newContext) { super(original, newContext); super(original, newContext); newContext = getBaseContext(newContext); newContext = getBaseContext(newContext); if (newContext instanceof BridgeContext) { if (newContext instanceof BridgeContext) { mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback(); mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback(); mLoadAppCompatViews = ((BridgeContext) newContext).isAppCompatTheme(); } else { } else { mLayoutlibCallback = null; mLayoutlibCallback = null; mLoadAppCompatViews = false; } } } } Loading @@ -91,10 +124,11 @@ public final class BridgeInflater extends LayoutInflater { * @param context The Android application context. * @param context The Android application context. * @param layoutlibCallback the {@link LayoutlibCallback} object. * @param layoutlibCallback the {@link LayoutlibCallback} object. */ */ public BridgeInflater(Context context, LayoutlibCallback layoutlibCallback) { public BridgeInflater(BridgeContext context, LayoutlibCallback layoutlibCallback) { super(context); super(context); mLayoutlibCallback = layoutlibCallback; mLayoutlibCallback = layoutlibCallback; mConstructorArgs[0] = context; mConstructorArgs[0] = context; mLoadAppCompatViews = context.isAppCompatTheme(); } } @Override @Override Loading @@ -102,6 +136,15 @@ public final class BridgeInflater extends LayoutInflater { View view = null; View view = null; try { try { if (mLoadAppCompatViews && APPCOMPAT_VIEWS.contains(name)) { // We are using an AppCompat theme so try to load the appcompat views view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs); if (view == null) { mLoadAppCompatViews = false; // Do not try anymore } } else { // First try to find a class using the default Android prefixes // First try to find a class using the default Android prefixes for (String prefix : sClassPrefixList) { for (String prefix : sClassPrefixList) { try { try { Loading @@ -123,6 +166,7 @@ public final class BridgeInflater extends LayoutInflater { } catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) { // Ignore. We'll try again using the custom view loader below. // Ignore. We'll try again using the custom view loader below. } } } // Finally try again using the custom view loader // Finally try again using the custom view loader if (view == null) { if (view == null) { Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +32 −0 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,7 @@ import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_AP */ */ @SuppressWarnings("deprecation") // For use of Pair. @SuppressWarnings("deprecation") // For use of Pair. public final class BridgeContext extends Context { public final class BridgeContext extends Context { private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; /** The map adds cookies to each view so that IDE can link xml tags to views. */ /** The map adds cookies to each view so that IDE can link xml tags to views. */ private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); private final HashMap<View, Object> mViewKeyMap = new HashMap<>(); Loading Loading @@ -153,6 +154,7 @@ public final class BridgeContext extends Context { private ClassLoader mClassLoader; private ClassLoader mClassLoader; private IBinder mBinder; private IBinder mBinder; private PackageManager mPackageManager; private PackageManager mPackageManager; private Boolean mIsThemeAppCompat; /** /** * Some applications that target both pre API 17 and post API 17, set the newer attrs to * Some applications that target both pre API 17 and post API 17, set the newer attrs to Loading Loading @@ -479,6 +481,36 @@ public final class BridgeContext extends Context { return Pair.of(null, Boolean.FALSE); return Pair.of(null, Boolean.FALSE); } } /** * Returns whether the current selected theme is based on AppCompat */ public boolean isAppCompatTheme() { // If a cached value exists, return it. if (mIsThemeAppCompat != null) { return mIsThemeAppCompat; } // Ideally, we should check if the corresponding activity extends // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme(); // We can't simply check for parent using resources.themeIsParentOf() since the // inheritance structure isn't really what one would expect. The first common parent // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). boolean isThemeAppCompat = false; for (int i = 0; i < 50; i++) { if (defaultTheme == null) { break; } // for loop ensures that we don't run into cyclic theme inheritance. if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { isThemeAppCompat = true; break; } defaultTheme = mRenderResources.getParent(defaultTheme); } mIsThemeAppCompat = isThemeAppCompat; return isThemeAppCompat; } @SuppressWarnings("deprecation") @SuppressWarnings("deprecation") private ILayoutPullParser getParser(ResourceReference resource) { private ILayoutPullParser getParser(ResourceReference resource) { ILayoutPullParser parser; ILayoutPullParser parser; Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java +2 −33 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,6 @@ import com.android.ide.common.rendering.api.HardwareConfig; 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.SessionParams; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.StyleResourceValue; 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; Loading Loading @@ -94,7 +93,6 @@ class Layout extends RelativeLayout { private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize"; 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_STATUS = StatusBar.ATTR_TRANSLUCENT; private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT; private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; // Default sizes // Default sizes private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; Loading Loading @@ -236,7 +234,7 @@ class Layout extends RelativeLayout { boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG)); BridgeActionBar actionBar; BridgeActionBar actionBar; if (mBuilder.isThemeAppCompat() && !isMenu) { if (context.isAppCompatTheme() && !isMenu) { actionBar = new AppCompatActionBar(context, params); actionBar = new AppCompatActionBar(context, params); } else { } else { actionBar = new FrameworkActionBar(context, params); actionBar = new FrameworkActionBar(context, params); Loading Loading @@ -324,8 +322,6 @@ class Layout extends RelativeLayout { private boolean mTranslucentStatus; private boolean mTranslucentStatus; private boolean mTranslucentNav; private boolean mTranslucentNav; private Boolean mIsThemeAppCompat; public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { mParams = params; mParams = params; mContext = context; mContext = context; Loading Loading @@ -365,7 +361,7 @@ class Layout extends RelativeLayout { } } // Check if an actionbar is needed // Check if an actionbar is needed boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, boolean windowActionBar = getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR, !isThemeAppCompat(), true); !mContext.isAppCompatTheme(), 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 { Loading Loading @@ -420,33 +416,6 @@ class Layout extends RelativeLayout { return mParams.getHardwareConfig().hasSoftwareButtons(); return mParams.getHardwareConfig().hasSoftwareButtons(); } } private boolean isThemeAppCompat() { // If a cached value exists, return it. if (mIsThemeAppCompat != null) { return mIsThemeAppCompat; } // Ideally, we should check if the corresponding activity extends // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. StyleResourceValue defaultTheme = mResources.getDefaultTheme(); // We can't simply check for parent using resources.themeIsParentOf() since the // inheritance structure isn't really what one would expect. The first common parent // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21). boolean isThemeAppCompat = false; for (int i = 0; i < 50; i++) { if (defaultTheme == null) { break; } // for loop ensures that we don't run into cyclic theme inheritance. if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) { isThemeAppCompat = true; break; } defaultTheme = mResources.getParent(defaultTheme); } mIsThemeAppCompat = isThemeAppCompat; return isThemeAppCompat; } /** /** * Return true if the status bar or nav bar are present, they are not translucent (i.e * Return true if the status bar or nav bar are present, they are not translucent (i.e * content doesn't overlap with them). * content doesn't overlap with them). Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -77,6 +77,7 @@ public final class ResourceHelper { */ */ public static int getColor(String value) { public static int getColor(String value) { if (value != null) { if (value != null) { value = value.trim(); if (!value.startsWith("#")) { if (!value.startsWith("#")) { if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { throw new NumberFormatException(String.format( throw new NumberFormatException(String.format( Loading