Skip to content

Commit

Permalink
Fix a bug with Modifier.flex() nested in a row and column
Browse files Browse the repository at this point in the history
This is a bug in Android only caused by not explicitly handling MeasureSpec.UNSPECIFIED.
  • Loading branch information
squarejesse committed Oct 4, 2024
1 parent 56118f2 commit ff77ec1
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import app.cash.paparazzi.Paparazzi
import app.cash.redwood.layout.AbstractFlexContainerTest
import app.cash.redwood.layout.TestFlexContainer
import app.cash.redwood.layout.widget.FlexContainer
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.snapshot.testing.ComposeSnapshotter
import app.cash.redwood.snapshot.testing.ComposeUiTestWidgetFactory
import app.cash.redwood.ui.Px
Expand Down Expand Up @@ -62,6 +63,11 @@ class ComposeUiFlexContainerTest(

override fun column() = flexContainer(FlexDirection.Column)

override fun spacer(backgroundColor: Int): Spacer<@Composable () -> Unit> {
// TODO: honor backgroundColor.
return ComposeUiRedwoodLayoutWidgetFactory().Spacer()
}

override fun snapshotter(widget: @Composable () -> Unit) = ComposeSnapshotter(paparazzi, widget)

class ComposeTestFlexContainer private constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import app.cash.redwood.layout.api.MainAxisAlignment
import app.cash.redwood.layout.api.Overflow
import app.cash.redwood.layout.widget.Column
import app.cash.redwood.layout.widget.Row
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.snapshot.testing.Blue
import app.cash.redwood.snapshot.testing.Green
import app.cash.redwood.snapshot.testing.Red
Expand Down Expand Up @@ -53,6 +54,10 @@ abstract class AbstractFlexContainerTest<T : Any> {
/** Returns a non-lazy flex container column, even if the test is for a LazyList. */
abstract fun column(): Column<T>

abstract fun spacer(
backgroundColor: Int = argb(17, 0, 0, 0),
): Spacer<T>

abstract fun snapshotter(widget: T): Snapshotter

@Test fun testEmptyLayout_Column() {
Expand Down Expand Up @@ -829,6 +834,43 @@ abstract class AbstractFlexContainerTest<T : Any> {

snapshotter(fullWidthParent.value).snapshot()
}

/**
* We were incorrectly collapsing the dimensions of the widget.
* https://github.com/cashapp/redwood/issues/2018
*/
@Test fun testWidgetWithFlexModifierNestedInRowAndColumn() {
val root = flexContainer(FlexDirection.Column).apply {
width(Constraint.Fill)
height(Constraint.Fill)
margin(Margin(top = 24.dp))
modifier = Modifier
}

val rootChild0 = row().apply {
width(Constraint.Fill)
horizontalAlignment(MainAxisAlignment.Center)
root.children.insert(0, this)
}

val rootChild0Child0 = column().apply {
width(Constraint.Fill)
height(Constraint.Fill)
horizontalAlignment(CrossAxisAlignment.Stretch)
modifier = Modifier
.then(MarginImpl(Margin(start = 24.dp, end = 24.dp)))
.then(FlexImpl(1.0))
rootChild0.children.insert(0, this)
}

val rootChild0Child0Child0 = spacer().apply {
width(48.dp)
height(48.dp)
rootChild0Child0.children.insert(0, this)
}

snapshotter(root.value).snapshot()
}
}

interface TestFlexContainer<T : Any> :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import app.cash.redwood.layout.TestFlexContainer
import app.cash.redwood.layout.api.Constraint
import app.cash.redwood.layout.api.CrossAxisAlignment
import app.cash.redwood.layout.widget.FlexContainer
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.snapshot.testing.UIViewSnapshotCallback
import app.cash.redwood.snapshot.testing.UIViewSnapshotter
import app.cash.redwood.snapshot.testing.UIViewTestWidgetFactory
Expand Down Expand Up @@ -68,6 +69,13 @@ class UIViewFlexContainerTest(

override fun column() = flexContainer(FlexDirection.Column)

override fun spacer(backgroundColor: Int): Spacer<UIView> {
return UIViewRedwoodLayoutWidgetFactory().Spacer()
.apply {
value.backgroundColor = backgroundColor.toUIColor()
}
}

class UIViewTestFlexContainer internal constructor(
private val delegate: UIViewFlexContainer,
) : TestFlexContainer<UIView>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ internal class YogaLayout(context: Context) : ViewGroup(context) {
calculateLayout(
requestedWidth = when {
widthMode == MeasureSpec.EXACTLY -> widthSize.toFloat()
widthMode == MeasureSpec.UNSPECIFIED -> Size.UNDEFINED
widthConstraint == Constraint.Fill -> widthSize.toFloat()
else -> Size.UNDEFINED
},
requestedHeight = when {
heightMode == MeasureSpec.EXACTLY -> heightSize.toFloat()
heightMode == MeasureSpec.UNSPECIFIED -> Size.UNDEFINED
heightConstraint == Constraint.Fill -> heightSize.toFloat()
else -> Size.UNDEFINED
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import app.cash.paparazzi.Paparazzi
import app.cash.redwood.layout.AbstractFlexContainerTest
import app.cash.redwood.layout.TestFlexContainer
import app.cash.redwood.layout.widget.FlexContainer
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.snapshot.testing.ViewSnapshotter
import app.cash.redwood.snapshot.testing.ViewTestWidgetFactory
import app.cash.redwood.ui.Px
Expand Down Expand Up @@ -63,6 +64,13 @@ class ViewFlexContainerTest(

override fun column() = flexContainer(FlexDirection.Column)

override fun spacer(backgroundColor: Int): Spacer<View> {
return ViewSpacer(paparazzi.context)
.apply {
setBackgroundColor(backgroundColor)
}
}

override fun snapshotter(widget: View) = ViewSnapshotter(paparazzi, widget)

class ViewTestFlexContainer internal constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import app.cash.redwood.layout.api.MainAxisAlignment
import app.cash.redwood.layout.api.Overflow
import app.cash.redwood.layout.widget.Column
import app.cash.redwood.layout.widget.Row
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.lazylayout.composeui.ComposeUiLazyList
import app.cash.redwood.lazylayout.widget.LazyList
import app.cash.redwood.snapshot.testing.ComposeSnapshotter
Expand Down Expand Up @@ -70,6 +71,11 @@ class ComposeUiLazyListTest(
return ComposeUiRedwoodLayoutWidgetFactory().Column()
}

override fun spacer(backgroundColor: Int): Spacer<@Composable () -> Unit> {
// TODO: honor backgroundColor.
return ComposeUiRedwoodLayoutWidgetFactory().Spacer()
}

override fun snapshotter(widget: @Composable () -> Unit) = ComposeSnapshotter(paparazzi, widget)

class ComposeTestFlexContainer private constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import app.cash.redwood.layout.TestFlexContainer
import app.cash.redwood.layout.api.MainAxisAlignment
import app.cash.redwood.layout.api.Overflow
import app.cash.redwood.layout.uiview.UIViewRedwoodLayoutWidgetFactory
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.lazylayout.toUIColor
import app.cash.redwood.lazylayout.widget.LazyList
import app.cash.redwood.snapshot.testing.UIViewSnapshotCallback
Expand Down Expand Up @@ -47,6 +48,13 @@ class UIViewLazyListAsFlexContainerTest(

override fun column() = UIViewRedwoodLayoutWidgetFactory().Column()

override fun spacer(backgroundColor: Int): Spacer<UIView> {
return UIViewRedwoodLayoutWidgetFactory().Spacer()
.apply {
value.backgroundColor = backgroundColor.toUIColor()
}
}

override fun snapshotter(widget: UIView) = UIViewSnapshotter.framed(callback, widget)

class ViewTestFlexContainer private constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import app.cash.redwood.layout.api.Overflow
import app.cash.redwood.layout.view.ViewRedwoodLayoutWidgetFactory
import app.cash.redwood.layout.widget.Column
import app.cash.redwood.layout.widget.Row
import app.cash.redwood.layout.widget.Spacer
import app.cash.redwood.lazylayout.widget.LazyList
import app.cash.redwood.snapshot.testing.ViewSnapshotter
import app.cash.redwood.snapshot.testing.ViewTestWidgetFactory
Expand Down Expand Up @@ -69,6 +70,13 @@ class ViewLazyListAsFlexContainerTest(
return ViewRedwoodLayoutWidgetFactory(paparazzi.context).Column()
}

override fun spacer(backgroundColor: Int): Spacer<View> {
return ViewRedwoodLayoutWidgetFactory(paparazzi.context).Spacer()
.apply {
value.setBackgroundColor(backgroundColor)
}
}

override fun snapshotter(widget: View) = ViewSnapshotter(paparazzi, widget)

class ViewTestFlexContainer private constructor(
Expand Down

0 comments on commit ff77ec1

Please sign in to comment.