Share via


RenderNode Class

Definition

RenderNode is used to build hardware accelerated rendering hierarchies.

[Android.Runtime.Register("android/graphics/RenderNode", ApiSince=29, DoNotGenerateAcw=true)]
public sealed class RenderNode : Java.Lang.Object
[<Android.Runtime.Register("android/graphics/RenderNode", ApiSince=29, DoNotGenerateAcw=true)>]
type RenderNode = class
    inherit Object
Inheritance
RenderNode
Attributes

Remarks

RenderNode is used to build hardware accelerated rendering hierarchies. Each RenderNode contains both a display list as well as a set of properties that affect the rendering of the display list. RenderNodes are used internally for all Views by default and are not typically used directly.

RenderNodes are used to divide up the rendering content of a complex scene into smaller pieces that can then be updated individually more cheaply. Updating part of the scene only needs to update the display list or properties of a small number of RenderNode instead of redrawing everything from scratch. A RenderNode only needs its display list re-recorded when its content alone should be changed. RenderNodes can also be transformed without re-recording the display list through the transform properties.

A text editor might for instance store each paragraph into its own RenderNode. Thus when the user inserts or removes characters, only the display list of the affected paragraph needs to be recorded again.

<h3>Hardware acceleration</h3>

RenderNodes can be drawn using a RecordingCanvas. They are not supported in software. Always make sure that the android.graphics.Canvas you are using to render a display list is hardware accelerated using android.graphics.Canvas#isHardwareAccelerated().

<h3>Creating a RenderNode</h3>

RenderNode renderNode = new RenderNode("myRenderNode");
                renderNode.setPosition(0, 0, 50, 50); // Set the size to 50x50
                RecordingCanvas canvas = renderNode.beginRecording();
                try {
                    // Draw with the canvas
                    canvas.drawRect(...);
                } finally {
                    renderNode.endRecording();
                }

<h3>Drawing a RenderNode in a View</h3>

protected void onDraw(Canvas canvas) {
                    if (canvas.isHardwareAccelerated()) {
                        // Check that the RenderNode has a display list, re-recording it if it does not.
                        if (!myRenderNode.hasDisplayList()) {
                            updateDisplayList(myRenderNode);
                        }
                        // Draw the RenderNode into this canvas.
                        canvas.drawRenderNode(myRenderNode);
                    }
                }

<h3>Releasing resources</h3>

This step is not mandatory but recommended if you want to release resources held by a display list as soon as possible. Most significantly any bitmaps it may contain.

// Discards the display list content allowing for any held resources to be released.
                // After calling this
                renderNode.discardDisplayList();

<h3>Properties</h3>

In addition, a RenderNode offers several properties, such as #setScaleX(float) or #setTranslationX(float), that can be used to affect all the drawing commands recorded within. For instance, these properties can be used to move around a large number of images without re-issuing all the individual canvas.drawBitmap() calls.

private void createDisplayList() {
                    mRenderNode = new RenderNode("MyRenderNode");
                    mRenderNode.setPosition(0, 0, width, height);
                    RecordingCanvas canvas = mRenderNode.beginRecording();
                    try {
                        for (Bitmap b : mBitmaps) {
                            canvas.drawBitmap(b, 0.0f, 0.0f, null);
                            canvas.translate(0.0f, b.getHeight());
                        }
                    } finally {
                        mRenderNode.endRecording();
                    }
                }

                protected void onDraw(Canvas canvas) {
                    if (canvas.isHardwareAccelerated())
                        canvas.drawRenderNode(mRenderNode);
                    }
                }

                private void moveContentBy(int x) {
                     // This will move all the bitmaps recorded inside the display list
                     // by x pixels to the right and redraw this view. All the commands
                     // recorded in createDisplayList() won't be re-issued, only onDraw()
                     // will be invoked and will execute very quickly
                     mRenderNode.offsetLeftAndRight(x);
                     invalidate();
                }

A few of the properties may at first appear redundant, such as #setElevation(float) and #setTranslationZ(float). The reason for these duplicates are to allow for a separation between static & transient usages. For example consider a button that raises from 2dp to 8dp when pressed. To achieve that an application may decide to setElevation(2dip), and then on press to animate setTranslationZ to 6dip. Combined this achieves the final desired 8dip value, but the animation need only concern itself with animating the lift from press without needing to know the initial starting value. #setTranslationX(float) and #setTranslationY(float) are similarly provided for animation uses despite the functional overlap with #setPosition(Rect).

The RenderNode's transform matrix is computed at render time as follows:

Matrix transform = new Matrix();
                transform.setTranslate(renderNode.getTranslationX(), renderNode.getTranslationY());
                transform.preRotate(renderNode.getRotationZ(),
                        renderNode.getPivotX(), renderNode.getPivotY());
                transform.preScale(renderNode.getScaleX(), renderNode.getScaleY(),
                        renderNode.getPivotX(), renderNode.getPivotY());

The current canvas transform matrix, which is translated to the RenderNode's position, is then multiplied by the RenderNode's transform matrix. Therefore the ordering of calling property setters does not affect the result. That is to say that:

renderNode.setTranslationX(100);
                renderNode.setScaleX(100);

is equivalent to:

renderNode.setScaleX(100);
                renderNode.setTranslationX(100);

<h3>Threading</h3>

RenderNode may be created and used on any thread but they are not thread-safe. Only a single thread may interact with a RenderNode at any given time. It is critical that the RenderNode is only used on the same thread it is drawn with. For example when using RenderNode with a custom View, then that RenderNode must only be used from the UI thread.

<h3>When to re-render</h3>

Many of the RenderNode mutation methods, such as #setTranslationX(float), return a boolean indicating if the value actually changed or not. This is useful in detecting if a new frame should be rendered or not. A typical usage would look like:

public void translateTo(int x, int y) {
                    boolean needsUpdate = myRenderNode.setTranslationX(x);
                    needsUpdate |= myRenderNode.setTranslationY(y);
                    if (needsUpdate) {
                        myOwningView.invalidate();
                    }
                }

This is marginally faster than doing a more explicit up-front check if the value changed by comparing the desired value against #getTranslationX() as it minimizes JNI transitions. The actual mechanism of requesting a new frame to be rendered will depend on how this RenderNode is being drawn. If it's drawn to a containing View, as in the above snippet, then simply invalidating that View works. If instead the RenderNode is being drawn to a Canvas directly such as with Surface#lockHardwareCanvas() then a new frame needs to be drawn by calling Surface#lockHardwareCanvas(), re-drawing the root RenderNode or whatever top-level content is desired, and finally calling Surface#unlockCanvasAndPost(Canvas). </p>

Java documentation for android.graphics.RenderNode.

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

Constructors

RenderNode(String)

Creates a new RenderNode that can be used to record batches of drawing operations, and store / apply render properties when drawn.

Properties

Alpha

Returns the translucency level of this display list.

AmbientShadowColor
Bottom

Gets the bottom position for the RenderNode.

CameraDistance

Returns the distance in Z of the camera for this RenderNode

Class

Returns the runtime class of this Object.

(Inherited from Object)
ClipToBounds

Returns whether or not the RenderNode is clipping to its bounds.

ClipToOutline

See #setClipToOutline(boolean)

Elevation

See #setElevation(float)

Handle

The handle to the underlying Android instance.

(Inherited from Object)
HasDisplayList

Returns whether the RenderNode has a display list.

HasIdentityMatrix

Whether or not the RenderNode has an identity transform.

HasOverlappingRendering

Indicates whether the content of this display list overlaps.

HasShadow

Checks if the RenderNode has a shadow.

Height

Gets the height of the RenderNode, which is the bottom - top.

IsForceDarkAllowed

See #setForceDarkAllowed(boolean)

IsPivotExplicitlySet
JniIdentityHashCode (Inherited from Object)
JniPeerMembers
Left

Gets the left position for the RenderNode.

PeerReference (Inherited from Object)
PivotX

Returns the pivot value for this display list on the X axis, in pixels.

PivotY

Returns the pivot value for this display list on the Y axis, in pixels.

Right

Gets the right position for the RenderNode.

RotationX

Returns the rotation value for this display list around the X axis, in degrees.

RotationY

Returns the rotation value for this display list around the Y axis, in degrees.

RotationZ

Returns the rotation value for this display list around the Z axis, in degrees.

ScaleX

Returns the scale value for this display list on the X axis.

ScaleY

Returns the scale value for this display list on the Y axis.

SpotShadowColor
ThresholdClass

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

(Inherited from Object)
ThresholdType

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

(Inherited from Object)
Top

Gets the top position for the RenderNode.

TranslationX

Returns the translation value for this display list on the X axis, in pixels.

TranslationY

Returns the translation value for this display list on the Y axis, in pixels.

TranslationZ

Returns the translation value for this display list on the Z axis.

UniqueId

Returns the unique ID that identifies this RenderNode.

UseCompositingLayer

Gets whether or not a compositing layer is forced to be used.

Width

Gets the width of the RenderNode, which is the right - left.

Methods

BeginRecording()

Same as #beginRecording(int, int) with the width & height set to the RenderNode's own width & height.

BeginRecording(Int32, Int32)

Starts recording a display list for the render node.

Clone()

Creates and returns a copy of this object.

(Inherited from Object)
ComputeApproximateMemoryUsage()

Gets the approximate memory usage of the RenderNode for debug purposes.

DiscardDisplayList()

Reset native resources.

Dispose() (Inherited from Object)
Dispose(Boolean) (Inherited from Object)
EndRecording()

` Ends the recording for this display list.

Equals(Object)

Indicates whether some other object is "equal to" this one.

(Inherited from Object)
GetHashCode()

Returns a hash code value for the object.

(Inherited from Object)
GetInverseMatrix(Matrix)

Gets the current transform inverted.

GetMatrix(Matrix)

Gets the current transform matrix

JavaFinalize()

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

(Inherited from Object)
Notify()

Wakes up a single thread that is waiting on this object's monitor.

(Inherited from Object)
NotifyAll()

Wakes up all threads that are waiting on this object's monitor.

(Inherited from Object)
OffsetLeftAndRight(Int32)

Offsets the left and right positions for the RenderNode

OffsetTopAndBottom(Int32)

Offsets the top and bottom values for the RenderNode

ResetPivot()

Clears any pivot previously set by a call to #setPivotX(float) or #setPivotY(float).

SetAlpha(Single)

Sets the translucency level for the display list.

SetAmbientShadowColor(Color)

Sets the color of the ambient shadow that is drawn when the RenderNode has a positive Z or elevation value and is drawn inside of a Canvas#enableZ() section.

SetCameraDistance(Single)

Sets the distance along the Z axis (orthogonal to the X/Y plane on which RenderNodes are drawn) from the camera to this RenderNode.

SetClipRect(Rect)

Sets an additional clip on the RenderNode.

SetClipToBounds(Boolean)

Set whether the Render node should clip itself to its bounds.

SetClipToOutline(Boolean)

Enables or disables clipping to the outline.

SetElevation(Single)

Sets the base elevation of this RenderNode in pixels

SetForceDarkAllowed(Boolean)

Sets whether or not to allow force dark to apply to this RenderNode.

SetHandle(IntPtr, JniHandleOwnership)

Sets the Handle property.

(Inherited from Object)
SetHasOverlappingRendering(Boolean)

Sets whether the display list renders content which overlaps.

SetOutline(Outline)

Sets the outline, defining the shape that casts a shadow, and the path to be clipped if setClipToOutline is set.

SetPivotX(Single)

Sets the pivot value for the display list on the X axis

SetPivotY(Single)

Sets the pivot value for the display list on the Y axis

SetPosition(Int32, Int32, Int32, Int32)

Sets the position of the RenderNode.

SetPosition(Rect)

Sets the position of the RenderNode.

SetProjectBackwards(Boolean)

Sets whether the RenderNode should be drawn immediately after the closest ancestor RenderNode containing a projection receiver.

SetProjectionReceiver(Boolean)

Sets whether the RenderNode is a projection receiver.

SetRenderEffect(RenderEffect)

Configure the android.graphics.RenderEffect to apply to this RenderNode.

SetRotationX(Single)

Sets the rotation value for the display list around the X axis.

SetRotationY(Single)

Sets the rotation value for the display list around the Y axis.

SetRotationZ(Single)

Sets the rotation value for the display list around the Z axis.

SetScaleX(Single)

Sets the scale value for the display list on the X axis.

SetScaleY(Single)

Sets the scale value for the display list on the Y axis.

SetSpotShadowColor(Color)

Sets the color of the spot shadow that is drawn when the RenderNode has a positive Z or elevation value and is drawn inside of a Canvas#enableZ() section.

SetTranslationX(Single)

Sets the translation value for the display list on the X axis.

SetTranslationY(Single)

Sets the translation value for the display list on the Y axis.

SetTranslationZ(Single)

Sets the translation value for the display list on the Z axis.

SetUseCompositingLayer(Boolean, Paint)

Controls whether or not to force this RenderNode to render to an intermediate buffer.

ToArray<T>() (Inherited from Object)
ToString()

Returns a string representation of the object.

(Inherited from Object)
UnregisterFromRuntime() (Inherited from Object)
Wait()

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>.

(Inherited from Object)
Wait(Int64, Int32)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)
Wait(Int64)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)

Explicit Interface Implementations

IJavaPeerable.Disposed() (Inherited from Object)
IJavaPeerable.DisposeUnlessReferenced() (Inherited from Object)
IJavaPeerable.Finalized() (Inherited from Object)
IJavaPeerable.JniManagedPeerState (Inherited from Object)
IJavaPeerable.SetJniIdentityHashCode(Int32) (Inherited from Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) (Inherited from Object)
IJavaPeerable.SetPeerReference(JniObjectReference) (Inherited from Object)

Extension Methods

JavaCast<TResult>(IJavaObject)

Performs an Android runtime-checked type conversion.

JavaCast<TResult>(IJavaObject)
GetJniTypeName(IJavaPeerable)

Applies to