androidkotlinandroid-jetpack-composeandroid-custom-viewandroid-jetpack

Change Jetpack Compose view size dynamically


I want create a simple button with 3 predefined sizes, I'm adding an enum param on my Compose view and depending on it I'm trying to set one of this predefined sizes as the width and height.

My enum looks like this:

    enum class ButtonSize(val height: Dp, val width: Dp) {
        LARGE_BUTTON(height = 50.dp, width = 200.dp),
        MEDIUM_BUTTON(height = 40.dp, width = 180.dp),
        SMALL_BUTTON(height = 30.dp, width = 140.dp)
    }

And my custom button:

    @Composable
    fun MyButton(
        onClick: () -> Unit,
        modifier: Modifier = Modifier,
        buttonSize: ButtonSize,
        text: String
    ) {
        when (buttonSize) {
            ButtonSize.LARGE_BUTTON -> {
                modifier.width(ButtonSize.LARGE_BUTTON.width)
                modifier.height(ButtonSize.LARGE_BUTTON.height)
            }
            ButtonSize.MEDIUM_BUTTON -> {
                modifier.width(ButtonSize.MEDIUM_BUTTON.width)
                modifier.height(ButtonSize.MEDIUM_BUTTON.height)
            }
            ButtonSize.SMALL_BUTTON -> {
                modifier.width(ButtonSize.SMALL_BUTTON.width)
                modifier.height(ButtonSize.SMALL_BUTTON.height)
            }
        }
    
        Button(
            onClick = onClick,
            modifier = modifier,
            content = {
                Text(text = text)
            }
        )
}

My Issue is that so far I haven't been able to set the width or height of the button this way, they always remain as the default.


Solution

  • When you call functions on a modifier, those functions don't mutate the original modifier, instead they return a new (combined) modifier as their result, so you have to save the result from your when expression into a local value and then pass that value as the modifier parameter to the Button composable.

    You also have to chain the function calls to .width() and to .height() inside the when expression (inside each case blocks).

    With all those changes you would get something like this

    @Composable
    fun MyButton(
        onClick: () -> Unit,
        modifier: Modifier = Modifier,
        buttonSize: ButtonSize,
        text: String
    ) {
        val newModifier = when (buttonSize) {
            ButtonSize.LARGE_BUTTON -> {
                modifier.width(ButtonSize.LARGE_BUTTON.width)
                  .height(ButtonSize.LARGE_BUTTON.height)
            }
            ButtonSize.MEDIUM_BUTTON -> {
                modifier.width(ButtonSize.MEDIUM_BUTTON.width)
                  .height(ButtonSize.MEDIUM_BUTTON.height)
            }
            ButtonSize.SMALL_BUTTON -> {
                modifier.width(ButtonSize.SMALL_BUTTON.width)
                  .height(ButtonSize.SMALL_BUTTON.height)
            }
        }
    
        Button(
            onClick = onClick,
            modifier = newModifier,
            content = {
                Text(text = text)
            }
        )
    }