TraversableNode


Allows Modifier.Node classes to traverse up/down the Node tree for classes of the same type or for a particular key (traverseKey).

Note: The actual traversals are done in extension functions (see bottom of file).

Summary

Nested types

Tree traversal actions for the traverseDescendantsIf related functions:

Public properties

Any
Cmn

Extension functions

T?

Finds the nearest ancestor of the same class and key.

Cmn
Unit
<T : TraversableNode> T.traverseAncestors(block: (T) -> Boolean)

Executes block for all ancestors of the same class and key.

Cmn
Unit
<T : TraversableNode> T.traverseChildren(block: (T) -> Boolean)

Executes block for all direct children of the node that are of the same class.

Cmn
Unit

Conditionally executes block for each descendant of the same class.

Cmn

Inherited functions

From androidx.compose.ui.node.DelegatableNode
open Unit

Invoked when the density changes for this node.

Cmn
open Unit

Invoked when the layout direction changes for this node.

Cmn

Inherited properties

From androidx.compose.ui.node.DelegatableNode
Modifier.Node

A reference of the Modifier.Node that holds this node's position in the node hierarchy.

Cmn

Public properties

traverseKey

val traverseKey: Any

Extension functions

T.findNearestAncestor

fun <T : TraversableNode> T.findNearestAncestor(): T?

Finds the nearest ancestor of the same class and key.

T.traverseAncestors

fun <T : TraversableNode> T.traverseAncestors(block: (T) -> Boolean): Unit

Executes block for all ancestors of the same class and 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 {
        // Because I use the existing key of the class, I can guarantee 'it' will be of the same
        // type as the class, so I can call my functions directly.
        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
    }
}

T.traverseChildren

fun <T : TraversableNode> T.traverseChildren(block: (T) -> Boolean): Unit

Executes block for all direct children of the node that are of the same class.

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 {
        // Because I use the existing key of the class, I can guarantee 'it' will be of the same
        // type as the class, so I can call my functions directly.
        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
    }
}

T.traverseDescendants

fun <T : TraversableNode> T.traverseDescendants(
    block: (T) -> TraversableNode.Companion.TraverseDescendantsAction
): Unit

Conditionally executes block for each descendant of the same class.

Note 1: For nodes that do not have the same key, it will continue to execute the block for the 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 {
        // Because I use the existing key of the class, I can guarantee 'it' will be of the same
        // type as the class, so I can call my functions directly.
        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
    }
}