diff options
author | Chet Haase <chet@google.com> | 2012-04-03 15:40:54 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-04-03 15:40:54 -0700 |
commit | 21aec19d3041fe040004dd32eef0cfd1bafd6fb6 (patch) | |
tree | a537409db7054f2faa88b2661cbec9a113bcb7e6 | |
parent | 66ac90276a07b63ad74761d0bd0f1a7218babfbf (diff) | |
parent | db8c9a6a4d9bf8c39f834b25611926caf21380f6 (diff) | |
download | frameworks_base-21aec19d3041fe040004dd32eef0cfd1bafd6fb6.zip frameworks_base-21aec19d3041fe040004dd32eef0cfd1bafd6fb6.tar.gz frameworks_base-21aec19d3041fe040004dd32eef0cfd1bafd6fb6.tar.bz2 |
Merge "Optimization of alpha with DisplayList properties"
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | core/java/android/view/DisplayList.java | 9 | ||||
-rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 11 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 6 | ||||
-rw-r--r-- | core/java/android/view/View.java | 44 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimator.java | 13 | ||||
-rw-r--r-- | core/java/android/widget/ImageView.java | 11 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 12 | ||||
-rw-r--r-- | core/jni/android_view_GLES20DisplayList.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 28 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 5 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 4 | ||||
-rw-r--r-- | libs/hwui/Snapshot.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/Snapshot.h | 11 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | tests/HwAccelerationTest/res/layout/view_properties.xml | 81 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java | 145 |
18 files changed, 368 insertions, 35 deletions
diff --git a/api/current.txt b/api/current.txt index 05fca90..b08705e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -23373,6 +23373,7 @@ package android.view { method public boolean hasFocus(); method public boolean hasFocusable(); method public boolean hasOnClickListeners(); + method public boolean hasOverlappingRendering(); method public boolean hasTransientState(); method public boolean hasWindowFocus(); method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup); diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index 33631b7..fba73fbd 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -149,6 +149,15 @@ public abstract class DisplayList { public abstract void setAlpha(float alpha); /** + * Sets whether the DisplayList renders content which overlaps. Non-overlapping rendering + * can use a fast path for alpha that avoids rendering to an offscreen buffer. + * + * @param hasOverlappingRendering + * @see android.view.View#hasOverlappingRendering() + */ + public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering); + + /** * Sets the translationX value for the DisplayList * * @param translationX The translationX value of the DisplayList diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index bc3bce0..f3618eb 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -147,6 +147,15 @@ class GLES20DisplayList extends DisplayList { } @Override + public void setHasOverlappingRendering(boolean hasOverlappingRendering) { + try { + nSetHasOverlappingRendering(getNativeDisplayList(), hasOverlappingRendering); + } catch (IllegalStateException e) { + // invalid DisplayList okay: we'll set current values the next time we render to it + } + } + + @Override public void setTranslationX(float translationX) { try { nSetTranslationX(getNativeDisplayList(), translationX); @@ -335,6 +344,8 @@ class GLES20DisplayList extends DisplayList { private static native void nSetClipChildren(int displayList, boolean clipChildren); private static native void nSetApplicationScale(int displayList, float scale); private static native void nSetAlpha(int displayList, float alpha); + private static native void nSetHasOverlappingRendering(int displayList, + boolean hasOverlappingRendering); private static native void nSetTranslationX(int displayList, float translationX); private static native void nSetTranslationY(int displayList, float translationY); private static native void nSetRotation(int displayList, float rotation); diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index b100a0c..9ef2621 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -134,7 +134,7 @@ public abstract class HardwareRenderer { /** * Number of frames to profile. */ - private static final int PROFILE_MAX_FRAMES = 64; + private static final int PROFILE_MAX_FRAMES = 120; /** * Number of floats per profiled frame. @@ -1046,10 +1046,6 @@ public abstract class HardwareRenderer { Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " + total + "ms"); } - if (View.USE_DISPLAY_LIST_PROPERTIES) { - Log.d("DLProperties", "getDisplayList():\t" + - mProfileData[mProfileCurrentFrame]); - } } if (displayList != null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a9421f0..c40a7d5 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2830,19 +2830,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal private boolean mSendingHoverAccessibilityEvents; /** - * Delegate for injecting accessiblity functionality. - */ - AccessibilityDelegate mAccessibilityDelegate; - - /** - * Consistency verifier for debugging purposes. - * @hide - */ - protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = - InputEventConsistencyVerifier.isInstrumentationEnabled() ? - new InputEventConsistencyVerifier(this, 0) : null; - - /** * Simple constructor to use when creating a view from code. * * @param context The Context the view is running in, through which it can @@ -2863,6 +2850,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } /** + * Delegate for injecting accessiblity functionality. + */ + AccessibilityDelegate mAccessibilityDelegate; + + /** + * Consistency verifier for debugging purposes. + * @hide + */ + protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = + InputEventConsistencyVerifier.isInstrumentationEnabled() ? + new InputEventConsistencyVerifier(this, 0) : null; + + /** * Constructor that is called when inflating a view from XML. This is called * when a view is being constructed from an XML file, supplying attributes * that were specified in the XML file. This version uses a default style of @@ -7855,6 +7855,23 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } /** + * Returns whether this View has content which overlaps. This function, intended to be + * overridden by specific View types, is an optimization when alpha is set on a view. If + * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer + * and then composited it into place, which can be expensive. If the view has no overlapping + * rendering, the view can draw each primitive with the appropriate alpha value directly. + * An example of overlapping rendering is a TextView with a background image, such as a + * Button. An example of non-overlapping rendering is a TextView with no background, or + * an ImageView with only the foreground image. The default implementation returns true; + * subclasses should override if they have cases which can be optimized. + * + * @return true if the content in this view might overlap, false otherwise. + */ + public boolean hasOverlappingRendering() { + return true; + } + + /** * <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> * @@ -11534,6 +11551,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal void setDisplayListProperties(DisplayList displayList) { if (USE_DISPLAY_LIST_PROPERTIES && displayList != null) { displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); + displayList.setHasOverlappingRendering(hasOverlappingRendering()); if (mParent instanceof ViewGroup) { displayList.setClipChildren( (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 623b567..3626aba 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -834,40 +834,49 @@ public class ViewPropertyAnimator { */ private void setValue(int propertyConstant, float value) { final View.TransformationInfo info = mView.mTransformationInfo; + DisplayList displayList = View.USE_DISPLAY_LIST_PROPERTIES ? mView.mDisplayList : null; switch (propertyConstant) { case TRANSLATION_X: info.mTranslationX = value; + if (displayList != null) displayList.setTranslationX(value); break; case TRANSLATION_Y: info.mTranslationY = value; + if (displayList != null) displayList.setTranslationY(value); break; case ROTATION: info.mRotation = value; + if (displayList != null) displayList.setRotation(value); break; case ROTATION_X: info.mRotationX = value; + if (displayList != null) displayList.setRotationX(value); break; case ROTATION_Y: info.mRotationY = value; + if (displayList != null) displayList.setRotationY(value); break; case SCALE_X: info.mScaleX = value; + if (displayList != null) displayList.setScaleX(value); break; case SCALE_Y: info.mScaleY = value; + if (displayList != null) displayList.setScaleY(value); break; case X: info.mTranslationX = value - mView.mLeft; + if (displayList != null) displayList.setTranslationX(value - mView.mLeft); break; case Y: info.mTranslationY = value - mView.mTop; + if (displayList != null) displayList.setTranslationY(value - mView.mTop); break; case ALPHA: info.mAlpha = value; + if (displayList != null) displayList.setAlpha(value); break; } - // TODO: optimize to set only the properties that have changed - mView.setDisplayListProperties(); } /** diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index b1a75e1..91e2e49 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -201,7 +201,7 @@ public class ImageView extends View { @Override protected boolean onSetAlpha(int alpha) { - if (getBackground() == null) { + if (!USE_DISPLAY_LIST_PROPERTIES && getBackground() == null) { int scale = alpha + (alpha >> 7); if (mViewAlphaScale != scale) { mViewAlphaScale = scale; @@ -214,6 +214,15 @@ public class ImageView extends View { } @Override + public boolean hasOverlappingRendering() { + if (!USE_DISPLAY_LIST_PROPERTIES) { + return super.hasOverlappingRendering(); + } else { + return (getBackground() != null); + } + } + + @Override public void onPopulateAccessibilityEvent(AccessibilityEvent event) { super.onPopulateAccessibilityEvent(event); CharSequence contentDescription = getContentDescription(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 2a81f08..d2a1755 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4268,7 +4268,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener protected boolean onSetAlpha(int alpha) { // Alpha is supported if and only if the drawing can be done in one pass. // TODO text with spans with a background color currently do not respect this alpha. - if (getBackground() == null) { + if (!USE_DISPLAY_LIST_PROPERTIES && + (getBackground() != null || mText instanceof Spannable || hasSelection())) { if (mCurrentAlpha != alpha) { mCurrentAlpha = alpha; final Drawables dr = mDrawables; @@ -4292,6 +4293,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + @Override + public boolean hasOverlappingRendering() { + if (!USE_DISPLAY_LIST_PROPERTIES) { + return super.hasOverlappingRendering(); + } else { + return (getBackground() != null || mText instanceof Spannable || hasSelection()); + } + } + /** * When a TextView is used to display a useful piece of information to the user (such as a * contact's address), it should be made selectable, so that the user can select and copy this diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp index 60fb6d4..b307a2f 100644 --- a/core/jni/android_view_GLES20DisplayList.cpp +++ b/core/jni/android_view_GLES20DisplayList.cpp @@ -65,6 +65,11 @@ static void android_view_GLES20DisplayList_setAlpha(JNIEnv* env, displayList->setAlpha(alpha); } +static void android_view_GLES20DisplayList_setHasOverlappingRendering(JNIEnv* env, + jobject clazz, DisplayList* displayList, bool hasOverlappingRendering) { + displayList->setHasOverlappingRendering(hasOverlappingRendering); +} + static void android_view_GLES20DisplayList_setTranslationX(JNIEnv* env, jobject clazz, DisplayList* displayList, float tx) { displayList->setTranslationX(tx); @@ -185,6 +190,8 @@ static JNINativeMethod gMethods[] = { { "nSetAnimationMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setAnimationMatrix }, { "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren }, { "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha }, + { "nSetHasOverlappingRendering", "(IZ)V", + (void*) android_view_GLES20DisplayList_setHasOverlappingRendering }, { "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX }, { "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY }, { "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation }, diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index f37bfd2..9f2bacd 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -112,6 +112,7 @@ void DisplayList::initProperties() { mClipChildren = true; mAlpha = 1; mMultipliedAlpha = 255; + mHasOverlappingRendering = true; mTranslationX = 0; mTranslationY = 0; mRotation = 0; @@ -772,18 +773,23 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui } } if (mAlpha < 1 && !mCaching) { - // TODO: should be able to store the size of a DL at record time and not - // have to pass it into this call. In fact, this information might be in the - // location/size info that we store with the new native transform data. - int flags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (mClipChildren) { - flags |= SkCanvas::kClipToLayer_SaveFlag; + if (!mHasOverlappingRendering) { + DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha); + renderer.setAlpha(mAlpha); + } else { + // TODO: should be able to store the size of a DL at record time and not + // have to pass it into this call. In fact, this information might be in the + // location/size info that we store with the new native transform data. + int flags = SkCanvas::kHasAlphaLayer_SaveFlag; + if (mClipChildren) { + flags |= SkCanvas::kClipToLayer_SaveFlag; + } + DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", + (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, + mMultipliedAlpha, flags); + renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, + mMultipliedAlpha, flags); } - DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", - (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, - mMultipliedAlpha, flags); - renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, - mMultipliedAlpha, flags); } if (mClipChildren) { DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 38b0a6d..fe0c94d 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -181,6 +181,10 @@ public: } } + void setHasOverlappingRendering(bool hasOverlappingRendering) { + mHasOverlappingRendering = hasOverlappingRendering; + } + void setTranslationX(float translationX) { if (translationX != mTranslationX) { mTranslationX = translationX; @@ -496,6 +500,7 @@ private: bool mClipChildren; float mAlpha; int mMultipliedAlpha; + bool mHasOverlappingRendering; float mTranslationX, mTranslationY; float mRotation, mRotationX, mRotationY; float mScaleX, mScaleY; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 115787c..ec9b56b 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1101,6 +1101,7 @@ void OpenGLRenderer::setupDrawColor(int color) { void OpenGLRenderer::setupDrawColor(int color, int alpha) { mColorA = alpha / 255.0f; + mColorA *= mSnapshot->alpha; // Second divide of a by 255 is an optimization, allowing us to simply multiply // the rgb values by a instead of also dividing by 255 const float a = mColorA / 255.0f; @@ -2800,6 +2801,7 @@ void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mod *mode = SkXfermode::kSrcOver_Mode; *alpha = 255; } + *alpha *= mSnapshot->alpha; } SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index b651904..ab137cc 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -85,6 +85,10 @@ public: virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int flags); + virtual void setAlpha(float alpha) { + mSnapshot->alpha = alpha; + } + virtual void translate(float dx, float dy); virtual void rotate(float degrees); virtual void scale(float sx, float sy); diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index de2c674..5d5961a 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -26,7 +26,7 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), - invisible(false), empty(false) { + invisible(false), empty(false), alpha(1.0f) { transform = &mTransformRoot; clipRect = &mClipRectRoot; @@ -41,7 +41,7 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags): flags(0), previous(s), layer(NULL), fbo(s->fbo), invisible(s->invisible), empty(false), - viewport(s->viewport), height(s->height) { + viewport(s->viewport), height(s->height), alpha(s->alpha) { clipRegion = NULL; diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index b2bc879..30b03fc 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -208,6 +208,17 @@ public: */ Region* region; + /** + * Current alpha value. This value is 1 by default, but may be set by a DisplayList which + * has translucent rendering in a non-overlapping View. This value will be used by + * the renderer to set the alpha in the current color being used for ensuing drawing + * operations. The value is inherited by child snapshots because the same value should + * be applied to descendents of the current DisplayList (for example, a TextView contains + * the base alpha value which should be applied to the child DisplayLists used for drawing + * the actual text). + */ + float alpha; + private: void ensureClipRegion(); void copyClipRectFromRegion(); diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index f4c0841..ceda610 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -657,5 +657,14 @@ </intent-filter> </activity> + <activity + android:name="ViewPropertyAlphaActivity" + android:label="_ViewPropAlpha"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/tests/HwAccelerationTest/res/layout/view_properties.xml b/tests/HwAccelerationTest/res/layout/view_properties.xml new file mode 100644 index 0000000..d7ed819 --- /dev/null +++ b/tests/HwAccelerationTest/res/layout/view_properties.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:id="@+id/container"> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Invalidate" + android:id="@+id/invalidateButton"/> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Button" + android:id="@+id/button"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Some text" + android:id="@+id/textview"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/spantext"/> + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Edit text" + android:id="@+id/edittext"/> + <EditText + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Selected text" + android:id="@+id/selectedtext"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Some text" + android:background="#00ff00" + android:id="@+id/textviewbackground"/> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/icon" + android:id="@+id/imageview"/> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:id="@+id/layout"> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Button"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Some text"/> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Some text" + android:background="#00ff00"/> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java new file mode 100644 index 0000000..738801d --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012 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.animation.ValueAnimator; +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.BackgroundColorSpan; +import android.text.style.ForegroundColorSpan; +import android.text.style.ImageSpan; +import android.text.style.SuggestionSpan; +import android.text.style.UnderlineSpan; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ViewPropertyAlphaActivity extends Activity { + + MyView myViewAlphaDefault, myViewAlphaHandled; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.view_properties); + + getWindow().getDecorView().postDelayed(new Runnable() { + @Override + public void run() { + startAnim(R.id.button); + startAnim(R.id.textview); + startAnim(R.id.spantext); + startAnim(R.id.edittext); + startAnim(R.id.selectedtext); + startAnim(R.id.textviewbackground); + startAnim(R.id.layout); + startAnim(R.id.imageview); + startAnim(myViewAlphaDefault); + startAnim(myViewAlphaHandled); + EditText selectedText = (EditText) findViewById(R.id.selectedtext); + selectedText.setSelection(3, 8); + } + }, 2000); + + Button invalidator = (Button) findViewById(R.id.invalidateButton); + invalidator.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + findViewById(R.id.textview).invalidate(); + findViewById(R.id.spantext).invalidate(); + } + }); + + TextView textView = (TextView) findViewById(R.id.spantext); + if (textView != null) { + SpannableStringBuilder text = + new SpannableStringBuilder("Now this is a short text message with spans"); + + text.setSpan(new BackgroundColorSpan(Color.RED), 0, 3, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ForegroundColorSpan(Color.BLUE), 4, 9, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new SuggestionSpan(this, new String[]{"longer"}, 3), 11, 16, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new UnderlineSpan(), 17, 20, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + text.setSpan(new ImageSpan(this, R.drawable.icon), 21, 22, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + textView.setText(text); + } + + LinearLayout container = (LinearLayout) findViewById(R.id.container); + myViewAlphaDefault = new MyView(this, false); + myViewAlphaDefault.setLayoutParams(new LinearLayout.LayoutParams(75, 75)); + container.addView(myViewAlphaDefault); + myViewAlphaHandled = new MyView(this, true); + myViewAlphaHandled.setLayoutParams(new LinearLayout.LayoutParams(75, 75)); + container.addView(myViewAlphaHandled); + } + + private void startAnim(View target) { + ObjectAnimator anim = ObjectAnimator.ofFloat(target, View.ALPHA, 0); + anim.setRepeatCount(ValueAnimator.INFINITE); + anim.setRepeatMode(ValueAnimator.REVERSE); + anim.setDuration(1000); + anim.start(); + } + private void startAnim(int id) { + startAnim(findViewById(id)); + } + + private static class MyView extends View { + private int mMyAlpha = 255; + private boolean mHandleAlpha; + private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private MyView(Context context, boolean handleAlpha) { + super(context); + mHandleAlpha = handleAlpha; + mPaint.setColor(Color.RED); + } + + @Override + protected void onDraw(Canvas canvas) { + if (mHandleAlpha) { + mPaint.setAlpha(mMyAlpha); + } + canvas.drawCircle(30, 30, 30, mPaint); + } + + @Override + protected boolean onSetAlpha(int alpha) { + if (mHandleAlpha) { + mMyAlpha = alpha; + return true; + } + return super.onSetAlpha(alpha); + } + } + +} |