diff options
author | Xavier Ducrohet <xav@android.com> | 2011-02-06 10:58:16 -0800 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2011-02-06 10:58:16 -0800 |
commit | 13bdc3355c781dc2614f2810a42d3a9e73f5bed9 (patch) | |
tree | b40424e57a6011ff0b0febf0fa39a13f6bfb0269 /tools/layoutlib/bridge | |
parent | fd18f573280bbbcc549b35b548580a562bd960e2 (diff) | |
download | frameworks_base-13bdc3355c781dc2614f2810a42d3a9e73f5bed9.zip frameworks_base-13bdc3355c781dc2614f2810a42d3a9e73f5bed9.tar.gz frameworks_base-13bdc3355c781dc2614f2810a42d3a9e73f5bed9.tar.bz2 |
LayoutLib: improved rendering for system/title/action bars.
Change-Id: I926531e9ad4a7b98e04e23cac3837794f7c89449
Diffstat (limited to 'tools/layoutlib/bridge')
13 files changed, 250 insertions, 131 deletions
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml index cd99a09..51983f2 100644 --- a/tools/layoutlib/bridge/resources/bars/action_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/action_bar.xml @@ -2,10 +2,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"/> + android:layout_width="wrap_content"/> <TextView android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center"/> + android:layout_height="wrap_content"/> </merge> diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png Binary files differnew file mode 100644 index 0000000..bd44b52 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png Binary files differnew file mode 100644 index 0000000..a4be298 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png Binary files differnew file mode 100644 index 0000000..eb7c1a4 --- /dev/null +++ b/tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml index 29df909..5211b0a 100644 --- a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml @@ -3,10 +3,11 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_weight="1" - android:text=" "/> + android:layout_weight="1"/> <ImageView android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_gravity="center"/> + android:layout_width="wrap_content"/> + <ImageView + android:layout_height="wrap_content" + android:layout_width="wrap_content"/> </merge> diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml index 8a3b87a..c5acddb 100644 --- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml @@ -15,6 +15,10 @@ android:layout_weight="1"/> <ImageView android:layout_height="wrap_content" + android:layout_width="wrap_content"/> + <ImageView + android:layout_height="wrap_content" android:layout_width="wrap_content" - android:layout_gravity="center"/> + android:layout_marginLeft="3dip" + android:layout_marginRight="15dip"/> </merge> diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml index 29fcc4b..76d78d9 100644 --- a/tools/layoutlib/bridge/resources/bars/title_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/title_bar.xml @@ -2,6 +2,5 @@ <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"/> + android:layout_height="wrap_content"/> </merge> diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java index 44b14dc..c4fffc8 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java @@ -40,6 +40,46 @@ import java.io.InputStream; */ /*package*/ class BitmapFactory_Delegate { + // ------ Java delegates ------ + + /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { + if (bm == null || opts == null) { + return bm; + } + + final int density = opts.inDensity; + if (density == 0) { + return bm; + } + + bm.setDensity(density); + final int targetDensity = opts.inTargetDensity; + if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { + return bm; + } + + byte[] np = bm.getNinePatchChunk(); + final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); + // DELEGATE CHANGE: never scale 9-patch + if (opts.inScaled && isNinePatch == false) { + float scale = targetDensity / (float)density; + // TODO: This is very inefficient and should be done in native by Skia + final Bitmap oldBitmap = bm; + bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f), + (int) (bm.getHeight() * scale + 0.5f), true); + oldBitmap.recycle(); + + if (isNinePatch) { + np = nativeScaleNinePatch(np, scale, outPadding); + bm.setNinePatchChunk(np); + } + bm.setDensity(targetDensity); + } + + return bm; + } + + // ------ Native Delegates ------ /*package*/ static void nativeSetDefaultConfig(int nativeConfig) { @@ -107,7 +147,8 @@ import java.io.InputStream; } /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) { - // don't scale for now. + // don't scale for now. This should not be called anyway since we re-implement + // BitmapFactory.finishDecode(); return chunk; } diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java index 7a6da95..61ed71e 100644 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -91,6 +91,50 @@ public final class NinePatch_Delegate { return array; } + /** + * Returns a {@link NinePatchChunk} object for the given serialized representation. + * + * If the chunk is present in the cache then the object from the cache is returned, otherwise + * the array is deserialized into a {@link NinePatchChunk} object. + * + * @param array the serialized representation of the chunk. + * @return the NinePatchChunk or null if deserialization failed. + */ + public static NinePatchChunk getChunk(byte[] array) { + SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); + NinePatchChunk chunk = chunkRef.get(); + if (chunk == null) { + ByteArrayInputStream bais = new ByteArrayInputStream(array); + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(bais); + chunk = (NinePatchChunk) ois.readObject(); + + // put back the chunk in the cache + if (chunk != null) { + sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); + } + } catch (IOException e) { + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Failed to deserialize NinePatchChunk content.", e, null /*data*/); + return null; + } catch (ClassNotFoundException e) { + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Failed to deserialize NinePatchChunk class.", e, null /*data*/); + return null; + } finally { + if (ois != null) { + try { + ois.close(); + } catch (IOException e) { + } + } + } + } + + return chunk; + } + // ---- native methods ---- /*package*/ static boolean isNinePatchChunk(byte[] chunk) { @@ -173,47 +217,5 @@ public final class NinePatch_Delegate { // ---- Private Helper methods ---- - /** - * Returns a {@link NinePatchChunk} object for the given serialized representation. - * - * If the chunk is present in the cache then the object from the cache is returned, otherwise - * the array is deserialized into a {@link NinePatchChunk} object. - * - * @param array the serialized representation of the chunk. - * @return the NinePatchChunk or null if deserialization failed. - */ - private static NinePatchChunk getChunk(byte[] array) { - SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); - NinePatchChunk chunk = chunkRef.get(); - if (chunk == null) { - ByteArrayInputStream bais = new ByteArrayInputStream(array); - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(bais); - chunk = (NinePatchChunk) ois.readObject(); - - // put back the chunk in the cache - if (chunk != null) { - sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); - } - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk content.", e, null /*data*/); - return null; - } catch (ClassNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk class.", e, null /*data*/); - return null; - } finally { - if (ois != null) { - try { - ois.close(); - } catch (IOException e) { - } - } - } - } - return chunk; - } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index f039994..70c507c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -24,6 +24,7 @@ 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 com.android.resources.ResourceType; import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; @@ -36,6 +37,7 @@ import android.graphics.Bitmap_Delegate; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.TypedValue; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -62,6 +64,7 @@ abstract class CustomBar extends LinearLayout { throws XmlPullParserException { super(context); setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.CENTER_VERTICAL); setBackgroundColor(0xFF000000); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( @@ -79,33 +82,58 @@ abstract class CustomBar extends LinearLayout { inflater.inflate(bridgeParser, this, true); } + private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut, + boolean tryOtherDensities) { + // current density + Density density = densityInOut[0]; + + // bitmap url relative to this class + pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName; + + InputStream stream = getClass().getResourceAsStream(pathOut[0]); + if (stream == null && tryOtherDensities) { + for (Density d : Density.values()) { + if (d != density) { + densityInOut[0] = d; + stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/); + if (stream != null) { + return stream; + } + } + } + } + + return stream; + } + 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); + String[] pathOut = new String[1]; + Density[] densityInOut = new Density[] { density }; + InputStream stream = getIcon(iconName, densityInOut, pathOut, + true /*tryOtherDensities*/); + density = densityInOut[0]; - if (stream != null) { + if (stream != null) { + // look for a cached bitmap + Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/); + if (bitmap == null) { try { bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); - Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/); + Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/); } catch (IOException e) { return; } } - } - if (bitmap != null) { - BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap); - imageView.setBackgroundDrawable(drawable); + if (bitmap != null) { + BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), + bitmap); + imageView.setBackgroundDrawable(drawable); + } } } } @@ -113,17 +141,37 @@ abstract class CustomBar extends LinearLayout { 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; + loadIcon(index, value); + } + } - Drawable drawable = ResourceHelper.getDrawable( - value, (BridgeContext) mContext); - if (drawable != null) { - imageView.setBackgroundDrawable(drawable); - } + protected Drawable loadIcon(int index, ResourceType type, String name) { + BridgeContext bridgeContext = (BridgeContext) mContext; + RenderResources res = bridgeContext.getRenderResources(); + + // find the resource + ResourceValue value = res.getFrameworkResource(type, name); + + // resolve it if needed + value = res.resolveResValue(value); + return loadIcon(index, value); + } + + private Drawable loadIcon(int index, ResourceValue value) { + 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); } + + return drawable; } + + return null; } protected TextView setText(int index, String stringReference) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java index 92615dc..e3022b4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java @@ -17,10 +17,14 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; +import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LevelListDrawable; +import android.view.Gravity; import android.widget.TextView; public class PhoneSystemBar extends CustomBar { @@ -28,11 +32,17 @@ public class PhoneSystemBar extends CustomBar { public PhoneSystemBar(Context context, Density density) throws XmlPullParserException { super(context, density, "/bars/tablet_system_bar.xml"); + setGravity(mGravity | Gravity.RIGHT); + // 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); + Drawable drawable = loadIcon(2, ResourceType.DRAWABLE, "stat_sys_battery_charge"); + if (drawable instanceof LevelListDrawable) { + ((LevelListDrawable) drawable).setLevel(100); + } } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java index bc61799..db1efdb 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java @@ -17,10 +17,13 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; +import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LevelListDrawable; import android.widget.TextView; public class TabletSystemBar extends CustomBar { @@ -36,6 +39,10 @@ public class TabletSystemBar extends CustomBar { loadIcon(2, "ic_sysbar_recent_default.png", density); // 3 is the spacer loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density); + Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge"); + if (drawable instanceof LevelListDrawable) { + ((LevelListDrawable) drawable).setLevel(100); + } } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index cea7cf3..19392a7 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -43,8 +43,10 @@ import android.graphics.drawable.NinePatchDrawable; import android.util.TypedValue; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -171,59 +173,24 @@ public final class ResourceHelper { String lowerCaseValue = stringValue.toLowerCase(); + Density density = Density.MEDIUM; + if (value instanceof DensityBasedResourceValue) { + density = + ((DensityBasedResourceValue)value).getResourceDensity(); + } + + if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { File file = new File(stringValue); if (file.isFile()) { - // see if we still have both the chunk and the bitmap in the caches - NinePatchChunk chunk = Bridge.getCached9Patch(stringValue, - value.isFramework() ? null : context.getProjectKey()); - Bitmap bitmap = Bridge.getCachedBitmap(stringValue, - value.isFramework() ? null : context.getProjectKey()); - - // if either chunk or bitmap is null, then we reload the 9-patch file. - if (chunk == null || bitmap == null) { - try { - NinePatch ninePatch = NinePatch.load(file.toURI().toURL(), - false /* convert */); - if (ninePatch != null) { - if (chunk == null) { - chunk = ninePatch.getChunk(); - - Bridge.setCached9Patch(stringValue, chunk, - value.isFramework() ? null : context.getProjectKey()); - } - - if (bitmap == null) { - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = - ((DensityBasedResourceValue)value).getResourceDensity(); - } - - bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), - false /*isMutable*/, - density); - - Bridge.setCachedBitmap(stringValue, bitmap, - value.isFramework() ? null : context.getProjectKey()); - } - } - } catch (MalformedURLException e) { - // URL is wrong, we'll return null below - } catch (IOException e) { - // failed to read the file, we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); - } - } - - if (chunk != null && bitmap != null) { - int[] padding = chunk.getPadding(); - Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); - - return new NinePatchDrawable(context.getResources(), bitmap, - NinePatch_Delegate.serialize(chunk), - paddingRect, null); + try { + return getNinePatchDrawable( + new FileInputStream(file), density, value.isFramework(), + stringValue, context); + } catch (IOException e) { + // failed to read the file, we'll return null below. + Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, + "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); } } @@ -262,11 +229,6 @@ public final class ResourceHelper { value.isFramework() ? null : context.getProjectKey()); if (bitmap == null) { - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = ((DensityBasedResourceValue)value).getResourceDensity(); - } - bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density); Bridge.setCachedBitmap(stringValue, bitmap, @@ -296,6 +258,52 @@ public final class ResourceHelper { return null; } + private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, + boolean isFramework, String cacheKey, BridgeContext context) throws IOException { + // see if we still have both the chunk and the bitmap in the caches + NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, + isFramework ? null : context.getProjectKey()); + Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, + isFramework ? null : context.getProjectKey()); + + // if either chunk or bitmap is null, then we reload the 9-patch file. + if (chunk == null || bitmap == null) { + try { + NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, + false /* convert */); + if (ninePatch != null) { + if (chunk == null) { + chunk = ninePatch.getChunk(); + + Bridge.setCached9Patch(cacheKey, chunk, + isFramework ? null : context.getProjectKey()); + } + + if (bitmap == null) { + bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), + false /*isMutable*/, + density); + + Bridge.setCachedBitmap(cacheKey, bitmap, + isFramework ? null : context.getProjectKey()); + } + } + } catch (MalformedURLException e) { + // URL is wrong, we'll return null below + } + } + + if (chunk != null && bitmap != null) { + int[] padding = chunk.getPadding(); + Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); + + return new NinePatchDrawable(context.getResources(), bitmap, + NinePatch_Delegate.serialize(chunk), + paddingRect, null); + } + + return null; + } // ------- TypedValue stuff // This is taken from //device/libs/utils/ResourceTypes.cpp @@ -458,3 +466,4 @@ public final class ResourceHelper { return false; } } + |