Loading api/current.xml +70 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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" Loading Loading @@ -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" Loading Loading @@ -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" core/java/android/view/GLES20Canvas.java +10 −3 Original line number Diff line number Diff line Loading @@ -127,7 +127,11 @@ class GLES20Canvas extends HardwareCanvas { @Override protected void finalize() throws Throwable { try { replaceNativeObject(0); } finally { super.finalize(); } } } Loading Loading @@ -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, Loading core/java/android/view/View.java +172 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading Loading @@ -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. * Loading Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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 Loading @@ -7754,11 +7914,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * 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); Loading Loading @@ -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; } Loading core/java/android/view/ViewGroup.java +51 −12 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -2270,11 +2274,19 @@ 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 { if (layerType == LAYER_TYPE_SOFTWARE) { child.buildDrawingCache(true); cache = child.getDrawingCache(true); } else { displayList = child.getDisplayList(); } } } final boolean hasDisplayList = displayList != null && displayList.isReady(); final boolean hasNoCache = cache == null || hasDisplayList; Loading @@ -2291,6 +2303,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } boolean layerSaved = false; if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; Loading Loading @@ -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; } } Loading @@ -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) { Loading @@ -2376,7 +2406,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } else if (cache != null) { child.mPrivateFlags &= ~DIRTY_MASK; final Paint cachePaint = mCachePaint; 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; Loading @@ -2384,6 +2417,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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); } Loading core/res/res/values/attrs.xml +16 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
api/current.xml +70 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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" Loading Loading @@ -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" Loading Loading @@ -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"
core/java/android/view/GLES20Canvas.java +10 −3 Original line number Diff line number Diff line Loading @@ -127,7 +127,11 @@ class GLES20Canvas extends HardwareCanvas { @Override protected void finalize() throws Throwable { try { replaceNativeObject(0); } finally { super.finalize(); } } } Loading Loading @@ -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, Loading
core/java/android/view/View.java +172 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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> Loading @@ -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 Loading @@ -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 Loading Loading @@ -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. * Loading Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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 Loading @@ -7754,11 +7914,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * 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); Loading Loading @@ -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; } Loading
core/java/android/view/ViewGroup.java +51 −12 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -2270,11 +2274,19 @@ 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 { if (layerType == LAYER_TYPE_SOFTWARE) { child.buildDrawingCache(true); cache = child.getDrawingCache(true); } else { displayList = child.getDisplayList(); } } } final boolean hasDisplayList = displayList != null && displayList.isReady(); final boolean hasNoCache = cache == null || hasDisplayList; Loading @@ -2291,6 +2303,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } boolean layerSaved = false; if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; Loading Loading @@ -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; } } Loading @@ -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) { Loading @@ -2376,7 +2406,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } else if (cache != null) { child.mPrivateFlags &= ~DIRTY_MASK; final Paint cachePaint = mCachePaint; 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; Loading @@ -2384,6 +2417,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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); } Loading
core/res/res/values/attrs.xml +16 −0 Original line number Diff line number Diff line Loading @@ -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 Loading