I have some issues with creating a runtime built U...
# compose
m
I have some issues with creating a runtime built UI system the scenario is that I want to “inflate” my custom button that defaults to fillMaxWidth(1f) as long as its not placed inside a Row(). If it’s placed inside a Row() it should instead use .weight(1f) so that several buttons can be shown together on one line. With the old xml system it was possible to grab the layout object after inflating the button and modify it depending on which class we got back but in Compose this approach does not work. Do we have any solution for this?
v
does something else break if you just use
weight(1f)
always? you could also pass a modifier for your custom button from the parent:
Copy code
fun MyButton(modifier: Modifier) = { Box(modifier.[...]) }
m
weight(1f) does not exist if the button isn’t known to be inside a Column or Row Scope
the “parent” is also unknown until I create the button (i’m doing this recursively) so I don’t even know the parent beforehand
weight
is also a different function depending on if its in a columnscope or a rowscope, and as far as i understand it, it has to be known at compiletime?
v
ah yes, that's true
how exactly is the parent unknown? can you give an example of the generating code?
m
ok, lets try (since it’s quite a framework) I have a componentFactory with one
create
method it also contains a map of all components that I have access to in my framework, driven from a “presenter” class (i.e ButtonPresenter(title:String) -> {MyButton(presenterClass)} so I parse a Json file, getting all the different presenters in a polymorphic list. In the general case I can just read that list, call the factorys createFromPresenter(presenter) function and it will call the correct component constructor to create for example the button are you with me so far?
i.e from knowing the presenter::class I can call a constructor
Copy code
val registry = mutableMapOf<KClass<out Presenter>, @Composable (Presenter) -> Unit>()
    registry[ButtonPresenter::class] = { MyButton(it as ButtonPresenter) }

    fun create(presenter:Presenter){
        registry[presenter::class]?.invoke(presenter)
    }
some presenters can contain childPresenters (i.e a list of presenters) so any component that can act as a group will be calling this create function for all children as well, and now we are in the realm of not knowing (not in the create function anyway)
e
make that
Copy code
@Composable (Presenter, Modifier) -> Unit
then rows can pass down
Modifier.weight(1f)
, others can pass down
Modifier
, and the mapper builds off of the given modifier
or is this specific to buttons for some reason?
m
and create a “create” function per scope?
e
no, why?
m
modifier.weight(1f) only exists in row and column scope, trying to call it outside any of those scopes is (as far as i know) not possible
e
Copy code
registry[MyRow::class] = { row, modifier ->
    Row(modifier = modifier) {
        for (child in row.children) {
            registry[child::class]?.invoke(child, Modifier.weight(1f))
👍 1
👆🏼 1
m
yea, that sounds good, did not think of using the called lambda like that. Thanks.
v
sorry, I managed to tap the wrong emoji on my phone 😅
e
that's what I assumed happened. thanks for updating blob ok hand