Nested ContourLayout causing StackOverflow
See original GitHub issueThe following code causes a stack overflow during layout:
class ParentView(context: Context): ContourLayout(context) {
init {
setBackgroundColor(Color.RED)
}
val childView = ChildView(context).apply {
applyLayout(
x = leftTo { parent.left() }.widthOf { 100.xdip },
y = topTo { parent.top() }.heightOf { 100.ydip }
)
}
}
class ChildView(context: Context) : ContourLayout(context) {
init {
setBackgroundColor(Color.BLUE)
}
}
However, moving ChildView
’s applyLayout
into it’s onInitializeLayout
solves the issue:
class ParentView(context: Context): ContourLayout(context) {
init {
setBackgroundColor(Color.RED)
}
val childView = ChildView(context).also { addView(it) }
}
class ChildView(context: Context) : ContourLayout(context) {
init {
setBackgroundColor(Color.BLUE)
}
override fun onInitializeLayout() {
super.onInitializeLayout()
applyLayout(
x = leftTo { parent.left() }.widthOf { 100.xdip },
y = topTo { parent.top() }.heightOf { 100.ydip }
)
}
}
I don’t know if this is a bug or not, but my hunch is it’s the intended behavior (if not, I’d be happy to look into it).
I realize nesting layouts is discouraged, but there are going to be situations where it is useful and people are going to do it anyway.
The pattern Contour uses for configuring child views (MyView(context).apply { applyLayout() }
) is great, and it seems clunky to have to violate it iff the child happens to be another ContourLayout (I can imagine during refactoring a View that didn’t start as Contour might become one later).
Could we make it so layout constraints declared at construction time get deferred until onInitializeLayout
? Either by having applyLayout
behave differently for ContourLayouts or with an onInitializeLayout
DSL:
class ParentView(context: Context): ContourLayout(context) {
init {
setBackgroundColor(Color.RED)
}
val childView = ChildView(context).apply {
onInitializeLayout {
applyLayout(
x = leftTo { parent.left() }.widthOf { 100.xdip },
y = topTo { parent.top() }.heightOf { 100.ydip }
)
}
}
}
class ChildView(context: Context) : ContourLayout(context) {
init {
setBackgroundColor(Color.BLUE)
}
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:6
I share your pain. We have a work-in-progress solution for this.
Getting caught by this over and over. (I keep forgetting about this issue). I use
ContourLayout
extensively in my new project, so naturally often child views are alsoCountourLayout
s. Having to use.let
instead of.apply
makes code look irregular.If possible I’d suggest to increase priority of this bug.