diff options
author | Deepanshu Gupta <deepanshu@google.com> | 2015-08-26 20:20:58 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-08-26 20:20:58 +0000 |
commit | 5eaa09ff9e4cbf71fd8ca312029987c0c3d43f9e (patch) | |
tree | a5a08bad9b1c5b80c401d51d0cf9927bcd9c44ef | |
parent | 1f2c15ca8e976f3378c9e4cf63b55de3484bb2cc (diff) | |
parent | d1dde055060d63f8981ba51aeb75ab8a459db9b4 (diff) | |
download | frameworks_base-5eaa09ff9e4cbf71fd8ca312029987c0c3d43f9e.zip frameworks_base-5eaa09ff9e4cbf71fd8ca312029987c0c3d43f9e.tar.gz frameworks_base-5eaa09ff9e4cbf71fd8ca312029987c0c3d43f9e.tar.bz2 |
am d1dde055: am e5afc311: Move the layout code out of RenderSessionImpl. [DO NOT MERGE]
* commit 'd1dde055060d63f8981ba51aeb75ab8a459db9b4':
Move the layout code out of RenderSessionImpl. [DO NOT MERGE]
11 files changed, 511 insertions, 490 deletions
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index d07f19f..a0813c5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -593,9 +593,13 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge { /** * Returns the integer id of a framework resource, from a given resource type and resource name. + * <p/> + * If no resource is found, it creates a dynamic id for the resource. + * * @param type the type of the resource * @param name the name of the resource. - * @return an {@link Integer} containing the resource id, or null if no resource were found. + * + * @return an {@link Integer} containing the resource id. */ @NonNull public static Integer getResourceId(ResourceType type, String name) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java index 8b8cc38..7f2d3b4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java @@ -31,7 +31,6 @@ import android.graphics.drawable.Drawable; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; import java.lang.reflect.InvocationTargetException; @@ -51,9 +50,8 @@ public class AppCompatActionBar extends BridgeActionBar { /** * Inflate the action bar and attach it to {@code parentView} */ - public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams params, - @NonNull ViewGroup parentView) { - super(context, params, parentView); + public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { + super(context, params); int contentRootId = context.getProjectResourceValue(ResourceType.ID, "action_bar_activity_content", 0); View contentView = getDecorContent().findViewById(contentRootId); @@ -64,7 +62,9 @@ public class AppCompatActionBar extends BridgeActionBar { // Something went wrong. Create a new FrameLayout in the enclosing layout. FrameLayout contentRoot = new FrameLayout(context); setMatchParent(contentRoot); - mEnclosingLayout.addView(contentRoot); + if (mEnclosingLayout != null) { + mEnclosingLayout.addView(contentRoot); + } setContentRoot(contentRoot); } try { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java index a19b689..f900b45 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java @@ -24,6 +24,7 @@ import com.android.ide.common.rendering.api.SessionParams; import com.android.layoutlib.bridge.android.BridgeContext; import android.annotation.NonNull; +import android.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -39,7 +40,7 @@ public abstract class BridgeActionBar { @NonNull protected final BridgeContext mBridgeContext; @NonNull protected final SessionParams mParams; // A Layout that contains the inflated action bar. The menu popup is added to this layout. - @NonNull protected final ViewGroup mEnclosingLayout; + @Nullable protected final ViewGroup mEnclosingLayout; private final View mDecorContent; private final ActionBarCallback mCallback; @@ -47,8 +48,7 @@ public abstract class BridgeActionBar { @SuppressWarnings("NullableProblems") // Should be initialized by subclasses. @NonNull private FrameLayout mContentRoot; - public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params, - @NonNull ViewGroup parentView) { + public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { mBridgeContext = context; mParams = params; mCallback = params.getLayoutlibCallback().getActionBarCallback(); @@ -75,14 +75,13 @@ public abstract class BridgeActionBar { // added. mEnclosingLayout = new RelativeLayout(mBridgeContext); setMatchParent(mEnclosingLayout); - parentView.addView(mEnclosingLayout); } else { - mEnclosingLayout = parentView; + mEnclosingLayout = null; } // Inflate action bar layout. - mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout, true); - + mDecorContent = + getInflater(context).inflate(layoutId, mEnclosingLayout, mEnclosingLayout != null); } /** @@ -153,6 +152,13 @@ public abstract class BridgeActionBar { public abstract void createMenuPopup(); + /** + * The root view that represents the action bar and possibly the content included in it. + */ + public View getRootView() { + return mEnclosingLayout == null ? mDecorContent : mEnclosingLayout; + } + public ActionBarCallback getCallBack() { return mCallback; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index 90a1c75..c95fd74 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -68,7 +68,7 @@ abstract class CustomBar extends LinearLayout { protected abstract TextView getStyleableTextView(); protected CustomBar(BridgeContext context, int orientation, String layoutPath, - String name, int simulatedPlatformVersion) throws XmlPullParserException { + String name, int simulatedPlatformVersion) { super(context); mSimulatedPlatformVersion = simulatedPlatformVersion; setOrientation(orientation); @@ -81,11 +81,16 @@ abstract class CustomBar extends LinearLayout { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); - XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), - name); + XmlPullParser parser; + try { + parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), name); + } catch (XmlPullParserException e) { + // Should not happen as the resource is bundled with the jar, and ParserFactory should + // have been initialized. + throw new AssertionError(e); + } - BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( - parser, (BridgeContext) context, false /*platformFile*/); + BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(parser, context, false); try { inflater.inflate(bridgeParser, this, true); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java index bb3d13f..d2a5117 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java @@ -60,23 +60,24 @@ public class FrameworkActionBar extends BridgeActionBar { /** * Inflate the action bar and attach it to {@code parentView} */ - public FrameworkActionBar(@NonNull BridgeContext context, @NonNull SessionParams params, - @NonNull ViewGroup parentView) { - super(context, params, parentView); + public FrameworkActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) { + super(context, params); View decorContent = getDecorContent(); mActionBar = FrameworkActionBarWrapper.getActionBarWrapper(context, getCallBack(), decorContent); - FrameLayout contentRoot = (FrameLayout) mEnclosingLayout.findViewById(android.R.id.content); + FrameLayout contentRoot = (FrameLayout) decorContent.findViewById(android.R.id.content); // If something went wrong and we were not able to initialize the content root, // just add a frame layout inside this and return. if (contentRoot == null) { contentRoot = new FrameLayout(context); setMatchParent(contentRoot); - mEnclosingLayout.addView(contentRoot); + if (mEnclosingLayout != null) { + mEnclosingLayout.addView(contentRoot); + } setContentRoot(contentRoot); } else { setContentRoot(contentRoot); @@ -162,6 +163,7 @@ public class FrameworkActionBar extends BridgeActionBar { listView.setDivider(a.getDrawable(R.attr.actionBarDivider)); a.recycle(); listView.setElevation(mActionBar.getMenuPopupElevation()); + assert mEnclosingLayout != null : "Unable to find view to attach ActionMenuPopup."; mEnclosingLayout.addView(listView); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java index daad602..af6ba24 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java @@ -79,7 +79,7 @@ public abstract class FrameworkActionBarWrapper { } } - FrameworkActionBarWrapper(@NonNull BridgeContext context, ActionBarCallback callback, + FrameworkActionBarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback, @NonNull ActionBar actionBar) { mActionBar = actionBar; mCallback = callback; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java index 04aadff..b543ca6 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java @@ -19,8 +19,6 @@ package com.android.layoutlib.bridge.bars; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.resources.Density; -import org.xmlpull.v1.XmlPullParserException; - import android.content.Context; import android.content.pm.ApplicationInfo; import android.util.AttributeSet; @@ -37,8 +35,8 @@ public class NavigationBar extends CustomBar { * Constructor to be used when creating the {@link NavigationBar} as a regular control. * This is currently used by the theme editor. */ - public NavigationBar(Context context, AttributeSet attrs) - throws XmlPullParserException { + @SuppressWarnings("unused") + public NavigationBar(Context context, AttributeSet attrs) { this((BridgeContext) context, Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically @@ -49,7 +47,7 @@ public class NavigationBar extends CustomBar { } public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl, - boolean rtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException { + boolean rtlEnabled, int simulatedPlatformVersion) { super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml", simulatedPlatformVersion); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java index a0ed0e8..b77f140 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java @@ -26,6 +26,7 @@ import com.android.resources.Density; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; @@ -47,17 +48,19 @@ public class StatusBar extends CustomBar { * Constructor to be used when creating the {@link StatusBar} as a regular control. This * is currently used by the theme editor. */ - public StatusBar(Context context, AttributeSet attrs) throws XmlPullParserException { + @SuppressWarnings("UnusedParameters") + public StatusBar(Context context, AttributeSet attrs) { this((BridgeContext) context, Density.getEnum(((BridgeContext) context).getMetrics().densityDpi), - LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically ((BridgeContext) context).getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL, + (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0, context.getApplicationInfo().targetSdkVersion); } - public StatusBar(BridgeContext context, Density density, int direction, boolean RtlEnabled, - int simulatedPlatformVersion) throws XmlPullParserException { + @SuppressWarnings("UnusedParameters") + public StatusBar(BridgeContext context, Density density, boolean isRtl, boolean rtlEnabled, + int simulatedPlatformVersion) { // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar. super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml", simulatedPlatformVersion); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java index c610601..4fe1001 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java @@ -27,8 +27,7 @@ public class TitleBar extends CustomBar { private TextView mTextView; - public TitleBar(BridgeContext context, String label, int simulatedPlatformVersion) - throws XmlPullParserException { + public TitleBar(BridgeContext context, String label, int simulatedPlatformVersion) { super(context, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml", simulatedPlatformVersion); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java new file mode 100644 index 0000000..0798716 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2015 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 com.android.layoutlib.bridge.impl; + +import com.android.ide.common.rendering.api.HardwareConfig; +import com.android.ide.common.rendering.api.RenderResources; +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; +import com.android.layoutlib.bridge.bars.BridgeActionBar; +import com.android.layoutlib.bridge.bars.Config; +import com.android.layoutlib.bridge.bars.FrameworkActionBar; +import com.android.layoutlib.bridge.bars.NavigationBar; +import com.android.layoutlib.bridge.bars.StatusBar; +import com.android.layoutlib.bridge.bars.TitleBar; +import com.android.resources.Density; +import com.android.resources.ResourceType; +import com.android.resources.ScreenOrientation; + +import android.annotation.NonNull; +import android.graphics.drawable.Drawable; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.widget.LinearLayout.VERTICAL; + +/** + * The Layout used to create the system decor. + * + * The layout inflated will contain a content frame where the user's layout can be inflated. + * <pre> + * +-------------------------------------------------+---+ + * | Status bar | N | + * +-------------------------------------------------+ a | + * | Title/Action bar (optional) | v | + * +-------------------------------------------------+ | + * | Content, vertical extending | b | + * | | a | + * | | r | + * +-------------------------------------------------+---+ + * </pre> + * or + * <pre> + * +-------------------------------------+ + * | Status bar | + * +-------------------------------------+ + * | Title/Action bar (optional) | + * +-------------------------------------+ + * | Content, vertical extending | + * | | + * | | + * +-------------------------------------+ + * | Nav bar | + * +-------------------------------------+ + * </pre> + * + */ +class Layout extends RelativeLayout { + + // Theme attributes used for configuring appearance of the system decor. + private static final String ATTR_WINDOW_FLOATING = "windowIsFloating"; + private static final String ATTR_WINDOW_BACKGROUND = "windowBackground"; + private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullScreen"; + private static final String ATTR_NAV_BAR_HEIGHT = "navigation_bar_height"; + private static final String ATTR_NAV_BAR_WIDTH = "navigation_bar_width"; + private static final String ATTR_STATUS_BAR_HEIGHT = "status_bar_height"; + private static final String ATTR_WINDOW_ACTION_BAR = "windowActionBar"; + 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 PREFIX_THEME_APPCOMPAT = "Theme.AppCompat"; + + // Default sizes + private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; + private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; + private static final int DEFAULT_NAV_BAR_SIZE = 48; + + // Ids assigned to components created. This is so that we can refer to other components in + // layout params. + private static final String ID_NAV_BAR = "navBar"; + private static final String ID_STATUS_BAR = "statusBar"; + private static final String ID_TITLE_BAR = "titleBar"; + // Prefix used with the above ids in order to make them unique in framework namespace. + private static final String ID_PREFIX = "android_layoutlib_"; + + /** + * Temporarily store the builder so that it doesn't have to be passed to all methods used + * during inflation. + */ + private Builder mBuilder; + + /** + * This holds user's layout. + */ + private FrameLayout mContentRoot; + + public Layout(@NonNull Builder builder) { + super(builder.mContext); + mBuilder = builder; + if (builder.mWindowBackground != null) { + Drawable d = ResourceHelper.getDrawable(builder.mWindowBackground, builder.mContext); + setBackground(d); + } + + int simulatedPlatformVersion = getParams().getSimulatedPlatformVersion(); + HardwareConfig hwConfig = getParams().getHardwareConfig(); + Density density = hwConfig.getDensity(); + boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale()); + + NavigationBar navBar = null; + if (Config.showOnScreenNavBar(simulatedPlatformVersion) && mBuilder.hasSoftwareButtons() && + builder.isNavBarVertical()) { + navBar = createNavBar(getContext(), density, isRtl, getParams().isRtlSupported(), + simulatedPlatformVersion); + } + + StatusBar statusBar = null; + if (builder.mStatusBarSize > 0) { + statusBar = createStatusBar(getContext(), density, isRtl, getParams().isRtlSupported(), + simulatedPlatformVersion); + } + + View actionBar = null; + TitleBar titleBar = null; + if (builder.mActionBarSize > 0) { + BridgeActionBar bar = createActionBar(getContext(), getParams()); + mContentRoot = bar.getContentRoot(); + actionBar = bar.getRootView(); + } else if (mBuilder.mTitleBarSize > 0) { + titleBar = createTitleBar(getContext(), getParams().getAppLabel(), + simulatedPlatformVersion); + } + + addViews(titleBar, mContentRoot == null ? (mContentRoot = createContentFrame()) : actionBar, + statusBar, navBar); + // Done with the builder. Don't hold a reference to it. + mBuilder = null; + } + + @NonNull + private FrameLayout createContentFrame() { + FrameLayout contentRoot = new FrameLayout(getContext()); + LayoutParams params = + new LayoutParams(MATCH_PARENT, MATCH_PARENT); + int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; + if (mBuilder.mNavBarSize > 0) { + 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) { + below = getId(ID_STATUS_BAR); + } + if (below != -1) { + params.addRule(BELOW, below); + } + + return contentRoot; + } + + @NonNull + public FrameLayout getContentRoot() { + return mContentRoot; + } + + @NonNull + private SessionParams getParams() { + return mBuilder.mParams; + } + + @NonNull + @Override + public BridgeContext getContext(){ + return (BridgeContext) super.getContext(); + } + + /** + * @param isRtl whether the current locale is an RTL locale. + * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true + * in the manifest and targetSdkVersion >= 17. + */ + @NonNull + private StatusBar createStatusBar(BridgeContext context, Density density, boolean isRtl, + boolean isRtlSupported, int simulatedPlatformVersion) { + StatusBar statusBar = + new StatusBar(context, density, isRtl, isRtlSupported, simulatedPlatformVersion); + LayoutParams params = new LayoutParams(MATCH_PARENT, mBuilder.mStatusBarSize); + if (mBuilder.isNavBarVertical()) { + params.addRule(START_OF, getId(ID_NAV_BAR)); + } + statusBar.setLayoutParams(params); + statusBar.setId(getId(ID_STATUS_BAR)); + return statusBar; + } + + private BridgeActionBar createActionBar(@NonNull BridgeContext context, + @NonNull SessionParams params) { + BridgeActionBar actionBar; + if (mBuilder.isThemeAppCompat()) { + actionBar = new AppCompatActionBar(context, params); + } else { + actionBar = new FrameworkActionBar(context, params); + } + LayoutParams layoutParams = new LayoutParams(MATCH_PARENT, MATCH_PARENT); + int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE; + if (mBuilder.mNavBarSize > 0) { + layoutParams.addRule(rule, getId(ID_NAV_BAR)); + } + if (mBuilder.mStatusBarSize > 0) { + layoutParams.addRule(BELOW, getId(ID_STATUS_BAR)); + } + actionBar.getRootView().setLayoutParams(layoutParams); + actionBar.createMenuPopup(); + 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) { + params.addRule(BELOW, getId(ID_STATUS_BAR)); + } + if (mBuilder.isNavBarVertical()) { + params.addRule(START_OF, getId(ID_NAV_BAR)); + } + titleBar.setLayoutParams(params); + titleBar.setId(getId(ID_TITLE_BAR)); + return titleBar; + } + + /** + * @param isRtl whether the current locale is an RTL locale. + * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true + * in the manifest and targetSdkVersion >= 17. + */ + @NonNull + private NavigationBar createNavBar(BridgeContext context, Density density, boolean isRtl, + boolean isRtlSupported, int simulatedPlatformVersion) { + int orientation = mBuilder.mNavBarOrientation; + int size = mBuilder.mNavBarSize; + NavigationBar navBar = new NavigationBar(context, density, orientation, isRtl, + isRtlSupported, simulatedPlatformVersion); + boolean isVertical = mBuilder.isNavBarVertical(); + int w = isVertical ? size : MATCH_PARENT; + int h = isVertical ? MATCH_PARENT : size; + LayoutParams params = new LayoutParams(w, h); + params.addRule(isVertical ? ALIGN_PARENT_END : ALIGN_PARENT_BOTTOM); + navBar.setLayoutParams(params); + navBar.setId(getId(ID_NAV_BAR)); + return navBar; + } + + private void addViews(@NonNull View... views) { + for (View view : views) { + if (view != null) { + addView(view); + } + } + } + + private int getId(String name) { + return Bridge.getResourceId(ResourceType.ID, ID_PREFIX + name); + } + + /** + * A helper class to help initialize the Layout. + */ + static class Builder { + @NonNull + private final SessionParams mParams; + @NonNull + private final BridgeContext mContext; + private final RenderResources mResources; + + private final boolean mWindowIsFloating; + private ResourceValue mWindowBackground; + private int mStatusBarSize; + private int mNavBarSize; + private int mNavBarOrientation; + private int mActionBarSize; + private int mTitleBarSize; + + private Boolean mIsThemeAppCompat; + + public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) { + mParams = params; + mContext = context; + mResources = mParams.getResources(); + mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true); + + findBackground(); + findStatusBar(); + findActionBar(); + findNavBar(); + } + + public boolean isNavBarVertical() { + return mNavBarOrientation == VERTICAL; + } + + private void findBackground() { + if (!mParams.isBgColorOverridden()) { + mWindowBackground = mResources.findItemInTheme(ATTR_WINDOW_BACKGROUND, true); + mWindowBackground = mResources.resolveResValue(mWindowBackground); + } + } + + private void findStatusBar() { + boolean windowFullScreen = + getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false); + if (!windowFullScreen && !mWindowIsFloating) { + mStatusBarSize = + getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT); + } + } + + private void findActionBar() { + if (mWindowIsFloating) { + return; + } + // Check if an actionbar is needed + boolean windowActionBar = 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); + if (!windowNoTitle) { + mTitleBarSize = + getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT); + } + } + } + + private void findNavBar() { + if (hasSoftwareButtons() && !mWindowIsFloating) { + + // get orientation + HardwareConfig hwConfig = mParams.getHardwareConfig(); + boolean barOnBottom = true; + + if (hwConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { + int shortSize = hwConfig.getScreenHeight(); + int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / + hwConfig.getDensity().getDpiValue(); + + // 0-599dp: "phone" UI with bar on the side + // 600+dp: "tablet" UI with bar on the bottom + barOnBottom = shortSizeDp >= 600; + } + + mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL; + mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH, + true, DEFAULT_NAV_BAR_SIZE); + } + } + + private int getDimension(String attr, boolean isFramework, int defaultValue) { + ResourceValue value = mResources.findItemInTheme(attr, isFramework); + value = mResources.resolveResValue(value); + if (value != null) { + TypedValue typedValue = ResourceHelper.getValue(attr, value.getValue(), true); + if (typedValue != null) { + return (int) typedValue.getDimension(mContext.getMetrics()); + } + } + 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(); + } + + 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; + } + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index 6a9d5dd..15d14cb 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -29,10 +29,8 @@ import com.android.ide.common.rendering.api.Result; import com.android.ide.common.rendering.api.Result.Status; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.SessionParams.RenderingMode; -import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.ide.common.rendering.api.ViewInfo; import com.android.ide.common.rendering.api.ViewType; -import com.android.internal.util.XmlUtils; import com.android.internal.view.menu.ActionMenuItemView; import com.android.internal.view.menu.BridgeMenuItemImpl; import com.android.internal.view.menu.IconMenuItemView; @@ -45,22 +43,11 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.layoutlib.bridge.android.support.DesignLibUtil; -import com.android.layoutlib.bridge.bars.AppCompatActionBar; -import com.android.layoutlib.bridge.bars.BridgeActionBar; -import com.android.layoutlib.bridge.bars.Config; -import com.android.layoutlib.bridge.bars.FrameworkActionBar; -import com.android.layoutlib.bridge.bars.NavigationBar; -import com.android.layoutlib.bridge.bars.StatusBar; -import com.android.layoutlib.bridge.bars.TitleBar; import com.android.layoutlib.bridge.impl.binding.FakeAdapter; import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter; -import com.android.resources.Density; import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; import com.android.util.Pair; -import org.xmlpull.v1.XmlPullParserException; - import android.animation.AnimationThread; import android.animation.Animator; import android.animation.AnimatorInflater; @@ -72,10 +59,7 @@ import android.app.Fragment_Delegate; import android.graphics.Bitmap; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; -import android.graphics.drawable.Drawable; import android.preference.Preference_Delegate; -import android.util.DisplayMetrics; -import android.util.TypedValue; import android.view.AttachInfo_Accessor; import android.view.BridgeInflater; import android.view.IWindowManager; @@ -126,33 +110,22 @@ import static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf; */ public class RenderSessionImpl extends RenderAction<SessionParams> { - private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; - private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; - // scene state private RenderSession mScene; private BridgeXmlBlockParser mBlockParser; private BridgeInflater mInflater; - private ResourceValue mWindowBackground; private ViewGroup mViewRoot; private FrameLayout mContentRoot; private Canvas mCanvas; private int mMeasuredScreenWidth = -1; private int mMeasuredScreenHeight = -1; private boolean mIsAlphaChannelImage; - private boolean mWindowIsFloating; - private Boolean mIsThemeAppCompat; - - private int mStatusBarSize; - private int mNavigationBarSize; - private int mNavigationBarOrientation = LinearLayout.HORIZONTAL; - private int mTitleBarSize; - private int mActionBarSize; // information being returned through the API private BufferedImage mImage; private List<ViewInfo> mViewInfoList; private List<ViewInfo> mSystemViewInfoList; + private Layout.Builder mLayoutBuilder; private static final class PostInflateException extends Exception { private static final long serialVersionUID = 1L; @@ -196,34 +169,24 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { SessionParams params = getParams(); BridgeContext context = getContext(); - - RenderResources resources = getParams().getResources(); - DisplayMetrics metrics = getContext().getMetrics(); - // use default of true in case it's not found to use alpha by default - mIsAlphaChannelImage = getBooleanThemeValue(resources, "windowIsFloating", true, true); - // FIXME: Find out why both variables are taking the same value. - mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", true, true); + mIsAlphaChannelImage = Layout.Builder.getBooleanThemeValue(params.getResources(), + "windowIsFloating", true, true); - findBackground(resources); - findStatusBar(resources, metrics); - findActionBar(resources, metrics); - findNavigationBar(resources, metrics); + mLayoutBuilder = new Layout.Builder(params, context); // FIXME: find those out, and possibly add them to the render params boolean hasNavigationBar = true; //noinspection ConstantConditions IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(), - metrics, Surface.ROTATION_0, - hasNavigationBar); + context.getMetrics(), Surface.ROTATION_0, hasNavigationBar); WindowManagerGlobal_Delegate.setWindowManagerService(iwm); // build the inflater and parser. mInflater = new BridgeInflater(context, params.getLayoutlibCallback()); context.setBridgeInflater(mInflater); - mBlockParser = new BridgeXmlBlockParser( - params.getLayoutDescription(), context, false /* platformResourceFlag */); + mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false); return SUCCESS.createResult(); } @@ -240,164 +203,11 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { checkLock(); try { - + mViewRoot = new Layout(mLayoutBuilder); + mLayoutBuilder = null; // Done with the builder. + mContentRoot = ((Layout) mViewRoot).getContentRoot(); SessionParams params = getParams(); - HardwareConfig hardwareConfig = params.getHardwareConfig(); BridgeContext context = getContext(); - boolean isRtl = Bridge.isLocaleRtl(params.getLocale()); - int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR; - - // the view group that receives the window background. - ViewGroup backgroundView; - - if (mWindowIsFloating || params.isForceNoDecor()) { - backgroundView = mViewRoot = mContentRoot = new FrameLayout(context); - mViewRoot.setLayoutDirection(layoutDirection); - } else { - int simulatedPlatformVersion = params.getSimulatedPlatformVersion(); - if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) { - /* - * This is a special case where the navigation bar is on the right. - +-------------------------------------------------+---+ - | Status bar (always) | | - +-------------------------------------------------+ | - | (Layout with background drawable) | | - | +---------------------------------------------+ | | - | | Title/Action bar (optional) | | | - | +---------------------------------------------+ | | - | | Content, vertical extending | | | - | | | | | - | +---------------------------------------------+ | | - +-------------------------------------------------+---+ - - So we create a horizontal layout, with the nav bar on the right, - and the left part is the normal layout below without the nav bar at - the bottom - */ - LinearLayout topLayout = new LinearLayout(context); - topLayout.setLayoutDirection(layoutDirection); - mViewRoot = topLayout; - topLayout.setOrientation(LinearLayout.HORIZONTAL); - - if (Config.showOnScreenNavBar(simulatedPlatformVersion)) { - try { - NavigationBar navigationBar = createNavigationBar(context, - hardwareConfig.getDensity(), isRtl, params.isRtlSupported(), - simulatedPlatformVersion); - topLayout.addView(navigationBar); - } catch (XmlPullParserException ignored) { - } - } - } - - /* - * we're creating the following layout - * - +-------------------------------------------------+ - | Status bar (always) | - +-------------------------------------------------+ - | (Layout with background drawable) | - | +---------------------------------------------+ | - | | Title/Action bar (optional) | | - | +---------------------------------------------+ | - | | Content, vertical extending | | - | | | | - | +---------------------------------------------+ | - +-------------------------------------------------+ - | Navigation bar for soft buttons, maybe see above| - +-------------------------------------------------+ - - */ - - LinearLayout topLayout = new LinearLayout(context); - topLayout.setOrientation(LinearLayout.VERTICAL); - topLayout.setLayoutDirection(layoutDirection); - // if we don't already have a view root this is it - if (mViewRoot == null) { - mViewRoot = topLayout; - } else { - int topLayoutWidth = - params.getHardwareConfig().getScreenWidth() - mNavigationBarSize; - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - topLayoutWidth, LayoutParams.MATCH_PARENT); - topLayout.setLayoutParams(layoutParams); - - // 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 statusBar = createStatusBar(context, hardwareConfig.getDensity(), - layoutDirection, params.isRtlSupported(), - simulatedPlatformVersion); - topLayout.addView(statusBar); - } catch (XmlPullParserException ignored) { - - } - } - - LinearLayout backgroundLayout = new LinearLayout(context); - backgroundView = backgroundLayout; - backgroundLayout.setOrientation(LinearLayout.VERTICAL); - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, 0); - layoutParams.weight = 1; - backgroundLayout.setLayoutParams(layoutParams); - topLayout.addView(backgroundLayout); - - - // if the theme says no title/action bar, then the size will be 0 - if (mActionBarSize > 0) { - BridgeActionBar actionBar = createActionBar(context, params, backgroundLayout); - actionBar.createMenuPopup(); - mContentRoot = actionBar.getContentRoot(); - } else if (mTitleBarSize > 0) { - try { - TitleBar titleBar = createTitleBar(context, - params.getAppLabel(), - simulatedPlatformVersion); - backgroundLayout.addView(titleBar); - } catch (XmlPullParserException ignored) { - - } - } - - // content frame - if (mContentRoot == null) { - mContentRoot = new FrameLayout(context); - layoutParams = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, 0); - layoutParams.weight = 1; - mContentRoot.setLayoutParams(layoutParams); - backgroundLayout.addView(mContentRoot); - } - - if (Config.showOnScreenNavBar(simulatedPlatformVersion) && - mNavigationBarOrientation == LinearLayout.HORIZONTAL && - mNavigationBarSize > 0) { - // system bar - try { - NavigationBar navigationBar = createNavigationBar(context, - hardwareConfig.getDensity(), isRtl, params.isRtlSupported(), - simulatedPlatformVersion); - topLayout.addView(navigationBar); - } catch (XmlPullParserException ignored) { - - } - } - } - // Sets the project callback (custom view loader) to the fragment delegate so that // it can instantiate the custom Fragment. @@ -408,7 +218,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { View view; if (isPreference) { view = Preference_Delegate.inflatePreference(getContext(), mBlockParser, - mContentRoot); + mContentRoot); } else { view = mInflater.inflate(mBlockParser, mContentRoot); } @@ -427,12 +237,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { setActiveToolbar(view, context, params); - // get the background drawable - if (mWindowBackground != null) { - Drawable d = ResourceHelper.getDrawable(mWindowBackground, context); - backgroundView.setBackground(d); - } - return SUCCESS.createResult(); } catch (PostInflateException e) { return ERROR_INFLATION.createResult(e.getMessage(), e); @@ -1073,198 +877,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { } } - - private void findBackground(RenderResources resources) { - if (!getParams().isBgColorOverridden()) { - mWindowBackground = resources.findItemInTheme("windowBackground", - true /*isFrameworkAttr*/); - if (mWindowBackground != null) { - mWindowBackground = resources.resolveResValue(mWindowBackground); - } - } - } - - private boolean hasSoftwareButtons() { - return getParams().getHardwareConfig().hasSoftwareButtons(); - } - - private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { - boolean windowFullscreen = getBooleanThemeValue(resources, - "windowFullscreen", false, true); - - if (!windowFullscreen && !mWindowIsFloating) { - // default value - mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; - - // get the real value - ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - "status_bar_height"); - - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("status_bar_height", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mStatusBarSize = (int)typedValue.getDimension(metrics); - } - } - } - } - - private void findActionBar(RenderResources resources, DisplayMetrics metrics) { - if (mWindowIsFloating) { - return; - } - - boolean windowActionBar = getBooleanThemeValue(resources, - "windowActionBar", true, !isThemeAppCompat(resources)); - - // if there's a value and it's false (default is true) - if (windowActionBar) { - - // default size of the window title bar - mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT; - - // get value from the theme. - ResourceValue value = resources.findItemInTheme("actionBarSize", - true /*isFrameworkAttr*/); - - // resolve it - value = resources.resolveResValue(value); - - if (value != null) { - // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(), - true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mActionBarSize = (int)typedValue.getDimension(metrics); - } - } - } else { - // action bar overrides title bar so only look for this one if action bar is hidden - boolean windowNoTitle = getBooleanThemeValue(resources, "windowNoTitle", false, true); - - if (!windowNoTitle) { - - // default size of the window title bar - mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT; - - // get value from the theme. - ResourceValue value = resources.findItemInTheme("windowTitleSize", - true /*isFrameworkAttr*/); - - // resolve it - value = resources.resolveResValue(value); - - if (value != null) { - // get the numerical value, if available - TypedValue typedValue = ResourceHelper.getValue("windowTitleSize", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mTitleBarSize = (int)typedValue.getDimension(metrics); - } - } - } - - } - } - - private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) { - if (hasSoftwareButtons() && !mWindowIsFloating) { - - // default value - mNavigationBarSize = 48; // ?? - - HardwareConfig hardwareConfig = getParams().getHardwareConfig(); - - boolean barOnBottom = true; - - if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) { - // compute the dp of the screen. - int shortSize = hardwareConfig.getScreenHeight(); - - // compute in dp - int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / - hardwareConfig.getDensity().getDpiValue(); - - // 0-599dp: "phone" UI with bar on the side - // 600+dp: "tablet" UI with bar on the bottom - barOnBottom = shortSizeDp >= 600; - } - - if (barOnBottom) { - mNavigationBarOrientation = LinearLayout.HORIZONTAL; - } else { - mNavigationBarOrientation = LinearLayout.VERTICAL; - } - - // get the real value - ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, - barOnBottom ? "navigation_bar_height" : "navigation_bar_width"); - - if (value != null) { - TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height", - value.getValue(), true /*requireUnit*/); - if (typedValue != null) { - // compute the pixel value based on the display metrics - mNavigationBarSize = (int)typedValue.getDimension(metrics); - } - } - } - } - - private boolean isThemeAppCompat(RenderResources resources) { - // Ideally, we should check if the corresponding activity extends - // android.support.v7.app.ActionBarActivity, and not care about the theme name at all. - if (mIsThemeAppCompat == null) { - StyleResourceValue defaultTheme = resources.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("Theme.AppCompat")) { - isThemeAppCompat = true; - break; - } - defaultTheme = resources.getParent(defaultTheme); - } - mIsThemeAppCompat = isThemeAppCompat; - } - return mIsThemeAppCompat; - } - - /** - * 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. - */ - private boolean getBooleanThemeValue(RenderResources resources, - String name, boolean defaultValue, boolean isFrameworkAttr) { - - ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr); - - // because it may reference something else, we resolve it. - value = resources.resolveResValue(value); - - // if there's no value, return the default. - if (value == null || value.getValue() == null) { - return defaultValue; - } - - return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); - } - /** * Post process on a view hierarchy that was just inflated. * <p/> @@ -1737,63 +1349,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { mMeasuredScreenWidth = mMeasuredScreenHeight = -1; } - /** - * Creates the status bar with wifi and battery icons. - */ - private StatusBar createStatusBar(BridgeContext context, Density density, int direction, - boolean isRtlSupported, int platformVersion) throws XmlPullParserException { - StatusBar statusBar = new StatusBar(context, density, - direction, isRtlSupported, platformVersion); - statusBar.setLayoutParams( - new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, mStatusBarSize)); - return statusBar; - } - - /** - * Creates the navigation bar with back, home and recent buttons. - * - * @param isRtl true if the current locale is right-to-left - * @param isRtlSupported true is the project manifest declares that the application - * is RTL aware. - */ - private NavigationBar createNavigationBar(BridgeContext context, Density density, - boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion) - throws XmlPullParserException { - NavigationBar navigationBar = new NavigationBar(context, - density, mNavigationBarOrientation, isRtl, - isRtlSupported, simulatedPlatformVersion); - if (mNavigationBarOrientation == LinearLayout.VERTICAL) { - navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize, - LayoutParams.MATCH_PARENT)); - } else { - navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, - mNavigationBarSize)); - } - return navigationBar; - } - - private TitleBar createTitleBar(BridgeContext context, String title, - int simulatedPlatformVersion) - throws XmlPullParserException { - TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion); - titleBar.setLayoutParams( - new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize)); - return titleBar; - } - - /** - * Creates the action bar. Also queries the project callback for missing information. - */ - private BridgeActionBar createActionBar(BridgeContext context, SessionParams params, - ViewGroup parentView) { - if (mIsThemeAppCompat == Boolean.TRUE) { - return new AppCompatActionBar(context, params, parentView); - } else { - return new FrameworkActionBar(context, params, parentView); - } - } - public BufferedImage getImage() { return mImage; } |