DelegatingNode
Class
Common
abstract class DelegatingNode : Modifier.Node()
A Modifier.Node
which is able to delegate work to other Modifier.Node
instances.
This can be useful to compose multiple node implementations into one.
Code Examples
DelegatedNodeSampleExplicit
@Composable
fun DelegatedNodeSampleExplicit() {
class TapGestureNode(var onTap: () -> Unit) : PointerInputModifierNode, Modifier.Node() {
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize,
) {
// ...
}
override fun onCancelPointerInput() {
// ...
}
}
class TapGestureWithClickSemantics(onTap: () -> Unit) :
PointerInputModifierNode, SemanticsModifierNode, DelegatingNode() {
var onTap: () -> Unit
get() = gesture.onTap
set(value) {
gesture.onTap = value
}
val gesture = delegate(TapGestureNode(onTap))
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize,
) {
gesture.onPointerEvent(pointerEvent, pass, bounds)
}
override fun onCancelPointerInput() {
gesture.onCancelPointerInput()
}
override fun SemanticsPropertyReceiver.applySemantics() {
onClick {
gesture.onTap()
true
}
}
}
}
DelegatedNodeSampleImplicit
@Composable
fun DelegatedNodeSampleImplicit() {
class TapGestureNode(var onTap: () -> Unit) : PointerInputModifierNode, Modifier.Node() {
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize,
) {
// ...
}
override fun onCancelPointerInput() {
// ...
}
}
class TapSemanticsNode(var onTap: () -> Unit) : SemanticsModifierNode, Modifier.Node() {
override fun SemanticsPropertyReceiver.applySemantics() {
onClick {
onTap()
true
}
}
}
class TapGestureWithClickSemantics(onTap: () -> Unit) : DelegatingNode() {
var onTap: () -> Unit
get() = gesture.onTap
set(value) {
gesture.onTap = value
semantics.onTap = value
}
val gesture = delegate(TapGestureNode(onTap))
val semantics = delegate(TapSemanticsNode(onTap))
}
}
LazyDelegationExample
@Composable
fun LazyDelegationExample() {
class ExpensivePositionHandlingOnPointerEvents : PointerInputModifierNode, DelegatingNode() {
val globalAwareNode =
object : GlobalPositionAwareModifierNode, Modifier.Node() {
override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
// ...
}
}
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize,
) {
// wait until first pointer event to start listening to global
// position
if (!globalAwareNode.isAttached) {
delegate(globalAwareNode)
}
// normal input processing
}
override fun onCancelPointerInput() {
// ...
}
}
class TapGestureNode(var onTap: () -> Unit) : PointerInputModifierNode, Modifier.Node() {
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize,
) {
// ...
}
override fun onCancelPointerInput() {
// ...
}
}
class TapSemanticsNode(var onTap: () -> Unit) : SemanticsModifierNode, Modifier.Node() {
override fun SemanticsPropertyReceiver.applySemantics() {
onClick {
onTap()
true
}
}
}
class TapGestureWithClickSemantics(onTap: () -> Unit) : DelegatingNode() {
var onTap: () -> Unit
get() = gesture.onTap
set(value) {
gesture.onTap = value
semantics.onTap = value
}
val gesture = delegate(TapGestureNode(onTap))
val semantics = delegate(TapSemanticsNode(onTap))
}
}
ConditionalDelegationExample
fun ConditionalDelegationExample() {
class MyModifierNode(global: Boolean) : DelegatingNode() {
val globalAwareNode =
object : GlobalPositionAwareModifierNode, Modifier.Node() {
override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
// ...
}
}
.also { if (global) delegate(it) }
var global: Boolean = global
set(value) {
if (global && !value) {
undelegate(globalAwareNode)
} else if (!global && value) {
delegate(globalAwareNode)
}
field = value
}
}
}
DelegateInAttachSample
fun DelegateInAttachSample() {
class MyModifierNode : DelegatingNode() {
val globalAwareNode =
object : GlobalPositionAwareModifierNode, Modifier.Node() {
override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
// ...
}
}
override fun onAttach() {
// one can conditionally delegate in attach, for instance if certain conditions are met
if (requireLayoutDirection() == LayoutDirection.Rtl) {
delegate(globalAwareNode)
}
}
}
}