DelegatableNode
-
Cmn
interface DelegatableNode
BeyondBoundsLayoutProviderModifierNode |
Provides a |
BringIntoViewModifierNode |
A node that can respond to |
CompositionLocalConsumerModifierNode |
Implementing this interface allows your |
DragAndDropModifierNode |
This interface is deprecated. This interface is deprecated in favor to DragAndDropSourceModifierNode and DragAndDropTargetModifierNode |
DrawModifierNode |
A |
FocusEventModifierNode |
Implement this interface create a modifier node that can be used to observe focus state changes to a |
FocusPropertiesModifierNode |
Implement this interface create a modifier node that can be used to modify the focus properties of the associated |
FocusRequesterModifierNode |
Implement this interface to create a modifier node that can be used to request changes in the focus state of a |
FocusTargetModifierNode |
This modifier node can be delegated to in order to create a modifier that makes a component focusable. |
GlobalPositionAwareModifierNode |
A |
IndirectPointerInputModifierNode |
A |
KeyInputModifierNode |
Implement this interface to create a |
LayoutAwareModifierNode |
A |
LayoutModifierNode |
A |
Modifier.Node |
The longer-lived object that is created for each |
ModifierLocalModifierNode |
A |
ObserverModifierNode |
|
ParentDataModifierNode |
A |
PlatformTextInputModifierNode |
A modifier node that can connect to the platform's text input IME system. |
PointerInputModifierNode |
A |
RotaryInputModifierNode |
Implement this interface to create a |
SemanticsModifierNode |
A |
SoftKeyboardInterceptionModifierNode |
Implement this interface to create a |
TraversableNode |
Allows |
UnplacedAwareModifierNode |
A |
ApproachLayoutModifierNode |
|
CacheDrawModifierNode |
Expands on the |
DelegatingNode |
A |
DragAndDropSourceModifierNode |
A |
DragAndDropTargetModifierNode |
A |
SuspendingPointerInputModifierNode |
Extends |
Represents a Modifier.Node which can be a delegate of another Modifier.Node. Since Modifier.Node implements this interface, in practice any Modifier.Node can be delegated.
| See also | |
|---|---|
DelegatingNode |
|
delegate |
Summary
Nested types |
|---|
fun interface DelegatableNode.RegistrationHandle |
Public functions |
||
|---|---|---|
open Unit |
Invoked when the density changes for this node. |
Cmn
|
open Unit |
Invoked when the layout direction changes for this node. |
Cmn
|
Public properties |
||
|---|---|---|
Modifier.Node |
A reference of the |
Cmn
|
Extension functions |
||
|---|---|---|
suspend Unit |
DelegatableNode.bringIntoView(bounds: (() -> Rect?)?)Bring this node into visible bounds. |
Cmn
|
Unit |
Call this function whenever a scroll chang happened in the LayoutNode that this |
Cmn
|
BeyondBoundsLayout? |
Call this function to find the nearest |
Cmn
|
Unit |
Invalidates draw for the entire subtree of this node. |
Cmn
|
Unit |
Invalidates measurements for the entire subtree of this node. |
Cmn
|
Unit |
Invalidates the subtree of this layout, including layout, drawing, parent data, etc. |
Cmn
|
Unit |
Requests autofill for the LayoutNode that this |
Cmn
|
Density |
Returns the current |
Cmn
|
GraphicsContext |
Returns the current |
Cmn
|
LayoutCoordinates |
Returns the |
Cmn
|
LayoutDirection |
Returns the current |
Cmn
|
View |
The Android |
android
|
Unit |
If the node implements |
Cmn
|
DelegatableNode.RegistrationHandle |
DelegatableNode.registerOnGlobalLayoutListener(Registers a |
Cmn
|
DelegatableNode.RegistrationHandle |
DelegatableNode.registerOnLayoutRectChanged(Registers a |
Cmn
|
Boolean |
DelegatableNode.requestFocusForChildInRootBounds(Attempts to request focus for the most suitable focusable child node that overlaps with the given rect area ( |
Cmn
|
TraversableNode? |
Finds the nearest traversable ancestor with a matching |
Cmn
|
Unit |
DelegatableNode.traverseAncestors( |
Cmn
|
Unit |
DelegatableNode.traverseChildren(Executes |
Cmn
|
Unit |
DelegatableNode.traverseDescendants(Conditionally executes |
Cmn
|
Public functions
onDensityChange
open fun onDensityChange(): Unit
Invoked when the density changes for this node. This affects Dp to pixel conversions, and can cause coordinates / other values to change.
Changes to density will automatically invalidate layout / draw modifiers, as layout, measurement, and draw depend on density. This callback can be used to update any other node state that depends on density, outside of these phases. Density can be retrieved inside a node by using androidx.compose.ui.node.requireDensity.
onLayoutDirectionChange
open fun onLayoutDirectionChange(): Unit
Invoked when the layout direction changes for this node. This can affect the layout and drawing of nodes.
Changes to layout direction will automatically invalidate layout / draw modifiers, as layout, measurement, and draw depend on layout direction. This callback can be used to update any other node state that depends on layout direction, outside of these phases. Layout direction can be retrieved inside a node by using androidx.compose.ui.node.requireLayoutDirection.
Public properties
node
val node: Modifier.Node
A reference of the Modifier.Node that holds this node's position in the node hierarchy. If the node is a delegate of another node, this will point to the root delegating node that is actually part of the node tree. Otherwise, this will point to itself.
Extension functions
bringIntoView
suspend fun DelegatableNode.bringIntoView(bounds: (() -> Rect?)? = null): Unit
Bring this node into visible bounds. Does nothing if the node is not attached.
This method will not return until this request is satisfied or a newer request interrupts it. If this call is interrupted by a newer call, this method will throw a CancellationException.
| Parameters | |
|---|---|
bounds: (() -> Rect?)? = null |
provides the bounds (In local coordinates) that should be brought into view. The function may return a different value over time, if the bounds of the request change while the request is being processed. If you don't provide bounds, the whole node bounds will be used. |
dispatchOnScrollChanged
fun DelegatableNode.dispatchOnScrollChanged(delta: Offset): Unit
Call this function whenever a scroll chang happened in the LayoutNode that this DelegatableNode is attached to to let the underlying platform know that a scroll event happened in this LayoutNode.
On Android this will trigger a ViewTreeObserver onScrollChanged callback.
| Parameters | |
|---|---|
delta: Offset |
The scroll delta that was consumed by this node. |
findNearestBeyondBoundsLayoutAncestor
fun DelegatableNode.findNearestBeyondBoundsLayoutAncestor(): BeyondBoundsLayout?
Call this function to find the nearest BeyondBoundsLayout to the current node.
invalidateDrawForSubtree
fun DelegatableNode.invalidateDrawForSubtree(): Unit
Invalidates draw for the entire subtree of this node.
Note that invalidateDraw is preferable in most cases, however it is only guaranteed to invalidate draw for that specific node, and it is possible that draw nodes that are underneath it could be cached and thus their draw methods will not get re-executed. Use this API if you need to ensure that draw is called for all draw nodes below this one. This might be necessary in certain situations where you are updating some data which you know descendant nodes use, but you are not relaying on automatic snapshot observation through androidx.compose.runtime.MutableState.
Calling this method can be a relatively expensive operation as it will cause the entire subtree to redraw instead of just parts that are otherwise invalidated. invalidateDraw is preferable in most cases, and this should only be used when absolutely necessary.
invalidateMeasurementForSubtree
fun DelegatableNode.invalidateMeasurementForSubtree(): Unit
Invalidates measurements for the entire subtree of this node.
Note that invalidateMeasurement is preferable in most cases, however it is only guaranteed to invalidate measurement for that specific node, and it is possible that layout nodes that are underneath it could be cached and thus their measure policies will not get re-executed. Use this API if you need to ensure that measure is called for all layout nodes below this one. This might be necessary in certain situations where you are updating some data which you know descendant nodes use, but you are not relaying on automatic snapshot observation through androidx.compose.runtime.MutableState.
Calling this method can be a relatively expensive operation as it will cause the entire subtree to relayout instead of just parts that are otherwise invalidated. invalidateMeasurement is preferable in most cases, and this should only be used when absolutely necessary.
invalidateSubtree
fun DelegatableNode.invalidateSubtree(): Unit
Invalidates the subtree of this layout, including layout, drawing, parent data, etc.
Calling this method can be a relatively expensive operation as it will cause the entire subtree to relayout and redraw instead of just parts that are otherwise invalidated. Its use should be limited to structural changes. This might be necessary in certain situations where you are updating some data which you know descendant nodes use, but you are not relaying on automatic snapshot observation through androidx.compose.runtime.MutableState.
requestAutofill
fun DelegatableNode.requestAutofill(): Unit
Requests autofill for the LayoutNode that this DelegatableNode is attached to. If the node does not have any autofill semantic properties set, then the request still may be sent to the Autofill service, but no response is expected.
requireDensity
fun DelegatableNode.requireDensity(): Density
Returns the current Density of the LayoutNode that this DelegatableNode is attached to. If the node is not attached, this function will throw an IllegalStateException.
requireGraphicsContext
fun DelegatableNode.requireGraphicsContext(): GraphicsContext
Returns the current GraphicsContext of the Owner
requireLayoutCoordinates
fun DelegatableNode.requireLayoutCoordinates(): LayoutCoordinates
Returns the LayoutCoordinates of this node.
To get a signal when the LayoutCoordinates become available, or when its parent places it, implement LayoutAwareModifierNode.
| Throws | |
|---|---|
kotlin.IllegalStateException |
When either this node is not attached, or the |
requireLayoutDirection
fun DelegatableNode.requireLayoutDirection(): LayoutDirection
Returns the current LayoutDirection of the LayoutNode that this DelegatableNode is attached to. If the node is not attached, this function will throw an IllegalStateException.
requireView
fun DelegatableNode.requireView(): View
The Android View hosting the composition.
| Throws | |
|---|---|
kotlin.IllegalStateException |
If the modifier node is not |
dispatchDraw
fun DelegatableNode.dispatchDraw(scope: ContentDrawScope): Unit
If the node implements DrawModifierNode, then this will just call DrawModifierNode.draw. if it does NOT implement DrawModifierNode, it will dispatch draw recursively to any of its direct delegates which DO implement DrawModifierNode
This can be useful when there is a DelegatingNode which wants to ensure all draw calls are executed of any delegates, but the implementation of the node may not have knowledge of which delegates actually implement DrawModifierNode.
registerOnGlobalLayoutListener
fun DelegatableNode.registerOnGlobalLayoutListener(
throttleMillis: Long,
debounceMillis: Long,
callback: (RelativeLayoutBounds) -> Unit
): DelegatableNode.RegistrationHandle
Registers a callback to be executed with the position of this modifier node relative to the coordinate system of the root of the composition, as well as in screen coordinates and window coordinates, see RelativeLayoutBounds.
It may also be used to calculate certain Layout relationships at the time of the callback execution, such as RelativeLayoutBounds.calculateOcclusions.
This will be called after layout pass. This API allows for throttling and debouncing parameters in order to moderate the frequency with which the callback gets invoked during high rates of change (e.g. scrolling).
Specifying throttleMillis will prevent callback from being executed more than once over that time period. Specifying debounceMillis will delay the execution of callback until that amount of time has elapsed without a new position.
Specifying 0 for both throttleMillis and debounceMillis will result in the callback being executed every time the position has changed. Specifying non-zero amounts for both will result in both conditions being met.
| Parameters | |
|---|---|
throttleMillis: Long |
The duration, in milliseconds, to prevent |
debounceMillis: Long |
The duration, in milliseconds, to delay the execution of |
callback: (RelativeLayoutBounds) -> Unit |
The callback to be executed, provides a new |
| Returns | |
|---|---|
DelegatableNode.RegistrationHandle |
an object which should be used to unregister/dispose this callback, such as when a node is detached |
registerOnLayoutRectChanged
fun DelegatableNode.registerOnLayoutRectChanged(
throttleMillis: Long,
debounceMillis: Long,
callback: (RelativeLayoutBounds) -> Unit
): DelegatableNode.RegistrationHandle
Registers a callback to be executed with the position of this modifier node relative to the coordinate system of the root of the composition, as well as in screen coordinates and window coordinates. This will be called after layout pass. This API allows for throttling and debouncing parameters in order to moderate the frequency with which the callback gets invoked during high rates of change (e.g. scrolling).
Specifying throttleMillis will prevent callback from being executed more than once over that time period. Specifying debounceMillis will delay the execution of callback until that amount of time has elapsed without a new position.
Specifying 0 for both throttleMillis and debounceMillis will result in the callback being executed every time the position has changed. Specifying non-zero amounts for both will result in both conditions being met.
| Parameters | |
|---|---|
throttleMillis: Long |
The duration, in milliseconds, to prevent |
debounceMillis: Long |
The duration, in milliseconds, to delay the execution of |
callback: (RelativeLayoutBounds) -> Unit |
The callback to be executed. |
| Returns | |
|---|---|
DelegatableNode.RegistrationHandle |
an object which should be used to unregister/dispose this callback |
| See also | |
|---|---|
onLayoutRectChanged |
requestFocusForChildInRootBounds
fun DelegatableNode.requestFocusForChildInRootBounds(
left: Int,
top: Int,
right: Int,
bottom: Int
): Boolean
Attempts to request focus for the most suitable focusable child node that overlaps with the given rect area (left, top, right, bottom).
The rectangle is interpreted in the coordinate space relative to the compose root. See androidx.compose.ui.layout.LayoutCoordinates.localToRoot for converting local coordinates to the root coordinates.
| Parameters | |
|---|---|
left: Int |
is the left edge of the rectangle, in pixels relative to the compose root. |
top: Int |
is the top edge of the rectangle, in pixels relative to the compose root. |
right: Int |
is the right edge of the rectangle, in pixels relative to the compose root. |
bottom: Int |
is the bottom edge of the rectangle, in pixels relative to the compose root. |
| Returns | |
|---|---|
Boolean |
|
findNearestAncestor
fun DelegatableNode.findNearestAncestor(key: Any?): TraversableNode?
Finds the nearest traversable ancestor with a matching key.
traverseAncestors
fun DelegatableNode.traverseAncestors(
key: Any?,
block: (TraversableNode) -> Boolean
): Unit
Executes block for all ancestors with a matching key.
Note: The parameter block's return boolean value will determine if the traversal will continue (true = continue, false = cancel).
import androidx.compose.ui.Modifier import androidx.compose.ui.node.traverseAncestors val customTraversableModifierNode = CustomTraversableModifierNode() with(customTraversableModifierNode) { traverseAncestors(traverseKey) { if (it is CustomTraversableModifierNode) { it.doSomethingWithAncestor() } // Return true to continue searching the tree after a match. If you were looking to // match only some of the nodes, you could return false and stop executing the search. true } }
traverseChildren
fun DelegatableNode.traverseChildren(
key: Any?,
block: (TraversableNode) -> Boolean
): Unit
Executes block for all direct children of the node with a matching key.
Note 1: This stops at the children and does not include grandchildren and so on down the tree.
Note 2: The parameter block's return boolean value will determine if the traversal will continue (true = continue, false = cancel).
import androidx.compose.ui.Modifier import androidx.compose.ui.node.traverseChildren val customTraversableModifierNode = CustomTraversableModifierNode() with(customTraversableModifierNode) { traverseChildren(traverseKey) { if (it is CustomTraversableModifierNode) { it.doSomethingWithChild() } // Return true to continue searching the tree after a match. If you were looking to // match only some of the nodes, you could return false and stop executing the search. true } }
traverseDescendants
fun DelegatableNode.traverseDescendants(
key: Any?,
block: (TraversableNode) -> TraversableNode.Companion.TraverseDescendantsAction
): Unit
Conditionally executes block for each descendant with a matching key.
Note 1: For nodes that do not have the same key, it will continue to execute the block for descendants below that non-matching node (where there may be a node that matches).
Note 2: The parameter block's return value TraverseDescendantsAction will determine the next step in the traversal.
import androidx.compose.ui.Modifier import androidx.compose.ui.node.TraversableNode.Companion.TraverseDescendantsAction import androidx.compose.ui.node.traverseDescendants val customTraversableModifierNode = CustomTraversableModifierNode() with(customTraversableModifierNode) { traverseDescendants(traverseKey) { if (it is CustomTraversableModifierNode) { it.doSomethingWithDescendant() } // [traverseDescendants()] actually has three options: // - ContinueTraversal // - SkipSubtreeAndContinueTraversal - rarely used // - CancelTraversal // They are pretty self explanatory. Usually, you just want to continue or cancel the // search. In some rare cases, you might want to skip the subtree but continue searching // the tree. TraverseDescendantsAction.ContinueTraversal } }