I had the assumption that chaining Modifiers with ...
# compose
d
I had the assumption that chaining Modifiers with
.then()
would replace the configuration of earlier modifiers. Now I stand corrected that an application of the
.padding(...)
modifier and an additional
Modifier.padding(...)
applied via
.then()
is actually additive. Is this really so or did I hit a weird bug here? I looked into the implementation of padding and this just measures / places the contents, I guess the culprit might be somewhere in
CombinedModifier
which I haven’t fully understood how it works (and if there is special code somewhere that folds “padding” modifiers by adding their values together).
f
I think that most of the modifier are "additive". The exceptions are for example layout modifiers like
align
or
size
2
d
Hrm… but why is this a good idea? When you think about reusable components where you want to override one of the default setting, where does this behaviour help? Would one have to deal with negative values instead? That’s hilarious, no?
f
I am sure the Google Compose team had long discussions about the Modifier system so I might let other answer this.
😄 1
👌 1
Which is another way of saying, I might not know enough to give you a good answer 😅
🙂 1
a
long, long conversations. 😄
😄 3
spanning years
😄 3
👴 1
the short answer is that a modifier is behaviorally similar to a wrapper composable, but limited to decorating a single compose-ui layout node whereas a wrapper composable may have 0-N nodes emitted, and the number isn't known until post-composition. As such, if you wrote
Copy code
Padding(16.dp) {
  Padding(4.dp) {
    Text("Hello, world!")
  }
}
you would not expect one to outright replace the other, and the expectation of modifiers is the same. If this were not the case, composability (little-c) suffers as writing a reusable component or widget becomes far more complex; every modifier and how it might replace an inner implementation detail from the outside suddenly becomes a public api consideration
compose-ui also doesn't define a fixed box model for similar reasons of composability. Android view padding in particular experienced a powerful lesson in that kind of fragile base class when bidi text and layout support was added in api 17
bidi view padding is incredibly complicated in its compatibility and correctness handling and suffered from an endless chain of bugs and issues. These arose from its consideration as part of a single box model defined by fixed view properties, where any code that worked with view property ordering, overriding, and replacement was affected
since compose-ui defines things like padding as wrapper layout modifiers, adding new properties like absolute vs bidi padding has clear behavioral expectations and it can be done from outside of the core compose-ui modules in 3rd party libraries if desired
layout modifiers do not need to have prior knowledge of the existence of other layout modifiers to behave properly when used together. Coordination is performed by the integrator assembling the modifiers instead. This allows modifiers written by different 3rd parties that do not know of each other's existence to be used together
d
Ok, many thanks for clearing that up!
👍 1
👍🏻 1