Add attach() callback to LayoutNodeWrapper
The LayoutNodeWrapper class has a detach() callback. Add an attach() callback too. This is needed by FocusModifier and KeyInputModifier so that they can keep track of children (add/remove children) using attach and detach.
Fixes: 154962853
Test: Ran demo app locally
Change-Id: I049251f782b5c48eb207309af8705ffd69cb1c94
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt b/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
index ff2fa34..7792faa 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/ComponentNodes.kt
@@ -765,6 +765,7 @@
if (oldPlaceable != layoutNodeWrapper) {
oldPlaceable.detach()
requestRemeasure()
+ layoutNodeWrapper.attach()
} else if (!needsRemeasure && !needsRelayout && addedCallback) {
// We need to notify the callbacks of a change in position since there's
// a new one.
@@ -795,6 +796,7 @@
requestRemeasure()
parentDataDirty = true
parentLayoutNode?.layoutChildrenDirty = true
+ layoutNodeWrapper.attach()
onAttach?.invoke(owner)
}
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt b/ui/ui-platform/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
index 1f449b1..80d4b9b 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/DelegatingLayoutNodeWrapper.kt
@@ -128,6 +128,11 @@
wrapped.maxIntrinsicHeight(width, layoutDirection)
override val parentData: Any? get() = wrapped.parentData
+ override fun attach() {
+ wrapped.attach()
+ _isAttached = true
+ }
+
override fun detach() {
_isAttached = false
wrapped.detach()
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/InnerPlaceable.kt b/ui/ui-platform/src/main/java/androidx/ui/core/InnerPlaceable.kt
index 9b9d1b9..db54e55 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/InnerPlaceable.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/InnerPlaceable.kt
@@ -148,6 +148,10 @@
}
}
+ override fun attach() {
+ // Do nothing. InnerPlaceable only is attached when the LayoutNode is attached.
+ }
+
override fun detach() {
// Do nothing. InnerPlaceable only is detached when the LayoutNode is detached.
}
diff --git a/ui/ui-platform/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt b/ui/ui-platform/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
index 5c18498..a3eb00d 100644
--- a/ui/ui-platform/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
+++ b/ui/ui-platform/src/main/java/androidx/ui/core/LayoutNodeWrapper.kt
@@ -218,9 +218,26 @@
}
/**
- * Detaches the LayoutNodeWrapper and its wrapped LayoutNodeWrapper from an active LayoutNode.
- * This will be called whenever the modifier chain is replaced and the LayoutNodeWrappers
- * are recreated.
+ * Attaches the [LayoutNodeWrapper] and its wrapped [LayoutNodeWrapper] to an active
+ * LayoutNode.
+ *
+ * This will be called when the [LayoutNode] associated with this [LayoutNodeWrapper] is
+ * attached to the [Owner].
+ *
+ * It is also called whenever the modifier chain is replaced and the [LayoutNodeWrapper]s are
+ * recreated.
+ */
+ abstract fun attach()
+
+ /**
+ * Detaches the [LayoutNodeWrapper] and its wrapped [LayoutNodeWrapper] from an active
+ * LayoutNode.
+ *
+ * This will be called when the [LayoutNode] associated with this [LayoutNodeWrapper] is
+ * detached from the [Owner].
+ *
+ * It is also called whenever the modifier chain is replaced and the [LayoutNodeWrapper]s are
+ * recreated.
*/
abstract fun detach()
diff --git a/ui/ui-platform/src/test/java/androidx/ui/core/ComponentNodeTest.kt b/ui/ui-platform/src/test/java/androidx/ui/core/ComponentNodeTest.kt
index e2d0980..5750760 100644
--- a/ui/ui-platform/src/test/java/androidx/ui/core/ComponentNodeTest.kt
+++ b/ui/ui-platform/src/test/java/androidx/ui/core/ComponentNodeTest.kt
@@ -19,7 +19,6 @@
import androidx.ui.core.pointerinput.PointerInputFilter
import androidx.ui.core.pointerinput.PointerInputModifier
import androidx.ui.core.pointerinput.resize
-import androidx.ui.unit.IntPx
import androidx.ui.unit.IntPxPosition
import androidx.ui.unit.PxPosition
import androidx.ui.unit.ipx
@@ -765,20 +764,23 @@
assertFalse(layoutNode.coordinates.isAttached)
}
- // The LayoutNodeWrapper should be detached when it has been replaced
+ // The LayoutNodeWrapper should be detached when it has been replaced.
@Test
fun layoutNodeWrapperAttachedWhenLayoutNodeAttached() {
val layoutNode = LayoutNode()
val drawModifier = Modifier.drawBehind { }
+
layoutNode.modifier = drawModifier
- val layoutNodeWrapper = layoutNode.layoutNodeWrapper
- assertFalse(layoutNodeWrapper.isAttached)
+ val oldLayoutNodeWrapper = layoutNode.layoutNodeWrapper
+ assertFalse(oldLayoutNodeWrapper.isAttached)
+
layoutNode.attach(mockOwner())
- assertTrue(layoutNodeWrapper.isAttached)
+ assertTrue(oldLayoutNodeWrapper.isAttached)
+
layoutNode.modifier = Modifier.drawBehind { }
- assertFalse(layoutNodeWrapper.isAttached)
- assertTrue(layoutNode.coordinates.isAttached)
- assertTrue(layoutNode.coordinates.isAttached)
+ val newLayoutNodeWrapper = layoutNode.layoutNodeWrapper
+ assertTrue(newLayoutNodeWrapper.isAttached)
+ assertFalse(oldLayoutNodeWrapper.isAttached)
}
@Test