Merge "LayoutLib: render system/title/action bars." into honeycomb
This commit is contained in:
committed by
Android (Google) Code Review
commit
331e93e5a2
@@ -17,6 +17,8 @@ LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under,src)
|
||||
LOCAL_JAVA_RESOURCE_DIRS := resources
|
||||
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := \
|
||||
kxml2-2.3.0 \
|
||||
|
||||
11
tools/layoutlib/bridge/resources/bars/action_bar.xml
Normal file
11
tools/layoutlib/bridge/resources/bars/action_bar.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</merge>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 885 B |
12
tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
Normal file
12
tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text=" "/>
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</merge>
|
||||
20
tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
Normal file
20
tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</merge>
|
||||
7
tools/layoutlib/bridge/resources/bars/title_bar.xml
Normal file
7
tools/layoutlib/bridge/resources/bars/title_bar.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
</merge>
|
||||
@@ -18,6 +18,9 @@ package android.graphics;
|
||||
|
||||
import com.android.ide.common.rendering.api.LayoutLog;
|
||||
import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
|
||||
import com.android.ninepatch.NinePatch;
|
||||
import com.android.ninepatch.NinePatchChunk;
|
||||
import com.android.resources.Density;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
@@ -438,6 +441,8 @@ public class BitmapFactory {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean isNinePatch = is instanceof NinePatchInputStream;
|
||||
|
||||
// we need mark/reset to work properly
|
||||
|
||||
if (!is.markSupported()) {
|
||||
@@ -466,7 +471,29 @@ public class BitmapFactory {
|
||||
if (opts != null) {
|
||||
density = Density.getEnum(opts.inDensity);
|
||||
}
|
||||
bm = Bitmap_Delegate.createBitmap(is, true, density);
|
||||
|
||||
if (isNinePatch) {
|
||||
// load the bitmap as a nine patch
|
||||
NinePatch ninePatch = NinePatch.load(is, true /*is9Patch*/, false /*convert*/);
|
||||
|
||||
// get the bitmap and chunk objects.
|
||||
bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
|
||||
density);
|
||||
NinePatchChunk chunk = ninePatch.getChunk();
|
||||
|
||||
// put the chunk in the bitmap
|
||||
bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
|
||||
|
||||
// read the padding
|
||||
int[] padding = chunk.getPadding();
|
||||
outPadding.left = padding[0];
|
||||
outPadding.top = padding[1];
|
||||
outPadding.right = padding[2];
|
||||
outPadding.bottom = padding[3];
|
||||
} else {
|
||||
// load the bitmap directly.
|
||||
bm = Bitmap_Delegate.createBitmap(is, true, density);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
|
||||
|
||||
import com.android.ide.common.rendering.api.Capability;
|
||||
import com.android.ide.common.rendering.api.LayoutLog;
|
||||
import com.android.ide.common.rendering.api.Params;
|
||||
import com.android.ide.common.rendering.api.RenderParams;
|
||||
import com.android.ide.common.rendering.api.RenderSession;
|
||||
import com.android.ide.common.rendering.api.Result;
|
||||
import com.android.layoutlib.bridge.android.BridgeAssetManager;
|
||||
@@ -293,15 +293,15 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
|
||||
/**
|
||||
* Starts a layout session by inflating and rendering it. The method returns a
|
||||
* {@link ILayoutScene} on which further actions can be taken.
|
||||
* {@link RenderSession} on which further actions can be taken.
|
||||
*
|
||||
* @param params the {@link SceneParams} object with all the information necessary to create
|
||||
* @param params the {@link RenderParams} object with all the information necessary to create
|
||||
* the scene.
|
||||
* @return a new {@link ILayoutScene} object that contains the result of the layout.
|
||||
* @return a new {@link RenderSession} object that contains the result of the layout.
|
||||
* @since 5
|
||||
*/
|
||||
@Override
|
||||
public RenderSession createSession(Params params) {
|
||||
public RenderSession createSession(RenderParams params) {
|
||||
try {
|
||||
Result lastResult = SUCCESS.createResult();
|
||||
RenderSessionImpl scene = new RenderSessionImpl(params);
|
||||
@@ -331,10 +331,6 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void clearCaches(Object projectKey) {
|
||||
if (projectKey != null) {
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.android.layoutlib.bridge;
|
||||
|
||||
import com.android.ide.common.rendering.api.IAnimationListener;
|
||||
import com.android.ide.common.rendering.api.ILayoutPullParser;
|
||||
import com.android.ide.common.rendering.api.Params;
|
||||
import com.android.ide.common.rendering.api.RenderParams;
|
||||
import com.android.ide.common.rendering.api.RenderSession;
|
||||
import com.android.ide.common.rendering.api.Result;
|
||||
import com.android.ide.common.rendering.api.ViewInfo;
|
||||
@@ -128,7 +128,7 @@ public class BridgeRenderSession extends RenderSession {
|
||||
boolean isFrameworkAnimation, IAnimationListener listener) {
|
||||
try {
|
||||
Bridge.prepareThread();
|
||||
mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
|
||||
mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
|
||||
if (mLastResult.isSuccess()) {
|
||||
mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
|
||||
listener);
|
||||
@@ -150,7 +150,7 @@ public class BridgeRenderSession extends RenderSession {
|
||||
|
||||
try {
|
||||
Bridge.prepareThread();
|
||||
mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
|
||||
mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
|
||||
if (mLastResult.isSuccess()) {
|
||||
mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index,
|
||||
listener);
|
||||
@@ -176,7 +176,7 @@ public class BridgeRenderSession extends RenderSession {
|
||||
|
||||
try {
|
||||
Bridge.prepareThread();
|
||||
mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
|
||||
mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
|
||||
if (mLastResult.isSuccess()) {
|
||||
mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
|
||||
layoutParams, listener);
|
||||
@@ -197,7 +197,7 @@ public class BridgeRenderSession extends RenderSession {
|
||||
|
||||
try {
|
||||
Bridge.prepareThread();
|
||||
mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
|
||||
mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
|
||||
if (mLastResult.isSuccess()) {
|
||||
mLastResult = mSession.removeChild((View) childView, listener);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.ide.common.rendering.api.ResourceValue;
|
||||
import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.BridgeConstants;
|
||||
import com.android.layoutlib.bridge.impl.ResourceHelper;
|
||||
import com.android.ninepatch.NinePatch;
|
||||
import com.android.resources.ResourceType;
|
||||
import com.android.util.Pair;
|
||||
|
||||
@@ -57,6 +58,18 @@ public final class BridgeResources extends Resources {
|
||||
private IProjectCallback mProjectCallback;
|
||||
private boolean[] mPlatformResourceFlag = new boolean[1];
|
||||
|
||||
/**
|
||||
* Simpler wrapper around FileInputStream. This is used when the input stream represent
|
||||
* not a normal bitmap but a nine patch.
|
||||
* This is useful when the InputStream is created in a method but used in another that needs
|
||||
* to know whether this is 9-patch or not, such as BitmapFactory.
|
||||
*/
|
||||
public class NinePatchInputStream extends FileInputStream {
|
||||
public NinePatchInputStream(File file) throws FileNotFoundException {
|
||||
super(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes the static field {@link Resources#mSystem} which is used
|
||||
* by methods who get global resources using {@link Resources#getSystem()}.
|
||||
@@ -129,7 +142,7 @@ public final class BridgeResources extends Resources {
|
||||
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
|
||||
|
||||
if (value != null) {
|
||||
return ResourceHelper.getDrawable(value, mContext, value.isFramework());
|
||||
return ResourceHelper.getDrawable(value, mContext);
|
||||
}
|
||||
|
||||
// id was not found or not resolved. Throw a NotFoundException.
|
||||
@@ -165,44 +178,9 @@ public final class BridgeResources extends Resources {
|
||||
ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag);
|
||||
|
||||
if (resValue != null) {
|
||||
String value = resValue.getValue();
|
||||
if (value != null) {
|
||||
// first check if the value is a file (xml most likely)
|
||||
File f = new File(value);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
// let the framework inflate the ColorStateList from the XML file, by
|
||||
// providing an XmlPullParser
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
parser.setInput(new FileReader(f));
|
||||
|
||||
return ColorStateList.createFromXml(this,
|
||||
new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
|
||||
} catch (XmlPullParserException e) {
|
||||
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
|
||||
"Failed to configure parser for " + value, e, null /*data*/);
|
||||
// we'll return null below.
|
||||
} catch (Exception e) {
|
||||
// this is an error and not warning since the file existence is
|
||||
// checked before attempting to parse it.
|
||||
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
|
||||
"Failed to parse file " + value, e, null /*data*/);
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// try to load the color state list from an int
|
||||
try {
|
||||
int color = ResourceHelper.getColor(value);
|
||||
return ColorStateList.valueOf(color);
|
||||
} catch (NumberFormatException e) {
|
||||
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
|
||||
"Failed to convert " + value + " into a ColorStateList", e,
|
||||
null /*data*/);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext);
|
||||
if (stateList != null) {
|
||||
return stateList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,13 +540,19 @@ public final class BridgeResources extends Resources {
|
||||
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
|
||||
|
||||
if (value != null) {
|
||||
String v = value.getValue();
|
||||
String path = value.getValue();
|
||||
|
||||
if (v != null) {
|
||||
if (path != null) {
|
||||
// check this is a file
|
||||
File f = new File(value.getValue());
|
||||
File f = new File(path);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
// if it's a nine-patch return a custom input stream so that
|
||||
// other methods (mainly bitmap factory) can detect it's a 9-patch
|
||||
// and actually load it as a 9-patch instead of a normal bitmap
|
||||
if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
|
||||
return new NinePatchInputStream(f);
|
||||
}
|
||||
return new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
NotFoundException newE = new NotFoundException();
|
||||
@@ -590,9 +574,17 @@ public final class BridgeResources extends Resources {
|
||||
public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
|
||||
getValue(id, value, true);
|
||||
|
||||
File f = new File(value.string.toString());
|
||||
String path = value.string.toString();
|
||||
|
||||
File f = new File(path);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
// if it's a nine-patch return a custom input stream so that
|
||||
// other methods (mainly bitmap factory) can detect it's a 9-patch
|
||||
// and actually load it as a 9-patch instead of a normal bitmap
|
||||
if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
|
||||
return new NinePatchInputStream(f);
|
||||
}
|
||||
return new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
NotFoundException exception = new NotFoundException();
|
||||
|
||||
@@ -690,7 +690,7 @@ public final class BridgeTypedArray extends TypedArray {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
|
||||
return ResourceHelper.getDrawable(value, mContext);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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.ide.common.rendering.api.RenderResources;
|
||||
import com.android.ide.common.rendering.api.ResourceValue;
|
||||
import com.android.ide.common.rendering.api.StyleResourceValue;
|
||||
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.ResourceHelper;
|
||||
import com.android.resources.Density;
|
||||
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap_Delegate;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Base "bar" class for the window decor around the the edited layout.
|
||||
* This is basically an horizontal layout that loads a given layout on creation (it is read
|
||||
* through {@link Class#getResourceAsStream(String)}).
|
||||
*
|
||||
* The given layout should be a merge layout so that all the children belong to this class directly.
|
||||
*
|
||||
* It also provides a few utility methods to configure the content of the layout.
|
||||
*/
|
||||
abstract class CustomBar extends LinearLayout {
|
||||
|
||||
protected abstract TextView getStyleableTextView();
|
||||
|
||||
protected CustomBar(Context context, Density density, String layoutPath)
|
||||
throws XmlPullParserException {
|
||||
super(context);
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
setBackgroundColor(0xFF000000);
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
parser.setInput(
|
||||
getClass().getResourceAsStream(layoutPath),
|
||||
"UTF8");
|
||||
|
||||
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
|
||||
parser, (BridgeContext) context, false);
|
||||
|
||||
inflater.inflate(bridgeParser, this, true);
|
||||
}
|
||||
|
||||
protected void loadIcon(int index, String iconName, Density density) {
|
||||
View child = getChildAt(index);
|
||||
if (child instanceof ImageView) {
|
||||
ImageView imageView = (ImageView) child;
|
||||
|
||||
// bitmap url relative to this class
|
||||
String path = "/bars/" + density.getResourceValue() + "/" + iconName;
|
||||
|
||||
// create a bitmap
|
||||
Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
|
||||
|
||||
if (bitmap == null) {
|
||||
InputStream stream = getClass().getResourceAsStream(path);
|
||||
|
||||
if (stream != null) {
|
||||
try {
|
||||
bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
|
||||
Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
|
||||
} catch (IOException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmap != null) {
|
||||
BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
|
||||
imageView.setBackgroundDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadIcon(int index, String iconReference) {
|
||||
ResourceValue value = getResourceValue(iconReference);
|
||||
if (value != null) {
|
||||
View child = getChildAt(index);
|
||||
if (child instanceof ImageView) {
|
||||
ImageView imageView = (ImageView) child;
|
||||
|
||||
Drawable drawable = ResourceHelper.getDrawable(
|
||||
value, (BridgeContext) mContext);
|
||||
if (drawable != null) {
|
||||
imageView.setBackgroundDrawable(drawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected TextView setText(int index, String stringReference) {
|
||||
View child = getChildAt(index);
|
||||
if (child instanceof TextView) {
|
||||
TextView textView = (TextView) child;
|
||||
ResourceValue value = getResourceValue(stringReference);
|
||||
if (value != null) {
|
||||
textView.setText(value.getValue());
|
||||
} else {
|
||||
textView.setText(stringReference);
|
||||
}
|
||||
return textView;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void setStyle(String themeEntryName) {
|
||||
|
||||
BridgeContext bridgeContext = (BridgeContext) mContext;
|
||||
RenderResources res = bridgeContext.getRenderResources();
|
||||
|
||||
ResourceValue value = res.findItemInTheme(themeEntryName);
|
||||
value = res.resolveResValue(value);
|
||||
|
||||
if (value instanceof StyleResourceValue == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
StyleResourceValue style = (StyleResourceValue) value;
|
||||
|
||||
// get the background
|
||||
ResourceValue backgroundValue = res.findItemInStyle(style, "background");
|
||||
backgroundValue = res.resolveResValue(backgroundValue);
|
||||
if (backgroundValue != null) {
|
||||
Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
|
||||
if (d != null) {
|
||||
setBackgroundDrawable(d);
|
||||
}
|
||||
}
|
||||
|
||||
TextView textView = getStyleableTextView();
|
||||
if (textView != null) {
|
||||
// get the text style
|
||||
ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
|
||||
textStyleValue = res.resolveResValue(textStyleValue);
|
||||
if (textStyleValue instanceof StyleResourceValue) {
|
||||
StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
|
||||
|
||||
ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
|
||||
textSize = res.resolveResValue(textSize);
|
||||
|
||||
if (textSize != null) {
|
||||
TypedValue out = new TypedValue();
|
||||
if (ResourceHelper.stringToFloat(textSize.getValue(), out)) {
|
||||
textView.setTextSize(
|
||||
out.getDimension(bridgeContext.getResources().mMetrics));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
|
||||
textColor = res.resolveResValue(textColor);
|
||||
if (textColor != null) {
|
||||
ColorStateList stateList = ResourceHelper.getColorStateList(
|
||||
textColor, bridgeContext);
|
||||
if (stateList != null) {
|
||||
textView.setTextColor(stateList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ResourceValue getResourceValue(String reference) {
|
||||
BridgeContext bridgeContext = (BridgeContext) mContext;
|
||||
RenderResources res = bridgeContext.getRenderResources();
|
||||
|
||||
// find the resource
|
||||
ResourceValue value = res.findResValue(reference, false /*isFramework*/);
|
||||
|
||||
// resolve it if needed
|
||||
return res.resolveResValue(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.TextView;
|
||||
|
||||
public class FakeActionBar extends CustomBar {
|
||||
|
||||
private TextView mTextView;
|
||||
|
||||
public FakeActionBar(Context context, Density density, String label, String icon)
|
||||
throws XmlPullParserException {
|
||||
super(context, density, "/bars/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.
|
||||
loadIcon(0, icon);
|
||||
mTextView = setText(1, label);
|
||||
|
||||
setStyle("actionBarStyle");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getStyleableTextView() {
|
||||
return mTextView;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.TextView;
|
||||
|
||||
public class PhoneSystemBar extends CustomBar {
|
||||
|
||||
public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
|
||||
super(context, density, "/bars/tablet_system_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.
|
||||
// 0 is the spacer
|
||||
loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getStyleableTextView() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.TextView;
|
||||
|
||||
public class TabletSystemBar extends CustomBar {
|
||||
|
||||
public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
|
||||
super(context, density, "/bars/tablet_system_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.
|
||||
loadIcon(0, "ic_sysbar_back_default.png", density);
|
||||
loadIcon(1, "ic_sysbar_home_default.png", density);
|
||||
loadIcon(2, "ic_sysbar_recent_default.png", density);
|
||||
// 3 is the spacer
|
||||
loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getStyleableTextView() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.TextView;
|
||||
|
||||
public class TitleBar extends CustomBar {
|
||||
|
||||
private TextView mTextView;
|
||||
|
||||
public TitleBar(Context context, Density density, String label)
|
||||
throws XmlPullParserException {
|
||||
super(context, density, "/bars/title_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.
|
||||
mTextView = setText(0, label);
|
||||
|
||||
setStyle("windowTitleBackgroundStyle");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextView getStyleableTextView() {
|
||||
return mTextView;
|
||||
}
|
||||
}
|
||||
@@ -29,14 +29,13 @@ import com.android.ide.common.rendering.api.IAnimationListener;
|
||||
import com.android.ide.common.rendering.api.ILayoutPullParser;
|
||||
import com.android.ide.common.rendering.api.IProjectCallback;
|
||||
import com.android.ide.common.rendering.api.LayoutLog;
|
||||
import com.android.ide.common.rendering.api.Params;
|
||||
import com.android.ide.common.rendering.api.RenderParams;
|
||||
import com.android.ide.common.rendering.api.RenderResources;
|
||||
import com.android.ide.common.rendering.api.RenderSession;
|
||||
import com.android.ide.common.rendering.api.ResourceValue;
|
||||
import com.android.ide.common.rendering.api.Result;
|
||||
import com.android.ide.common.rendering.api.StyleResourceValue;
|
||||
import com.android.ide.common.rendering.api.ViewInfo;
|
||||
import com.android.ide.common.rendering.api.Params.RenderingMode;
|
||||
import com.android.ide.common.rendering.api.RenderParams.RenderingMode;
|
||||
import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
|
||||
import com.android.ide.common.rendering.api.Result.Status;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
@@ -47,11 +46,16 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
|
||||
import com.android.layoutlib.bridge.android.BridgeWindow;
|
||||
import com.android.layoutlib.bridge.android.BridgeWindowSession;
|
||||
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
|
||||
import com.android.resources.Density;
|
||||
import com.android.layoutlib.bridge.bars.FakeActionBar;
|
||||
import com.android.layoutlib.bridge.bars.PhoneSystemBar;
|
||||
import com.android.layoutlib.bridge.bars.TabletSystemBar;
|
||||
import com.android.layoutlib.bridge.bars.TitleBar;
|
||||
import com.android.resources.ResourceType;
|
||||
import com.android.resources.ScreenSize;
|
||||
import com.android.util.Pair;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorInflater;
|
||||
import android.animation.LayoutTransition;
|
||||
@@ -105,7 +109,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
*/
|
||||
private static BridgeContext sCurrentContext = null;
|
||||
|
||||
private final Params mParams;
|
||||
private final RenderParams mParams;
|
||||
|
||||
// scene state
|
||||
private RenderSession mScene;
|
||||
@@ -113,17 +117,18 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
private BridgeXmlBlockParser mBlockParser;
|
||||
private BridgeInflater mInflater;
|
||||
private ResourceValue mWindowBackground;
|
||||
private FrameLayout mViewRoot;
|
||||
private ViewGroup mViewRoot;
|
||||
private FrameLayout mContentRoot;
|
||||
private Canvas mCanvas;
|
||||
private int mMeasuredScreenWidth = -1;
|
||||
private int mMeasuredScreenHeight = -1;
|
||||
private boolean mIsAlphaChannelImage = true;
|
||||
private boolean mIsAlphaChannelImage;
|
||||
private boolean mWindowIsFloating;
|
||||
|
||||
private int mStatusBarSize;
|
||||
private int mTopBarSize;
|
||||
private int mSystemBarSize;
|
||||
private int mTopOffset;
|
||||
private int mTotalBarSize;
|
||||
private int mTitleBarSize;
|
||||
private int mActionBarSize;
|
||||
|
||||
|
||||
// information being returned through the API
|
||||
@@ -146,9 +151,9 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
*
|
||||
* @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
|
||||
*/
|
||||
public RenderSessionImpl(Params params) {
|
||||
public RenderSessionImpl(RenderParams params) {
|
||||
// copy the params.
|
||||
mParams = new Params(params);
|
||||
mParams = new RenderParams(params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,8 +177,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
|
||||
// setup the display Metrics.
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
metrics.densityDpi = mParams.getDensity();
|
||||
metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
|
||||
metrics.densityDpi = mParams.getDensity().getDpiValue();
|
||||
metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
|
||||
metrics.scaledDensity = metrics.density;
|
||||
metrics.widthPixels = mParams.getScreenWidth();
|
||||
metrics.heightPixels = mParams.getScreenHeight();
|
||||
@@ -190,17 +195,16 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
mIsAlphaChannelImage = getBooleanThemeValue(resources,
|
||||
"windowIsFloating", true /*defaultValue*/);
|
||||
|
||||
mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
|
||||
true /*defaultValue*/);
|
||||
|
||||
setUp();
|
||||
|
||||
findBackground(resources);
|
||||
findStatusBar(resources, metrics);
|
||||
findTopBar(resources, metrics);
|
||||
findActionBar(resources, metrics);
|
||||
findSystemBar(resources, metrics);
|
||||
|
||||
mTopOffset = mStatusBarSize + mTopBarSize;
|
||||
mTotalBarSize = mTopOffset + mSystemBarSize;
|
||||
|
||||
// build the inflater and parser.
|
||||
mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
|
||||
mContext.setBridgeInflater(mInflater);
|
||||
@@ -353,13 +357,100 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
|
||||
try {
|
||||
|
||||
mViewRoot = new FrameLayout(mContext);
|
||||
if (mWindowIsFloating || mParams.isForceNoDecor()) {
|
||||
mViewRoot = mContentRoot = new FrameLayout(mContext);
|
||||
} else {
|
||||
/*
|
||||
* we're creating the following layout
|
||||
*
|
||||
+-------------------------------------------------+
|
||||
| System bar (only in phone UI) |
|
||||
+-------------------------------------------------+
|
||||
| Title/Action bar (optional) |
|
||||
+-------------------------------------------------+
|
||||
| Content, vertical extending |
|
||||
| |
|
||||
+-------------------------------------------------+
|
||||
| System bar (only in tablet UI) |
|
||||
+-------------------------------------------------+
|
||||
|
||||
*/
|
||||
|
||||
LinearLayout topLayout = new LinearLayout(mContext);
|
||||
mViewRoot = topLayout;
|
||||
topLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
if (mStatusBarSize > 0) {
|
||||
// system bar
|
||||
try {
|
||||
PhoneSystemBar systemBar = new PhoneSystemBar(mContext,
|
||||
mParams.getDensity());
|
||||
systemBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mStatusBarSize));
|
||||
topLayout.addView(systemBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if the theme says no title/action bar, then the size will be 0
|
||||
if (mActionBarSize > 0) {
|
||||
try {
|
||||
FakeActionBar actionBar = new FakeActionBar(mContext,
|
||||
mParams.getDensity(),
|
||||
mParams.getAppLabel(), mParams.getAppIcon());
|
||||
actionBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mActionBarSize));
|
||||
topLayout.addView(actionBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
} else if (mTitleBarSize > 0) {
|
||||
try {
|
||||
TitleBar titleBar = new TitleBar(mContext,
|
||||
mParams.getDensity(), mParams.getAppLabel());
|
||||
titleBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mTitleBarSize));
|
||||
topLayout.addView(titleBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// content frame
|
||||
mContentRoot = new FrameLayout(mContext);
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
||||
params.weight = 1;
|
||||
mContentRoot.setLayoutParams(params);
|
||||
topLayout.addView(mContentRoot);
|
||||
|
||||
if (mSystemBarSize > 0) {
|
||||
// system bar
|
||||
try {
|
||||
TabletSystemBar systemBar = new TabletSystemBar(mContext,
|
||||
mParams.getDensity());
|
||||
systemBar.setLayoutParams(
|
||||
new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, mSystemBarSize));
|
||||
topLayout.addView(systemBar);
|
||||
} catch (XmlPullParserException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sets the project callback (custom view loader) to the fragment delegate so that
|
||||
// it can instantiate the custom Fragment.
|
||||
Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
|
||||
|
||||
View view = mInflater.inflate(mBlockParser, mViewRoot);
|
||||
View view = mInflater.inflate(mBlockParser, mContentRoot);
|
||||
|
||||
Fragment_Delegate.setProjectCallback(null);
|
||||
|
||||
@@ -377,9 +468,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
|
||||
// get the background drawable
|
||||
if (mWindowBackground != null) {
|
||||
Drawable d = ResourceHelper.getDrawable(mWindowBackground,
|
||||
mContext, true /* isFramework */);
|
||||
mViewRoot.setBackgroundDrawable(d);
|
||||
Drawable d = ResourceHelper.getDrawable(mWindowBackground, mContext);
|
||||
mContentRoot.setBackgroundDrawable(d);
|
||||
}
|
||||
|
||||
return SUCCESS.createResult();
|
||||
@@ -408,8 +498,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
* @throws IllegalStateException if the current context is different than the one owned by
|
||||
* the scene, or if {@link #acquire(long)} was not called.
|
||||
*
|
||||
* @see SceneParams#getRenderingMode()
|
||||
* @see LayoutScene#render(long)
|
||||
* @see RenderParams#getRenderingMode()
|
||||
* @see RenderSession#render(long)
|
||||
*/
|
||||
public Result render(boolean freshRender) {
|
||||
checkLock();
|
||||
@@ -428,7 +518,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
if (mMeasuredScreenWidth == -1) {
|
||||
newRenderSize = true;
|
||||
mMeasuredScreenWidth = mParams.getScreenWidth();
|
||||
mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize;
|
||||
mMeasuredScreenHeight = mParams.getScreenHeight();
|
||||
|
||||
if (renderingMode != RenderingMode.NORMAL) {
|
||||
// measure the full size needed by the layout.
|
||||
@@ -476,11 +566,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
if (mParams.getImageFactory() != null) {
|
||||
mImage = mParams.getImageFactory().getImage(
|
||||
mMeasuredScreenWidth,
|
||||
mMeasuredScreenHeight + mTotalBarSize);
|
||||
mMeasuredScreenHeight);
|
||||
} else {
|
||||
mImage = new BufferedImage(
|
||||
mMeasuredScreenWidth,
|
||||
mMeasuredScreenHeight + mTotalBarSize,
|
||||
mMeasuredScreenHeight,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
newImage = true;
|
||||
}
|
||||
@@ -491,46 +581,26 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
Graphics2D gc = mImage.createGraphics();
|
||||
gc.setColor(new Color(mParams.getOverrideBgColor(), true));
|
||||
gc.setComposite(AlphaComposite.Src);
|
||||
gc.fillRect(0, 0, mMeasuredScreenWidth,
|
||||
mMeasuredScreenHeight + mTotalBarSize);
|
||||
gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
|
||||
gc.dispose();
|
||||
}
|
||||
|
||||
// create an Android bitmap around the BufferedImage
|
||||
Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
|
||||
true /*isMutable*/,
|
||||
Density.getEnum(mParams.getDensity()));
|
||||
true /*isMutable*/, mParams.getDensity());
|
||||
|
||||
// create a Canvas around the Android bitmap
|
||||
mCanvas = new Canvas(bitmap);
|
||||
mCanvas.setDensity(mParams.getDensity());
|
||||
mCanvas.translate(0, mTopOffset);
|
||||
mCanvas.setDensity(mParams.getDensity().getDpiValue());
|
||||
}
|
||||
|
||||
if (freshRender && newImage == false) {
|
||||
Graphics2D gc = mImage.createGraphics();
|
||||
gc.setComposite(AlphaComposite.Src);
|
||||
|
||||
if (mStatusBarSize > 0) {
|
||||
gc.setColor(new Color(0xFF3C3C3C, true));
|
||||
gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize);
|
||||
}
|
||||
|
||||
if (mTopBarSize > 0) {
|
||||
gc.setColor(new Color(0xFF7F7F7F, true));
|
||||
gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset);
|
||||
}
|
||||
|
||||
// erase the rest
|
||||
gc.setColor(new Color(0x00000000, true));
|
||||
gc.fillRect(0, mTopOffset,
|
||||
mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset);
|
||||
|
||||
if (mSystemBarSize > 0) {
|
||||
gc.setColor(new Color(0xFF3C3C3C, true));
|
||||
gc.fillRect(0, mMeasuredScreenHeight + mTopOffset,
|
||||
mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize);
|
||||
}
|
||||
gc.fillRect(0, 0,
|
||||
mMeasuredScreenWidth, mMeasuredScreenHeight);
|
||||
|
||||
// done
|
||||
gc.dispose();
|
||||
@@ -538,7 +608,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
|
||||
mViewRoot.draw(mCanvas);
|
||||
|
||||
mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset);
|
||||
mViewInfoList = startVisitingViews(mViewRoot, 0);
|
||||
|
||||
// success!
|
||||
return SUCCESS.createResult();
|
||||
@@ -561,7 +631,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
* @throws IllegalStateException if the current context is different than the one owned by
|
||||
* the scene, or if {@link #acquire(long)} was not called.
|
||||
*
|
||||
* @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
|
||||
* @see RenderSession#animate(Object, String, boolean, IAnimationListener)
|
||||
*/
|
||||
public Result animate(Object targetObject, String animationName,
|
||||
boolean isFrameworkAnimation, IAnimationListener listener) {
|
||||
@@ -617,7 +687,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
* @throws IllegalStateException if the current context is different than the one owned by
|
||||
* the scene, or if {@link #acquire(long)} was not called.
|
||||
*
|
||||
* @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
|
||||
* @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
|
||||
*/
|
||||
public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
|
||||
final int index, IAnimationListener listener) {
|
||||
@@ -696,7 +766,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
* @throws IllegalStateException if the current context is different than the one owned by
|
||||
* the scene, or if {@link #acquire(long)} was not called.
|
||||
*
|
||||
* @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
|
||||
* @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
|
||||
*/
|
||||
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
|
||||
Map<String, String> layoutParamsMap, final IAnimationListener listener) {
|
||||
@@ -892,7 +962,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
* @throws IllegalStateException if the current context is different than the one owned by
|
||||
* the scene, or if {@link #acquire(long)} was not called.
|
||||
*
|
||||
* @see LayoutScene#removeChild(Object, IAnimationListener)
|
||||
* @see RenderSession#removeChild(Object, IAnimationListener)
|
||||
*/
|
||||
public Result removeChild(final View childView, IAnimationListener listener) {
|
||||
checkLock();
|
||||
@@ -989,40 +1059,12 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
return mParams.getConfigScreenSize() == ScreenSize.XLARGE;
|
||||
}
|
||||
|
||||
private boolean isHCApp() {
|
||||
RenderResources resources = mContext.getRenderResources();
|
||||
|
||||
// the app must say it targets 11+ and the theme name must extend Theme.Holo or
|
||||
// Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light)
|
||||
if (mParams.getTargetSdkVersion() < 11) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StyleResourceValue currentTheme = resources.getCurrentTheme();
|
||||
StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/);
|
||||
|
||||
if (currentTheme == holoTheme ||
|
||||
resources.themeIsParentOf(holoTheme, currentTheme)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light",
|
||||
true /*frameworkTheme*/);
|
||||
|
||||
if (currentTheme == holoLightTheme ||
|
||||
resources.themeIsParentOf(holoLightTheme, currentTheme)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
|
||||
if (isTabletUi() == false) {
|
||||
boolean windowFullscreen = getBooleanThemeValue(resources,
|
||||
"windowFullscreen", false /*defaultValue*/);
|
||||
|
||||
if (windowFullscreen == false) {
|
||||
if (windowFullscreen == false && mWindowIsFloating == false) {
|
||||
// default value
|
||||
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
|
||||
|
||||
@@ -1041,20 +1083,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void findTopBar(RenderResources resources, DisplayMetrics metrics) {
|
||||
boolean windowIsFloating = getBooleanThemeValue(resources,
|
||||
"windowIsFloating", true /*defaultValue*/);
|
||||
|
||||
if (windowIsFloating == false) {
|
||||
if (isHCApp()) {
|
||||
findActionBar(resources, metrics);
|
||||
} else {
|
||||
findTitleBar(resources, metrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
|
||||
if (mWindowIsFloating) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean windowActionBar = getBooleanThemeValue(resources,
|
||||
"windowActionBar", true /*defaultValue*/);
|
||||
|
||||
@@ -1062,7 +1095,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
if (windowActionBar) {
|
||||
|
||||
// default size of the window title bar
|
||||
mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
|
||||
mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
|
||||
|
||||
// get value from the theme.
|
||||
ResourceValue value = resources.findItemInTheme("actionBarSize");
|
||||
@@ -1075,44 +1108,43 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
|
||||
if (typedValue != null) {
|
||||
// compute the pixel value based on the display metrics
|
||||
mTopBarSize = (int)typedValue.getDimension(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 /*defaultValue*/);
|
||||
|
||||
private void findTitleBar(RenderResources resources, DisplayMetrics metrics) {
|
||||
boolean windowNoTitle = getBooleanThemeValue(resources,
|
||||
"windowNoTitle", false /*defaultValue*/);
|
||||
if (windowNoTitle == false) {
|
||||
|
||||
if (windowNoTitle == false) {
|
||||
// default size of the window title bar
|
||||
mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
|
||||
|
||||
// default size of the window title bar
|
||||
mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
|
||||
// get value from the theme.
|
||||
ResourceValue value = resources.findItemInTheme("windowTitleSize");
|
||||
|
||||
// get value from the theme.
|
||||
ResourceValue value = resources.findItemInTheme("windowTitleSize");
|
||||
// resolve it
|
||||
value = resources.resolveResValue(value);
|
||||
|
||||
// resolve it
|
||||
value = resources.resolveResValue(value);
|
||||
|
||||
if (value != null) {
|
||||
// get the numerical value, if available
|
||||
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
|
||||
if (typedValue != null) {
|
||||
// compute the pixel value based on the display metrics
|
||||
mTopBarSize = (int)typedValue.getDimension(metrics);
|
||||
if (value != null) {
|
||||
// get the numerical value, if available
|
||||
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
|
||||
if (typedValue != null) {
|
||||
// compute the pixel value based on the display metrics
|
||||
mTitleBarSize = (int)typedValue.getDimension(metrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
|
||||
if (isTabletUi() && getBooleanThemeValue(
|
||||
resources, "windowIsFloating", true /*defaultValue*/) == false) {
|
||||
if (isTabletUi() && mWindowIsFloating == false) {
|
||||
|
||||
// default value
|
||||
mSystemBarSize = 56; // ??
|
||||
mSystemBarSize = 48; // ??
|
||||
|
||||
// get the real value
|
||||
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
|
||||
@@ -1244,40 +1276,71 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private List<ViewInfo> startVisitingViews(View view, int offset) {
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// adjust the offset to this view.
|
||||
offset += view.getTop();
|
||||
|
||||
if (view == mContentRoot) {
|
||||
return visitAllChildren(mContentRoot, offset);
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (list != null) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a View and its children and generate a {@link ViewInfo} containing the
|
||||
* bounds of all the views.
|
||||
* @param view the root View
|
||||
* @param context the context.
|
||||
* @param offset an offset for the view bounds.
|
||||
*/
|
||||
private ViewInfo visit(View view, BridgeContext context, int offset) {
|
||||
private ViewInfo visit(View view, int offset) {
|
||||
if (view == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ViewInfo result = new ViewInfo(view.getClass().getName(),
|
||||
context.getViewKey(view),
|
||||
mContext.getViewKey(view),
|
||||
view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
|
||||
view, view.getLayoutParams());
|
||||
|
||||
if (view instanceof ViewGroup) {
|
||||
ViewGroup group = ((ViewGroup) view);
|
||||
result.setChildren(visitAllChildren(group, context, 0 /*offset*/));
|
||||
result.setChildren(visitAllChildren(group, 0 /*offset*/));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context,
|
||||
int offset) {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) {
|
||||
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), context, offset));
|
||||
children.add(visit(viewGroup.getChildAt(i), offset));
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.impl;
|
||||
|
||||
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
|
||||
import com.android.ide.common.rendering.api.LayoutLog;
|
||||
import com.android.ide.common.rendering.api.RenderResources;
|
||||
import com.android.ide.common.rendering.api.ResourceValue;
|
||||
import com.android.layoutlib.bridge.Bridge;
|
||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||
@@ -28,7 +29,9 @@ import com.android.resources.Density;
|
||||
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap_Delegate;
|
||||
import android.graphics.NinePatch_Delegate;
|
||||
@@ -108,19 +111,63 @@ public final class ResourceHelper {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
|
||||
public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
|
||||
String value = resValue.getValue();
|
||||
if (value != null) {
|
||||
// first check if the value is a file (xml most likely)
|
||||
File f = new File(value);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
// let the framework inflate the ColorStateList from the XML file, by
|
||||
// providing an XmlPullParser
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
||||
parser.setInput(new FileReader(f));
|
||||
|
||||
return ColorStateList.createFromXml(context.getResources(),
|
||||
new BridgeXmlBlockParser(parser, context, resValue.isFramework()));
|
||||
} catch (XmlPullParserException e) {
|
||||
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
|
||||
"Failed to configure parser for " + value, e, null /*data*/);
|
||||
// we'll return null below.
|
||||
} catch (Exception e) {
|
||||
// this is an error and not warning since the file existence is
|
||||
// checked before attempting to parse it.
|
||||
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
|
||||
"Failed to parse file " + value, e, null /*data*/);
|
||||
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// try to load the color state list from an int
|
||||
try {
|
||||
int color = ResourceHelper.getColor(value);
|
||||
return ColorStateList.valueOf(color);
|
||||
} catch (NumberFormatException e) {
|
||||
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
|
||||
"Failed to convert " + value + " into a ColorStateList", e,
|
||||
null /*data*/);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a drawable from the given value.
|
||||
* @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
|
||||
* or an hexadecimal color
|
||||
* @param context
|
||||
* @param isFramework indicates whether the resource is a framework resources.
|
||||
* Framework resources are cached, and loaded only once.
|
||||
* @param context the current context
|
||||
*/
|
||||
public static Drawable getDrawable(ResourceValue value, BridgeContext context,
|
||||
boolean isFramework) {
|
||||
public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
|
||||
Drawable d = null;
|
||||
|
||||
String stringValue = value.getValue();
|
||||
if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String lowerCaseValue = stringValue.toLowerCase();
|
||||
|
||||
@@ -129,9 +176,9 @@ public final class ResourceHelper {
|
||||
if (file.isFile()) {
|
||||
// see if we still have both the chunk and the bitmap in the caches
|
||||
NinePatchChunk chunk = Bridge.getCached9Patch(stringValue,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
|
||||
// if either chunk or bitmap is null, then we reload the 9-patch file.
|
||||
if (chunk == null || bitmap == null) {
|
||||
@@ -143,7 +190,7 @@ public final class ResourceHelper {
|
||||
chunk = ninePatch.getChunk();
|
||||
|
||||
Bridge.setCached9Patch(stringValue, chunk,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
}
|
||||
|
||||
if (bitmap == null) {
|
||||
@@ -158,7 +205,7 @@ public final class ResourceHelper {
|
||||
density);
|
||||
|
||||
Bridge.setCachedBitmap(stringValue, bitmap,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
@@ -192,7 +239,7 @@ public final class ResourceHelper {
|
||||
parser.setInput(new FileReader(f));
|
||||
|
||||
d = Drawable.createFromXml(context.getResources(),
|
||||
new BridgeXmlBlockParser(parser, context, isFramework));
|
||||
new BridgeXmlBlockParser(parser, context, value.isFramework()));
|
||||
return d;
|
||||
} catch (Exception e) {
|
||||
// this is an error and not warning since the file existence is checked before
|
||||
@@ -212,7 +259,7 @@ public final class ResourceHelper {
|
||||
if (bmpFile.isFile()) {
|
||||
try {
|
||||
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
|
||||
if (bitmap == null) {
|
||||
Density density = Density.MEDIUM;
|
||||
@@ -223,7 +270,7 @@ public final class ResourceHelper {
|
||||
bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
|
||||
density);
|
||||
Bridge.setCachedBitmap(stringValue, bitmap,
|
||||
isFramework ? null : context.getProjectKey());
|
||||
value.isFramework() ? null : context.getProjectKey());
|
||||
}
|
||||
|
||||
return new BitmapDrawable(context.getResources(), bitmap);
|
||||
|
||||
Reference in New Issue
Block a user