New layers API for Views.

This API can be used to back a view and its children with either a
software layer (bitmap) or hardware layer (FBO). Layers have
various usages, including color filtering and performance
improvements during animations.

Change-Id: Ifc3bea847918042730fc5a8c2d4206dd6c9420a3
This commit is contained in:
Romain Guy
2011-01-06 10:04:23 -08:00
parent f0fe6d311d
commit 171c592f0b
19 changed files with 664 additions and 48 deletions

View File

@@ -5900,6 +5900,17 @@
visibility="public"
>
</field>
<field name="layerType"
type="int"
transient="false"
volatile="false"
value="16843606"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="layout"
type="int"
transient="false"
@@ -213314,6 +213325,17 @@
visibility="public"
>
</method>
<method name="getLayerType"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getLayoutParams"
return="android.view.ViewGroup.LayoutParams"
abstract="false"
@@ -215816,6 +215838,21 @@
<parameter name="keepScreenOn" type="boolean">
</parameter>
</method>
<method name="setLayerType"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="layerType" type="int">
</parameter>
<parameter name="paint" type="android.graphics.Paint">
</parameter>
</method>
<method name="setLayoutParams"
return="void"
abstract="false"
@@ -216903,6 +216940,39 @@
visibility="public"
>
</field>
<field name="LAYER_TYPE_HARDWARE"
type="int"
transient="false"
volatile="false"
value="2"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="LAYER_TYPE_NONE"
type="int"
transient="false"
volatile="false"
value="0"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="LAYER_TYPE_SOFTWARE"
type="int"
transient="false"
volatile="false"
value="1"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="MEASURED_HEIGHT_STATE_SHIFT"
type="int"
transient="false"

View File

@@ -127,7 +127,11 @@ class GLES20Canvas extends HardwareCanvas {
@Override
protected void finalize() throws Throwable {
replaceNativeObject(0);
try {
replaceNativeObject(0);
} finally {
super.finalize();
}
}
}
@@ -395,8 +399,11 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
int saveFlags) {
int nativePaint = paint == null ? 0 : paint.mNativePaint;
return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
boolean hasColorFilter = paint != null && setupColorFilter(paint);
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
if (hasColorFilter) nResetModifiers(mRenderer);
return count;
}
private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,

View File

@@ -58,7 +58,6 @@ import android.util.PoolableManager;
import android.util.Pools;
import android.util.SparseArray;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -546,6 +545,10 @@ import java.util.WeakHashMap;
* subtree rooted by that node. When an animation is started, the framework will
* take care of redrawing the appropriate views until the animation completes.
* </p>
* <p>
* Starting with Android 3.0, the preferred way of animating views is to use the
* {@link android.animation} package APIs.
* </p>
*
* <a name="Security"></a>
* <h3>Security</h3>
@@ -569,6 +572,7 @@ import java.util.WeakHashMap;
* See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
* </p>
*
* @attr ref android.R.styleable#View_alpha
* @attr ref android.R.styleable#View_background
* @attr ref android.R.styleable#View_clickable
* @attr ref android.R.styleable#View_contentDescription
@@ -584,6 +588,7 @@ import java.util.WeakHashMap;
* @attr ref android.R.styleable#View_focusableInTouchMode
* @attr ref android.R.styleable#View_hapticFeedbackEnabled
* @attr ref android.R.styleable#View_keepScreenOn
* @attr ref android.R.styleable#View_layerType
* @attr ref android.R.styleable#View_longClickable
* @attr ref android.R.styleable#View_minHeight
* @attr ref android.R.styleable#View_minWidth
@@ -2151,6 +2156,69 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
public static final int SCROLLBAR_POSITION_RIGHT = 2;
/**
* Indicates that the view does not have a layer.
*
* @see #getLayerType()
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
*/
public static final int LAYER_TYPE_NONE = 0;
/**
* <p>Indicates that the view has a software layer. A software layer is backed
* by a bitmap and causes the view to be rendered using Android's software
* rendering pipeline, even if hardware acceleration is enabled.</p>
*
* <p>Software layers have various usages:</p>
* <p>When the application is not using hardware acceleration, a software layer
* is useful to apply a specific color filter and/or blending mode and/or
* translucency to a view and all its children.</p>
* <p>When the application is using hardware acceleration, a software layer
* is useful to render drawing primitives not supported by the hardware
* accelerated pipeline. It can also be used to cache a complex view tree
* into a texture and reduce the complexity of drawing operations. For instance,
* when animating a complex view tree with a translation, a software layer can
* be used to render the view tree only once.</p>
* <p>Software layers should be avoided when the affected view tree updates
* often. Every update will require to re-render the software layer, which can
* potentially be slow (particularly when hardware acceleration is turned on
* since the layer will have to be uploaded into a hardware texture after every
* update.)</p>
*
* @see #getLayerType()
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_HARDWARE
*/
public static final int LAYER_TYPE_SOFTWARE = 1;
/**
* <p>Indicates that the view has a hardware layer. A hardware layer is backed
* by a hardware specific texture (generally Frame Buffer Objects or FBO on
* OpenGL hardware) and causes the view to be rendered using Android's hardware
* rendering pipeline, but only if hardware acceleration is turned on for the
* view hierarchy. When hardware acceleration is turned off, hardware layers
* behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
*
* <p>A hardware layer is useful to apply a specific color filter and/or
* blending mode and/or translucency to a view and all its children.</p>
* <p>A hardware layer can also be used to increase the rendering quality when
* rotation transformations are applied on a view. It can also be used to
* prevent potential clipping issues when applying 3D transforms on a view.</p>
*
* @see #getLayerType()
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
*/
public static final int LAYER_TYPE_HARDWARE = 2;
@ViewDebug.ExportedProperty(category = "drawing")
int mLayerType = LAYER_TYPE_NONE;
Paint mLayerPaint;
/**
* Simple constructor to use when creating a view from code.
*
@@ -2489,6 +2557,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
case R.styleable.View_verticalScrollbarPosition:
mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
break;
case R.styleable.View_layerType:
setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
break;
}
}
@@ -5763,11 +5834,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
* Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
* completely transparent and 1 means the view is completely opaque.
* <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
* completely transparent and 1 means the view is completely opaque.</p>
*
* <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
* responsible for applying the opacity itself. Otherwise, calling this method is
* equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
* setting a hardware layer.</p>
*
* @param alpha The opacity of the view.
*
* @see #setLayerType(int, android.graphics.Paint)
*
* @attr ref android.R.styleable#View_alpha
*/
public void setAlpha(float alpha) {
@@ -7746,6 +7824,88 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
}
/**
* <p>Specifies the type of layer backing this view. The layer can be
* {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
* {@link #LAYER_TYPE_HARDWARE hardware}.</p>
*
* <p>A layer is associated with an optional {@link android.graphics.Paint}
* instance that controls how the layer is composed on screen. The following
* properties of the paint are taken into account when composing the layer:</p>
* <ul>
* <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
* <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
* <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
* </ul>
*
* <p>If this view has an alpha value set to < 1.0 by calling
* {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
* this view's alpha value. Calling {@link #setAlpha(float)} is therefore
* equivalent to setting a hardware layer on this view and providing a paint with
* the desired alpha value.<p>
*
* <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
* {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
* for more information on when and how to use layers.</p>
*
* @param layerType The ype of layer to use with this view, must be one of
* {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}
* @param paint The paint used to compose the layer. This argument is optional
* and can be null. It is ignored when the layer type is
* {@link #LAYER_TYPE_NONE}
*
* @see #getLayerType()
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
* @see #setAlpha(float)
*
* @attr ref android.R.styleable#View_layerType
*/
public void setLayerType(int layerType, Paint paint) {
if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
+ "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
}
// Destroy any previous software drawing cache if needed
if (mLayerType == LAYER_TYPE_SOFTWARE && layerType != LAYER_TYPE_SOFTWARE) {
if (mDrawingCache != null) {
mDrawingCache.recycle();
mDrawingCache = null;
}
if (mUnscaledDrawingCache != null) {
mUnscaledDrawingCache.recycle();
mUnscaledDrawingCache = null;
}
}
mLayerType = layerType;
mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
invalidate();
}
/**
* Indicates what type of layer is currently associated with this view. By default
* a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
* Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
* for more information on the different types of layers.
*
* @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}
*
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
*/
public int getLayerType() {
return mLayerType;
}
/**
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
@@ -7753,12 +7913,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* the cache is enabled. To benefit from the cache, you must request the drawing cache by
* calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
* null.</p>
*
* <p>Enabling the drawing cache is similar to
* {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
* acceleration is turned off. When hardware acceleration is turned on enabling the
* drawing cache has either no effect or the cache used at drawing time is not a bitmap.
* This API can however be used to manually generate a bitmap copy of this view.</p>
*
* @param enabled true to enable the drawing cache, false otherwise
*
* @see #isDrawingCacheEnabled()
* @see #getDrawingCache()
* @see #buildDrawingCache()
* @see #setLayerType(int, android.graphics.Paint)
*/
public void setDrawingCacheEnabled(boolean enabled) {
setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
@@ -8077,7 +8244,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN;
if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated) {
if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
mLayerType != LAYER_TYPE_NONE) {
mPrivateFlags |= DRAWING_CACHE_VALID;
}

View File

@@ -2175,11 +2175,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
boolean concatMatrix = false;
boolean scalingRequired = false;
boolean caching = false;
boolean caching;
final int layerType = child.getLayerType();
if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
(flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
caching = true;
if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
} else {
caching = layerType != LAYER_TYPE_NONE;
}
if (a != null) {
@@ -2270,9 +2274,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
Bitmap cache = null;
if (caching) {
if (!canvas.isHardwareAccelerated()) {
if (layerType != LAYER_TYPE_NONE) {
child.buildDrawingCache(true);
}
cache = child.getDrawingCache(true);
} else {
displayList = child.getDisplayList();
if (layerType == LAYER_TYPE_SOFTWARE) {
child.buildDrawingCache(true);
cache = child.getDrawingCache(true);
} else {
displayList = child.getDisplayList();
}
}
}
@@ -2290,6 +2302,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
canvas.scale(scale, scale);
}
}
boolean layerSaved = false;
if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
if (transformToApply != null || !childHasIdentityMatrix) {
@@ -2331,12 +2345,24 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int multipliedAlpha = (int) (255 * alpha);
if (!child.onSetAlpha(multipliedAlpha)) {
int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN ||
layerType != LAYER_TYPE_NONE) {
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
layerFlags);
if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
child.mLayerPaint.setAlpha(multipliedAlpha);
canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct,
child.mLayerPaint, layerFlags);
} else {
canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct,
multipliedAlpha, layerFlags);
}
layerSaved = true;
} else {
// Alpha is handled by the child directly, clobber the layer's alpha
if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
child.mLayerPaint.setAlpha(255);
}
child.mPrivateFlags |= ALPHA_SET;
}
}
@@ -2359,6 +2385,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if (hasNoCache) {
if (!layerSaved && layerType == LAYER_TYPE_HARDWARE) {
canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, child.mLayerPaint,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
}
if (!hasDisplayList) {
// Fast path for layouts with no backgrounds
if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
@@ -2376,13 +2406,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
} else if (cache != null) {
child.mPrivateFlags &= ~DIRTY_MASK;
final Paint cachePaint = mCachePaint;
if (alpha < 1.0f) {
cachePaint.setAlpha((int) (alpha * 255));
mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
} else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
cachePaint.setAlpha(255);
mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
Paint cachePaint;
if (layerType == LAYER_TYPE_NONE || child.mLayerPaint == null) {
cachePaint = mCachePaint;
if (alpha < 1.0f) {
cachePaint.setAlpha((int) (alpha * 255));
mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
} else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
cachePaint.setAlpha(255);
mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
}
} else {
cachePaint = child.mLayerPaint;
if (alpha < 1.0f) {
cachePaint.setAlpha((int) (alpha * 255));
}
}
canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
}

View File

@@ -1784,6 +1784,22 @@
<!-- Place the scroll bar on the right. -->
<enum name="right" value="2" />
</attr>
<!-- Specifies the type of layer backing this view. The default value is none.
Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint)
for more information.-->
<attr name="layerType">
<!-- Don't use a layer. -->
<enum name="none" value="0" />
<!-- Use a software layer. Refer to
{@link android.view.View#setLayerType(int, android.graphics.Paint) for
more information. -->
<enum name="software" value="1" />
<!-- Use a hardware layer. Refer to
{@link android.view.View#setLayerType(int, android.graphics.Paint) for
more information. -->
<enum name="hardware" value="2" />
</attr>
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any

View File

@@ -1420,6 +1420,7 @@
<public type="attr" name="editTextColor" />
<public type="attr" name="editTextBackground" />
<public type="attr" name="horizontalScrollViewStyle" />
<public type="attr" name="layerType" />
<!-- A simple fade-in animation. -->
<public type="animator" name="fade_in" id="0x010b0000" />

View File

@@ -26,6 +26,7 @@
#include <SkXfermode.h>
#include "Rect.h"
#include "SkiaColorFilter.h"
namespace android {
namespace uirenderer {
@@ -93,6 +94,11 @@ struct Layer {
* have been drawn.
*/
Region region;
/**
* Color filter used to draw this layer. Optional.
*/
SkiaColorFilter* colorFilter;
}; // struct Layer
}; // namespace uirenderer

View File

@@ -102,6 +102,7 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) {
layer->blend = true;
layer->empty = true;
layer->fbo = 0;
layer->colorFilter = NULL;
glGenTextures(1, &layer->texture);
glBindTexture(GL_TEXTURE_2D, layer->texture);

View File

@@ -406,6 +406,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
layer->layer.set(bounds);
layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height),
bounds.getWidth() / float(layer->width), 0.0f);
layer->colorFilter = mColorFilter;
// Save the layer in the snapshot
snapshot->flags |= Snapshot::kFlagIsLayer;
@@ -459,7 +460,6 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna
snapshot->flags |= Snapshot::kFlagIsFboLayer;
snapshot->fbo = layer->fbo;
snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
//snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
snapshot->height = bounds.getHeight();
@@ -544,7 +544,13 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
// drawing only the dirty region
if (fboLayer) {
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
if (layer->colorFilter) {
setupColorFilter(layer->colorFilter);
}
composeLayerRegion(layer, rect);
if (layer->colorFilter) {
resetColorFilter();
}
} else {
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
composeLayerRect(layer, rect, true);

View File

@@ -24,6 +24,15 @@
android:label="HwUi"
android:hardwareAccelerated="true">
<activity
android:name="ViewLayersActivity"
android:label="_ViewLayers">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="AlphaLayersActivity"
android:label="_αLayers">

View File

@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.AdvancedBlendActivity.ShadersView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.AdvancedBlendActivity.ShadersView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.AdvancedGradientsActivity.GradientsView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.AdvancedGradientsActivity.GradientsView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.LayersActivity.LayersView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.LayersActivity.LayersView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.LinesActivity.LinesView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.LinesActivity.LinesView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.NewLayersActivity.LayersView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.NewLayersActivity.LayersView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.PathsActivity.PathsView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.PathsActivity.PathsView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<com.android.test.hwui.ShadersActivity.ShadersView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</com.android.test.hwui.ShadersActivity.ShadersView>
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list1"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
<ListView
android:id="@+id/list2"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
<ListView
android:id="@+id/list3"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>

View File

@@ -0,0 +1,158 @@
/*
* 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.test.hwui;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
@SuppressWarnings({"UnusedDeclaration"})
public class ViewLayersActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_layers);
setupList(R.id.list1);
setupList(R.id.list2);
setupList(R.id.list3);
getWindow().getDecorView().postDelayed(new Runnable() {
@Override
public void run() {
final View leftList = findViewById(R.id.list1);
final View middleList = findViewById(R.id.list2);
final View rightList = findViewById(R.id.list3);
final ObjectAnimator moveRight = ObjectAnimator.ofFloat(leftList,
"x", 0, rightList.getLeft());
moveRight.setDuration(1500);
moveRight.setRepeatCount(ObjectAnimator.INFINITE);
moveRight.setRepeatMode(ObjectAnimator.REVERSE);
final ObjectAnimator moveLeft = ObjectAnimator.ofFloat(rightList,
"x", rightList.getLeft(), 0);
moveLeft.setDuration(1500);
moveLeft.setRepeatCount(ObjectAnimator.INFINITE);
moveLeft.setRepeatMode(ObjectAnimator.REVERSE);
final ObjectAnimator rotate = ObjectAnimator.ofFloat(middleList,
"rotationY", 0, 360);
rotate.setDuration(3000);
rotate.setRepeatCount(ObjectAnimator.INFINITE);
rotate.setRepeatMode(ObjectAnimator.REVERSE);
Paint p = new Paint();
p.setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.MULTIPLY));
Paint p2 = new Paint();
p2.setAlpha(127);
Paint p3 = new Paint();
p3.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
leftList.setLayerType(View.LAYER_TYPE_SOFTWARE, p);
leftList.setAlpha(0.5f);
middleList.setLayerType(View.LAYER_TYPE_HARDWARE, p3);
middleList.setAlpha(0.5f);
rightList.setLayerType(View.LAYER_TYPE_SOFTWARE, p2);
moveRight.start();
moveLeft.start();
rotate.start();
}
}, 2000);
}
private void setupList(int listId) {
final ListView list = (ListView) findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
}
private static class SimpleListAdapter extends ArrayAdapter<String> {
public SimpleListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1, DATA_LIST);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = (TextView) super.getView(position, convertView, parent);
final Resources r = getContext().getResources();
final DisplayMetrics metrics = r.getDisplayMetrics();
v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
null, null, null);
return v;
}
}
private static final String[] DATA_LIST = {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
"Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
"Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
"Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
"British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
"Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
"Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
"Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
"Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
"Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
"East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
"Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
"Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
"French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
"Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
"Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
"Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
"Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
"Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
"Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
"Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
"Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
"Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
"Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
"Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
"Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
"Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
"Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
"Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
"Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
"Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
"Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
"Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
"The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
"Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
"Ukraine", "United Arab Emirates", "United Kingdom",
"United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
"Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
"Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
};
}