am fe38489f: Action bar rendering in layoutlib [DO NOT MERGE]
* commit 'fe38489f6734fefd0a216e9cfe12f8f978ff371f': Action bar rendering in layoutlib [DO NOT MERGE]
This commit is contained in:
@@ -161,9 +161,11 @@ public class ShareActionProvider extends ActionProvider {
|
||||
@Override
|
||||
public View onCreateActionView() {
|
||||
// Create the view and set its data model.
|
||||
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
|
||||
ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
|
||||
activityChooserView.setActivityChooserModel(dataModel);
|
||||
if (!activityChooserView.isInEditMode()) {
|
||||
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
|
||||
activityChooserView.setActivityChooserModel(dataModel);
|
||||
}
|
||||
|
||||
// Lookup and set the expand action icon.
|
||||
TypedValue outTypedValue = new TypedValue();
|
||||
|
||||
@@ -162,6 +162,15 @@ public class ActionBarImpl extends ActionBar {
|
||||
init(dialog.getWindow().getDecorView());
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for edit mode.
|
||||
* @hide
|
||||
*/
|
||||
public ActionBarImpl(View layout) {
|
||||
assert layout.isInEditMode();
|
||||
init(layout);
|
||||
}
|
||||
|
||||
private void init(View decor) {
|
||||
mContext = decor.getContext();
|
||||
mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
|
||||
@@ -552,8 +561,8 @@ public class ActionBarImpl extends ActionBar {
|
||||
return;
|
||||
}
|
||||
|
||||
final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
|
||||
.disallowAddToBackStack();
|
||||
final FragmentTransaction trans = mActionView.isInEditMode() ? null :
|
||||
mActivity.getFragmentManager().beginTransaction().disallowAddToBackStack();
|
||||
|
||||
if (mSelectedTab == tab) {
|
||||
if (mSelectedTab != null) {
|
||||
@@ -571,7 +580,7 @@ public class ActionBarImpl extends ActionBar {
|
||||
}
|
||||
}
|
||||
|
||||
if (!trans.isEmpty()) {
|
||||
if (trans != null && !trans.isEmpty()) {
|
||||
trans.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<include layout="@android:layout/action_bar_home" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<include layout="@android:layout/screen_action_bar" />
|
||||
|
||||
</merge>
|
||||
|
||||
@@ -215,7 +215,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
Capability.ADAPTER_BINDING,
|
||||
Capability.EXTENDED_VIEWINFO,
|
||||
Capability.FIXED_SCALABLE_NINE_PATCH,
|
||||
Capability.RTL);
|
||||
Capability.RTL,
|
||||
Capability.ACTION_BAR);
|
||||
|
||||
|
||||
BridgeAssetManager.initSystem();
|
||||
|
||||
@@ -63,6 +63,11 @@ public class BridgeRenderSession extends RenderSession {
|
||||
return mSession.getViewInfos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewInfo> getSystemRootViews() {
|
||||
return mSession.getSystemViewInfos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getDefaultProperties(Object viewObject) {
|
||||
return mSession.getDefaultProperties(viewObject);
|
||||
|
||||
@@ -613,7 +613,8 @@ public final class BridgeContext extends Context {
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
if (value.getFirst() == ResourceType.STYLE) {
|
||||
if ((value.getFirst() == ResourceType.STYLE)
|
||||
|| (value.getFirst() == ResourceType.ATTR)) {
|
||||
// look for the style in the current theme, and its parent:
|
||||
ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
|
||||
isFrameworkRes);
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.bars;
|
||||
|
||||
import com.android.ide.common.rendering.api.ActionBarCallback;
|
||||
import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
|
||||
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.internal.app.ActionBarImpl;
|
||||
import com.android.internal.view.menu.MenuBuilder;
|
||||
import com.android.internal.widget.ActionBarContainer;
|
||||
import com.android.internal.widget.ActionBarView;
|
||||
import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
import com.android.layoutlib.bridge.impl.ParserFactory;
|
||||
import com.android.layoutlib.bridge.impl.ResourceHelper;
|
||||
import com.android.resources.ResourceType;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.ActionBar.Tab;
|
||||
import android.app.ActionBar.TabListener;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuInflater;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ActionBarLayout extends LinearLayout {
|
||||
|
||||
// Store another reference to the context so that we don't have to cast it repeatedly.
|
||||
@SuppressWarnings("hiding")
|
||||
private final BridgeContext mContext;
|
||||
private final ActionBar mActionBar;
|
||||
private final String mIcon;
|
||||
private final String mTitle;
|
||||
private final String mSubTitle;
|
||||
private final boolean mSplit;
|
||||
private final boolean mShowHomeAsUp;
|
||||
private final List<Integer> mMenuIds;
|
||||
private final MenuBuilder mMenuBuilder;
|
||||
private final int mNavMode;
|
||||
|
||||
public ActionBarLayout(BridgeContext context, SessionParams params)
|
||||
throws XmlPullParserException {
|
||||
super(context);
|
||||
mIcon = params.getAppIcon();
|
||||
mTitle = params.getAppLabel();
|
||||
mContext = context;
|
||||
mMenuIds = new ArrayList<Integer>();
|
||||
|
||||
ActionBarCallback callback = params.getProjectCallback().getActionBarCallback();
|
||||
mSplit = callback.getSplitActionBarWhenNarrow() &
|
||||
context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.split_action_bar_is_narrow);
|
||||
mNavMode = callback.getNavigationMode();
|
||||
// TODO: Support Navigation Drawer Indicator.
|
||||
mShowHomeAsUp = callback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
|
||||
mSubTitle = callback.getSubTitle();
|
||||
|
||||
fillMenuIds(callback.getMenuIdNames());
|
||||
mMenuBuilder = new MenuBuilder(mContext);
|
||||
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
setGravity(Gravity.CENTER_VERTICAL);
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
XmlPullParser parser = ParserFactory.create(
|
||||
getClass().getResourceAsStream("/bars/action_bar.xml"), "action_bar.xml");
|
||||
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
|
||||
parser, context, false /*platformFile*/);
|
||||
try {
|
||||
inflater.inflate(bridgeParser, this, true /*attachToRoot*/);
|
||||
} finally {
|
||||
bridgeParser.ensurePopped();
|
||||
}
|
||||
mActionBar = new ActionBarImpl(this);
|
||||
|
||||
setUpActionBar();
|
||||
}
|
||||
|
||||
private void fillMenuIds(List<String> menuIdNames) {
|
||||
for (String name : menuIdNames) {
|
||||
int id = mContext.getProjectResourceValue(ResourceType.MENU, name, -1);
|
||||
if (id > -1) {
|
||||
mMenuIds.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpActionBar() {
|
||||
RenderResources res = mContext.getRenderResources();
|
||||
Drawable iconDrawable = getDrawable(res, mIcon, false /*isFramework*/);
|
||||
if (iconDrawable != null) {
|
||||
mActionBar.setIcon(iconDrawable);
|
||||
}
|
||||
ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
|
||||
if (titleValue != null && titleValue.getValue() != null) {
|
||||
mActionBar.setTitle(titleValue.getValue());
|
||||
} else {
|
||||
mActionBar.setTitle(mTitle);
|
||||
}
|
||||
if (mSubTitle != null) {
|
||||
mActionBar.setSubtitle(mSubTitle);
|
||||
}
|
||||
ActionBarView actionBarView = (ActionBarView) findViewById(
|
||||
Bridge.getResourceId(ResourceType.ID, "action_bar"));
|
||||
actionBarView.setSplitView((ActionBarContainer) findViewById(
|
||||
Bridge.getResourceId(ResourceType.ID, "split_action_bar")));
|
||||
actionBarView.setSplitActionBar(mSplit);
|
||||
if (mShowHomeAsUp) {
|
||||
mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
|
||||
}
|
||||
setUpActionMenus();
|
||||
|
||||
mActionBar.setNavigationMode(mNavMode);
|
||||
if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
|
||||
setUpTabs(3);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpActionMenus() {
|
||||
if (mMenuIds == null) {
|
||||
return;
|
||||
}
|
||||
ActionBarView actionBarView = (ActionBarView) findViewById(Bridge.getResourceId(
|
||||
ResourceType.ID, "action_bar"));
|
||||
final MenuInflater inflater = new MenuInflater(mActionBar.getThemedContext());
|
||||
for (int id : mMenuIds) {
|
||||
inflater.inflate(id, mMenuBuilder);
|
||||
}
|
||||
actionBarView.setMenu(mMenuBuilder, null /*callback*/);
|
||||
}
|
||||
|
||||
// TODO: Use an adapter, like List View to set up tabs.
|
||||
private void setUpTabs(int num) {
|
||||
for (int i = 1; i <= num; i++) {
|
||||
Tab tab = mActionBar.newTab()
|
||||
.setText("Tab" + i)
|
||||
.setTabListener(new TabListener() {
|
||||
@Override
|
||||
public void onTabUnselected(Tab t, FragmentTransaction ft) {
|
||||
// pass
|
||||
}
|
||||
@Override
|
||||
public void onTabSelected(Tab t, FragmentTransaction ft) {
|
||||
// pass
|
||||
}
|
||||
@Override
|
||||
public void onTabReselected(Tab t, FragmentTransaction ft) {
|
||||
// pass
|
||||
}
|
||||
});
|
||||
mActionBar.addTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
private Drawable getDrawable(RenderResources res, String name, boolean isFramework) {
|
||||
ResourceValue value = res.findResValue(name, isFramework);
|
||||
value = res.resolveResValue(value);
|
||||
if (value != null) {
|
||||
return ResourceHelper.getDrawable(value, mContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.bars;
|
||||
|
||||
import com.android.resources.Density;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class FakeActionBar extends CustomBar {
|
||||
|
||||
private TextView mTextView;
|
||||
|
||||
public FakeActionBar(Context context, Density density, String label, String icon)
|
||||
throws XmlPullParserException {
|
||||
super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
|
||||
|
||||
// Cannot access the inside items through id because no R.id values have been
|
||||
// created for them.
|
||||
// We do know the order though.
|
||||
loadIconById(android.R.id.home, icon);
|
||||
mTextView = setText(1, label);
|
||||
|
||||
setStyle("actionBarStyle");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getStyleableTextView() {
|
||||
return mTextView;
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,13 @@ import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
|
||||
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
import com.android.layoutlib.bridge.bars.FakeActionBar;
|
||||
import com.android.layoutlib.bridge.bars.ActionBarLayout;
|
||||
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;
|
||||
@@ -134,6 +135,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
// information being returned through the API
|
||||
private BufferedImage mImage;
|
||||
private List<ViewInfo> mViewInfoList;
|
||||
private List<ViewInfo> mSystemViewInfoList;
|
||||
|
||||
private static final class PostInflateException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@@ -226,14 +228,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
HardwareConfig hardwareConfig = params.getHardwareConfig();
|
||||
BridgeContext context = getContext();
|
||||
boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
|
||||
int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
|
||||
int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
|
||||
|
||||
// the view group that receives the window background.
|
||||
ViewGroup backgroundView = null;
|
||||
|
||||
if (mWindowIsFloating || params.isForceNoDecor()) {
|
||||
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
|
||||
mViewRoot.setLayoutDirection(direction);
|
||||
mViewRoot.setLayoutDirection(layoutDirection);
|
||||
} else {
|
||||
if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
|
||||
/*
|
||||
@@ -255,18 +257,13 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
the bottom
|
||||
*/
|
||||
LinearLayout topLayout = new LinearLayout(context);
|
||||
topLayout.setLayoutDirection(direction);
|
||||
topLayout.setLayoutDirection(layoutDirection);
|
||||
mViewRoot = topLayout;
|
||||
topLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
try {
|
||||
NavigationBar navigationBar = new NavigationBar(context,
|
||||
hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
|
||||
params.isRtlSupported());
|
||||
navigationBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
mNavigationBarSize,
|
||||
LayoutParams.MATCH_PARENT));
|
||||
NavigationBar navigationBar = createNavigationBar(context,
|
||||
hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
|
||||
topLayout.addView(navigationBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
@@ -294,14 +291,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
|
||||
LinearLayout topLayout = new LinearLayout(context);
|
||||
topLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
topLayout.setLayoutDirection(direction);
|
||||
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(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
||||
layoutParams.weight = 1;
|
||||
topLayoutWidth, LayoutParams.MATCH_PARENT);
|
||||
topLayout.setLayoutParams(layoutParams);
|
||||
|
||||
// this is the case of soft buttons + vertical bar.
|
||||
@@ -320,12 +318,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
if (mStatusBarSize > 0) {
|
||||
// system bar
|
||||
try {
|
||||
StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
|
||||
direction, params.isRtlSupported());
|
||||
systemBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mStatusBarSize));
|
||||
topLayout.addView(systemBar);
|
||||
StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
|
||||
layoutDirection, params.isRtlSupported());
|
||||
topLayout.addView(statusBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
@@ -344,23 +339,16 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
// if the theme says no title/action bar, then the size will be 0
|
||||
if (mActionBarSize > 0) {
|
||||
try {
|
||||
FakeActionBar actionBar = new FakeActionBar(context,
|
||||
hardwareConfig.getDensity(),
|
||||
params.getAppLabel(), params.getAppIcon());
|
||||
actionBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mActionBarSize));
|
||||
ActionBarLayout actionBar = createActionBar(context, params);
|
||||
backgroundLayout.addView(actionBar);
|
||||
mContentRoot = (FrameLayout) actionBar.findViewById(android.R.id.content);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
} else if (mTitleBarSize > 0) {
|
||||
try {
|
||||
TitleBar titleBar = new TitleBar(context,
|
||||
TitleBar titleBar = createTitleBar(context,
|
||||
hardwareConfig.getDensity(), params.getAppLabel());
|
||||
titleBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mTitleBarSize));
|
||||
backgroundLayout.addView(titleBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
@@ -368,23 +356,21 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
}
|
||||
|
||||
// content frame
|
||||
mContentRoot = new FrameLayout(context);
|
||||
layoutParams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, 0);
|
||||
layoutParams.weight = 1;
|
||||
mContentRoot.setLayoutParams(layoutParams);
|
||||
backgroundLayout.addView(mContentRoot);
|
||||
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 (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
|
||||
mNavigationBarSize > 0) {
|
||||
// system bar
|
||||
try {
|
||||
NavigationBar navigationBar = new NavigationBar(context,
|
||||
hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
|
||||
params.isRtlSupported());
|
||||
navigationBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mNavigationBarSize));
|
||||
NavigationBar navigationBar = createNavigationBar(context,
|
||||
hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
|
||||
topLayout.addView(navigationBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
@@ -585,7 +571,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
mViewRoot.draw(mCanvas);
|
||||
}
|
||||
|
||||
mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode());
|
||||
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), false);
|
||||
|
||||
// success!
|
||||
return SUCCESS.createResult();
|
||||
@@ -1370,50 +1356,126 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
}
|
||||
}
|
||||
|
||||
private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) {
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// adjust the offset to this view.
|
||||
offset += view.getTop();
|
||||
|
||||
if (view == mContentRoot) {
|
||||
return visitAllChildren(mContentRoot, offset, setExtendedInfo);
|
||||
}
|
||||
|
||||
// otherwise, look for mContentRoot in the children
|
||||
if (view instanceof ViewGroup) {
|
||||
ViewGroup group = ((ViewGroup) view);
|
||||
|
||||
for (int i = 0; i < group.getChildCount(); i++) {
|
||||
List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset,
|
||||
setExtendedInfo);
|
||||
if (list != null) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a View and its children and generate a {@link ViewInfo} containing the
|
||||
* Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
|
||||
* bounds of all the views.
|
||||
*
|
||||
* @param view the root View
|
||||
* @param offset an offset for the view bounds.
|
||||
* @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
|
||||
* @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
|
||||
* content frame.
|
||||
*
|
||||
* @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
|
||||
*/
|
||||
private ViewInfo visit(View view, int offset, boolean setExtendedInfo) {
|
||||
private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
|
||||
boolean isContentFrame) {
|
||||
ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
|
||||
|
||||
if (view instanceof ViewGroup) {
|
||||
ViewGroup group = ((ViewGroup) view);
|
||||
result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
|
||||
setExtendedInfo, isContentFrame));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
|
||||
* containing the bounds of all the views. It also initializes the {@link mViewInfoList} with
|
||||
* the children of the {@code mContentRoot}.
|
||||
*
|
||||
* @param viewGroup the root View
|
||||
* @param offset an offset from the top for the content view frame.
|
||||
* @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
|
||||
* @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
|
||||
* content frame. {@code false} if the {@code ViewInfo} to be created is
|
||||
* part of the system decor.
|
||||
*/
|
||||
private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
|
||||
boolean setExtendedInfo, boolean isContentFrame) {
|
||||
if (viewGroup == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isContentFrame) {
|
||||
offset += viewGroup.getTop();
|
||||
}
|
||||
|
||||
int childCount = viewGroup.getChildCount();
|
||||
if (viewGroup == mContentRoot) {
|
||||
List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
|
||||
List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
|
||||
setExtendedInfo);
|
||||
childrenWithoutOffset.add(childViewInfo[0]);
|
||||
childrenWithOffset.add(childViewInfo[1]);
|
||||
}
|
||||
mViewInfoList = childrenWithOffset;
|
||||
return childrenWithoutOffset;
|
||||
} else {
|
||||
List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
|
||||
isContentFrame));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
|
||||
* bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
|
||||
* one with the {@code offset} and other without the {@code offset}. The offset is needed to
|
||||
* get the right bounds if the {@code ViewInfo} hierarchy is accessed from
|
||||
* {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
|
||||
* offset is not needed.
|
||||
*
|
||||
* @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
|
||||
* index 1 is with the offset.
|
||||
*/
|
||||
private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
|
||||
ViewInfo[] result = new ViewInfo[2];
|
||||
if (view == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result[0] = createViewInfo(view, 0, setExtendedInfo, true);
|
||||
result[1] = createViewInfo(view, offset, setExtendedInfo, true);
|
||||
if (view instanceof ViewGroup) {
|
||||
List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
|
||||
result[0].setChildren(children);
|
||||
result[1].setChildren(children);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
|
||||
* of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
|
||||
* set.
|
||||
* @param offset an offset for the view bounds. Used only if view is part of the content frame.
|
||||
*/
|
||||
private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
|
||||
boolean isContentFrame) {
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ViewInfo result = new ViewInfo(view.getClass().getName(),
|
||||
getContext().getViewKey(view),
|
||||
view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
|
||||
view, view.getLayoutParams());
|
||||
ViewInfo result;
|
||||
if (isContentFrame) {
|
||||
result = new ViewInfo(view.getClass().getName(),
|
||||
getContext().getViewKey(view),
|
||||
view.getLeft(), view.getTop() + offset, view.getRight(),
|
||||
view.getBottom() + offset, view, view.getLayoutParams());
|
||||
|
||||
} else {
|
||||
result = new SystemViewInfo(view.getClass().getName(),
|
||||
getContext().getViewKey(view),
|
||||
view.getLeft(), view.getTop(), view.getRight(),
|
||||
view.getBottom(), view, view.getLayoutParams());
|
||||
}
|
||||
|
||||
if (setExtendedInfo) {
|
||||
MarginLayoutParams marginParams = null;
|
||||
@@ -1428,39 +1490,67 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
marginParams != null ? marginParams.bottomMargin : 0);
|
||||
}
|
||||
|
||||
if (view instanceof ViewGroup) {
|
||||
ViewGroup group = ((ViewGroup) view);
|
||||
result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
|
||||
* containing the bounds of all the views.
|
||||
* @param view the root View
|
||||
* @param offset an offset for the view bounds.
|
||||
* @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
|
||||
*/
|
||||
private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
|
||||
boolean setExtendedInfo) {
|
||||
if (viewGroup == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ViewInfo> children = new ArrayList<ViewInfo>();
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
|
||||
private void invalidateRenderingSize() {
|
||||
mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the status bar with wifi and battery icons.
|
||||
*/
|
||||
private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
|
||||
boolean isRtlSupported) throws XmlPullParserException {
|
||||
StatusBar statusBar = new StatusBar(context, density,
|
||||
direction, isRtlSupported);
|
||||
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) throws XmlPullParserException {
|
||||
NavigationBar navigationBar = new NavigationBar(context,
|
||||
density, mNavigationBarOrientation, isRtl,
|
||||
isRtlSupported);
|
||||
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, Density density, String title)
|
||||
throws XmlPullParserException {
|
||||
TitleBar titleBar = new TitleBar(context, density, title);
|
||||
titleBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
|
||||
return titleBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the action bar. Also queries the project callback for missing information.
|
||||
*/
|
||||
private ActionBarLayout createActionBar(BridgeContext context, SessionParams params)
|
||||
throws XmlPullParserException {
|
||||
ActionBarLayout actionBar = new ActionBarLayout(context, params);
|
||||
actionBar.setLayoutParams(new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
return actionBar;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
return mImage;
|
||||
}
|
||||
@@ -1473,6 +1563,10 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
||||
return mViewInfoList;
|
||||
}
|
||||
|
||||
public List<ViewInfo> getSystemViewInfos() {
|
||||
return mSystemViewInfoList;
|
||||
}
|
||||
|
||||
public Map<String, String> getDefaultProperties(Object viewObject) {
|
||||
return getContext().getDefaultPropMap(viewObject);
|
||||
}
|
||||
|
||||
@@ -165,6 +165,9 @@ public final class ResourceHelper {
|
||||
* @param context the current context
|
||||
*/
|
||||
public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String stringValue = value.getValue();
|
||||
if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.ViewInfo;
|
||||
|
||||
public class SystemViewInfo extends ViewInfo {
|
||||
|
||||
public SystemViewInfo(String name, Object cookie, int left, int top,
|
||||
int right, int bottom) {
|
||||
super(name, cookie, left, top, right, bottom);
|
||||
}
|
||||
|
||||
public SystemViewInfo(String name, Object cookie, int left, int top,
|
||||
int right, int bottom, Object viewObject, Object layoutParamsObject) {
|
||||
super(name, cookie, left, top, right, bottom, viewObject,
|
||||
layoutParamsObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSystemView() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public class Main {
|
||||
"android.os.*", // for android.os.Handler
|
||||
"android.database.ContentObserver", // for Digital clock
|
||||
"com.android.i18n.phonenumbers.*", // for TextView with autolink attribute
|
||||
"com.android.internal.view.menu.ActionMenu",
|
||||
},
|
||||
excludeClasses,
|
||||
new String[] {
|
||||
|
||||
Reference in New Issue
Block a user