SwiftBox
SwiftBox copied to clipboard
Layout wasn't returning correct width/height when child nodes get a bit more complicated
Here's the setup I encountered issue
let imageText = Node(
direction: .Column,
padding: Edges(top: 20, bottom: 20),
children: strings.map { (text : String) -> Node in
let image = Node(
size: CGSizeMake(100, 100)
)
let text = Node(
measure: { w in
println("\(w)") // Nan
label.text = text
label.preferredMaxLayoutWidth = w
return label.sizeThatFits(CGSizeMake(w, CGFloat.max))
})
let row = Node(
direction: Direction.Row,
children:[image, text]
)
return row
}
)
println(imageText.layout(maxWidth: 375).frame) // (0.0, 0.0, 7704.0, 240.0)
Notice the width wasn't obeying the maxWidth
we've put into our layout.
So Basically I want to implement something like this:
I had some sample data setup here:
let strings : [String] = [
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ex dolor, imperdiet vel tellus sollicitudin, ultrices maximus nunc. Ut non vehicula magna. Etiam sit amet varius lectus, et luctus dui. Sed eget blandit turpis. Nullam laoreet at felis non fermentum. Integer elit sem, tempus eget ex non, mattis porta lorem. Sed ut quam vel nibh luctus bibendum quis sed mi.",
"Fusce scelerisque rhoncus elementum. Maecenas ultricies est ex, ut varius mauris cursus at. Maecenas sollicitudin orci posuere, ultricies lacus vel, scelerisque nibh. Nullam a turpis a urna elementum posuere. Integer porttitor vestibulum urna lobortis tincidunt. Aliquam consectetur sem metus, et laoreet libero rutrum nec. Donec sed justo dapibus, mollis nibh volutpat, sollicitudin sem. Suspendisse tempor, velit ac ullamcorper pretium, sapien risus molestie enim, aliquam cursus ex massa a nisl. Duis gravida, diam eget rutrum sagittis, dui est malesuada mi, a dapibus eros odio sit amet tellus. Nunc porttitor nunc nec massa mollis, et pellentesque est egestas. Vivamus venenatis dignissim massa in euismod. Vestibulum rutrum ex a interdum varius. Donec convallis gravida dui eget viverra. Suspendisse tempor, lorem sit amet consequat mattis, libero ex dictum quam, eget iaculis felis velit eu nunc. Morbi eros lectus, aliquet at pulvinar sed, tempor malesuada elit. Integer blandit gravida felis.",
]
// Also setting up a label to calculate the size
let label = UILabel()
label.numberOfLines = 0
I tried a simpler setup and works as expected:
let textOnly = Node(
direction: .Column,
padding: Edges(top: 20, bottom: 20),
children: strings.map { (text : String) -> Node in
let text = Node(
measure: { w in
println("\(w)") // 375
label.text = text
label.preferredMaxLayoutWidth = w
return label.sizeThatFits(CGSizeMake(w, CGFloat.max))
})
return text
}
)
println(textOnly.layout(maxWidth: 375).frame) // (0.0, 0.0, 375.0, 669.0)
So is there something wrong with my setup or it's a bug that I encountered? Thanks for helping out!
Yay I got it working!
let imageText = Node(
direction: .Column,
padding: Edges(top: 20, bottom: 20),
size: CGSizeMake(375, CGFloat.NaN), // I just have to make sure I defined the size here, height is important to be Nan
children: strings.map { (text : String) -> Node in
let image = Node(
size: CGSizeMake(100, 100)
)
let text = Node(
flex: 1, // And make sure flex are set
measure: { w in
label.text = text
label.preferredMaxLayoutWidth = w
return label.sizeThatFits(CGSizeMake(w, CGFloat.max))
})
let row = Node(
direction: Direction.Row,
children:[image, text]
)
return row
}
)
println(imageText.layout().frame) // (0.0, 0.0, 375.0, 912.5)
Glad you figured it out!
I'm going to re-open this because that does look like something's funny with maxWidth
.
Is maxWidth
something inside original Flexbox implementation or no?
Yeah it's in FB's flexbox implementation.
Then we have to either help to fix facebook's impl or patch it in SwiftBox manually
I just ran into a bug with maxWidth
myself (it was setting the width of some flex: 1
children to zero).
To work around it, I just wrapped the root node inside an extra node with its width
set to maxWidth
, and then just grabbed the first child after calling layout()
:
if let maxWidth = maxWidth {
let wrapper = Node(size: CGSize(width: maxWidth, height: .nan), children: [node])
let layout = wrapper.layout()
return layout.children.first!
} else {
return node.layout()
}