bongtoi
bongtoi

Reputation: 181

ConstraintLayout inside ConstraintLayout not working in Jetpack Compose

I've two components Brand and SignInCreateAccount. Each component created by ConstraintLayout. Now, I create WelcomeScreen from above components.

Usecase 1: WelcomeScreen using still ConstraintLayout (ConstraintLayout inside ConstraintLayout)

@Composable
fun WelcomeScreen(modifier: Modifier = Modifier) {

    ConstraintLayout {
        val (brand, formSignIn) = createRefs()

        Brand(modifier = modifier.constrainAs(brand) {
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
        })

        SignInCreateAccount(modifier = modifier.constrainAs(formSignIn) {
            start.linkTo(brand.start)
            end.linkTo(brand.end)
            top.linkTo(brand.bottom)
        })
    }
}

Result: Layout preview not show anything

Usecase 2: WelcomeScreen using Column(ConstrantLayout inside Column)

@Composable
fun WelcomeScreen(modifier: Modifier = Modifier) {

    Column {
        Brand()
        SignInCreateAccount()
    }
}

Result: Layout preview show expected result

Brand and SignInCreateAccount components

@Composable
fun SignInCreateAccount(modifier: Modifier = Modifier) {
    ConstraintLayout {
        val (titleSignIn, email, buttonContinue, titleOr, buttonSignGuest) = createRefs()

        Text(
            text = stringResource(id = R.string.sign_in_create_account),
            modifier = modifier.constrainAs(titleSignIn) {
                start.linkTo(parent.start)
                end.linkTo(parent.end)
                top.linkTo(parent.top)
            })

        Text(text = "... Enter your mail", modifier = modifier.constrainAs(email) {
            start.linkTo(titleSignIn.start)
            end.linkTo(titleSignIn.end)
            top.linkTo(titleSignIn.bottom)
        })
    }
}

@Composable
fun Brand(modifier: Modifier = Modifier) {
    ConstraintLayout {
        val (logo, slogan) = createRefs()

        Logo(modifier = modifier.constrainAs(logo) {
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
        })

        Text(text = stringResource(id = R.string.app_tagline),
            modifier = modifier.constrainAs(slogan) {
                start.linkTo(logo.start)
                end.linkTo(logo.end)
                top.linkTo(logo.bottom)
            })
    }
}

@Composable
fun Logo(
    modifier: Modifier = Modifier,
    lightTheme: Boolean = MaterialTheme.colors.isLight
) {
    val assetId = if (lightTheme) {
        R.drawable.ic_logo_light
    } else {
        R.drawable.ic_logo_dark
    }

    Image(
        painter = painterResource(id = assetId),
        modifier = modifier,
        contentDescription = null
    )
}

I want to using ConstraintLayout(as hobby) as use case 1. But I don't know what I did wrong or is there something wrong with ConstraintLayout.

Update: I missed a modifier parameter to the inner constraint layouts. However, another problem arose. That layout rearanged correct, but it not show anything: text, image.

enter image description here

WelcomeScreen.kt

@Composable
fun WelcomeScreen(modifier: Modifier = Modifier) {

    ConstraintLayout(modifier = modifier) {
        val (brand, formSignIn) = createRefs()

        Brand(modifier = modifier.constrainAs(brand) {
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
        })

        SignInCreateAccount(modifier = modifier.constrainAs(formSignIn) {
            start.linkTo(brand.start)
            end.linkTo(brand.end)
            top.linkTo(brand.bottom)
        })
    }
}

@Composable
fun SignInCreateAccount(modifier: Modifier = Modifier) {
    ConstraintLayout(modifier = modifier) {
        val (titleSignIn, email, buttonContinue, titleOr, buttonSignGuest) = createRefs()

        Text(
            text = stringResource(id = R.string.sign_in_create_account),
            modifier = modifier.constrainAs(titleSignIn) {
                start.linkTo(parent.start)
                end.linkTo(parent.end)
                top.linkTo(parent.top)
            })

        Text(text = "... Enter your mail", modifier = modifier.constrainAs(email) {
            start.linkTo(titleSignIn.start)
            end.linkTo(titleSignIn.end)
            top.linkTo(titleSignIn.bottom)
        })
    }
}

@Composable
fun Brand(modifier: Modifier = Modifier) {
    ConstraintLayout(modifier = modifier) {
        val (logo, slogan) = createRefs()

        Logo(modifier = modifier.constrainAs(logo) {
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
        })

        Text(text = stringResource(id = R.string.app_tagline),
            modifier = modifier.constrainAs(slogan) {
                start.linkTo(logo.start)
                end.linkTo(logo.end)
                top.linkTo(logo.bottom)
            })
    }
}

@Composable
fun Logo(
    modifier: Modifier = Modifier,
    lightTheme: Boolean = MaterialTheme.colors.isLight
) {
    val assetId = if (lightTheme) {
        R.drawable.ic_logo_light
    } else {
        R.drawable.ic_logo_dark
    }

    Image(
        painter = painterResource(id = assetId),
        modifier = modifier,
        contentDescription = null
    )
}

@Preview
@Composable
fun DevPreview() {
    JetsurveyTheme(darkTheme = false) {
        WelcomeScreen()
    }
}

Upvotes: 0

Views: 1701

Answers (1)

Dr BigKitkat
Dr BigKitkat

Reputation: 423

You are not passing the modifier parameter to the inner constraint layouts (ones in Brand and SignInCreateAccount), so all the constraints you set on them from the WelcomeScreen don't get passed along, and therefore not appearing on the screen.

For example your Brand composable should like something like this:

@Composable
fun Brand(modifier: Modifier = Modifier) {
    ConstraintLayout(modifier = modifier) {
        val (logo, slogan) = createRefs()

        Logo(modifier = modifier.constrainAs(logo) {
            start.linkTo(parent.start)
            end.linkTo(parent.end)
            top.linkTo(parent.top)
        })

        Text(text = stringResource(id = R.string.app_tagline),
            modifier = modifier.constrainAs(slogan) {
                start.linkTo(logo.start)
                end.linkTo(logo.end)
                top.linkTo(logo.bottom)
            })
    }
}

And the SignInCreateAccount would look like this

@Composable
fun SignInCreateAccount(modifier: Modifier = Modifier) {
    ConstraintLayout(modifier = modifier) {
        val (titleSignIn, email, buttonContinue, titleOr, buttonSignGuest) = createRefs()

        Text(
            text = stringResource(id = R.string.sign_in_create_account),
            modifier = modifier.constrainAs(titleSignIn) {
                start.linkTo(parent.start)
                end.linkTo(parent.end)
                top.linkTo(parent.top)
            })

        Text(text = "... Enter your mail", modifier = modifier.constrainAs(email) {
            start.linkTo(titleSignIn.start)
            end.linkTo(titleSignIn.end)
            top.linkTo(titleSignIn.bottom)
        })
    }
}

Upvotes: 3

Related Questions