Skip to content

Commit

Permalink
Apply modifiers as they change in ViewFlexContainer (#2357)
Browse files Browse the repository at this point in the history
* Apply modifiers as they change in ViewFlexContainer

This reduces the amount of preparation required to measure a layout.

* Spotless

* apiDump
  • Loading branch information
squarejesse authored Oct 2, 2024
1 parent 8b5f374 commit 372600f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,7 @@ internal class ViewFlexContainer(
private val direction: FlexDirection,
) : YogaFlexContainer<View>,
ChangeListener {
private val yogaLayout: YogaLayout = YogaLayout(
context,
applyModifier = { node, index ->
node.applyModifier(children.widgets[index].modifier, density)
},
)
private val yogaLayout: YogaLayout = YogaLayout(context)
override val rootNode: Node get() = yogaLayout.rootNode
override val density = Density(context.resources)

Expand All @@ -59,14 +54,26 @@ internal class ViewFlexContainer(

override val children = ViewGroupChildren(
yogaLayout,
insert = { index, view ->
yogaLayout.rootNode.children.add(index, view.asNode())
insert = { index, widget ->
val view = widget.value

val node = view.asNode()
yogaLayout.rootNode.children.add(index, node)

// Always apply changes *after* adding a node to its parent.
node.applyModifier(widget.modifier, density)

yogaLayout.addView(view, index)
},
remove = { index, count ->
yogaLayout.rootNode.children.remove(index, count)
yogaLayout.removeViews(index, count)
},
onModifierUpdated = { index, widget ->
val node = yogaLayout.rootNode.children[index]
node.applyModifier(widget.modifier, density)
yogaLayout.requestLayout()
},
)

private var onScroll: ((Px) -> Unit)? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import app.cash.redwood.yoga.Size
import kotlin.math.roundToInt

@SuppressLint("ViewConstructor")
internal class YogaLayout(
context: Context,
private val applyModifier: (Node, Int) -> Unit,
) : ViewGroup(context) {
internal class YogaLayout(context: Context) : ViewGroup(context) {
val rootNode = Node()

private fun applyLayout(node: Node, xOffset: Float, yOffset: Float) {
Expand Down Expand Up @@ -85,11 +82,6 @@ internal class YogaLayout(
MeasureSpec.UNSPECIFIED -> {}
}

// This must be applied immediately before measure.
for ((index, node) in rootNode.children.withIndex()) {
applyModifier(node, index)
}

// Sync widget layout requests to the Yoga node tree.
for (node in rootNode.children) {
if (node.view?.isLayoutRequested == true) {
Expand Down
4 changes: 2 additions & 2 deletions redwood-widget/api/android/redwood-widget.api
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public abstract interface class app/cash/redwood/widget/SavedStateRegistry {
}

public final class app/cash/redwood/widget/ViewGroupChildren : app/cash/redwood/widget/Widget$Children {
public fun <init> (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Landroid/view/ViewGroup;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun detach ()V
public fun getWidgets ()Ljava/util/List;
public fun insert (ILapp/cash/redwood/widget/Widget;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,36 @@ import android.view.ViewGroup

public class ViewGroupChildren(
private val container: ViewGroup,
private val insert: (index: Int, view: View) -> Unit = { index, view ->
container.addView(view, index)
private val insert: (index: Int, widget: Widget<View>) -> Unit = { index, widget ->
container.addView(widget.value, index)
},
private val remove: (index: Int, count: Int) -> Unit = { index, count ->
container.removeViews(index, count)
},
private val onModifierUpdated: (index: Int, widget: Widget<View>) -> Unit = { _, _ ->
container.requestLayout()
},
) : Widget.Children<View> {
private val _widgets = ArrayList<Widget<View>>()
override val widgets: List<Widget<View>> get() = _widgets

override fun insert(index: Int, widget: Widget<View>) {
_widgets.add(index, widget)
insert(index, widget.value)
insert.invoke(index, widget)
}

override fun move(fromIndex: Int, toIndex: Int, count: Int) {
_widgets.move(fromIndex, toIndex, count)

val views = Array(count) { offset ->
container.getChildAt(fromIndex + offset)
}
remove.invoke(fromIndex, count)

val newIndex = if (toIndex > fromIndex) {
toIndex - count
} else {
toIndex
}
views.forEachIndexed { offset, view ->
insert(newIndex + offset, view)
for (i in newIndex until newIndex + count) {
insert.invoke(i, _widgets[i])
}
}

Expand All @@ -59,7 +59,7 @@ public class ViewGroupChildren(
}

override fun onModifierUpdated(index: Int, widget: Widget<View>) {
container.requestLayout()
onModifierUpdated.invoke(index, widget)
}

override fun detach() {
Expand Down

0 comments on commit 372600f

Please sign in to comment.