What's the best way to achieve this layout? I'm cu...
# compose
a
What's the best way to achieve this layout? I'm currently offsetting my image but that causes spacing issues so is there a better way?
Copy code
Column(modifier, horizontalAlignment = Alignment.CenterHorizontally) {
    Spacer(modifier = Modifier.height(10.dp))

    Text(profile.name, style = MaterialTheme.typography.h6)
    CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
        Text(profile.bio, style = MaterialTheme.typography.body2)
    }

    Image(
        painter = rememberImagePainter(
            profile.avatarUrl,
            builder = { crossfade(true); transformations(CircleCropTransformation()) }
        ),
        contentDescription = ...,
        modifier = Modifier
            .offset(y = (50).dp)
            .size(120.dp)
            .zIndex(2f)
    )

    Surface(
        color = Color.White,
        shape = RoundedCornerShape(0),
        modifier = Modifier
            .fillMaxSize()
            .zIndex(1f)
    ) {

    }
}
a
If you have a fixed height for the profile picture, you can use constraint layout to position the image underneath the black header and then do an offset in the y axis.
Another way would be to create your own custom layout and when the object is measured, offset it's position by half it's height.
a
Thanks! I'll give it a shot
c
I’d use the Compose ConstraintLayout library for this
👍 1
It’s nice because you can easily use it within a Column. You don’t necessarily need to make the whole hierarchy ConstraintLayout
Otherwise (w/o using ConstraintLayout), you can also store the size of the avatar as a variable, then just do some math on the offset that way the positioning is a little more dynamic relative to the image size.
l
I would do
Copy code
Column(background = Black) {
  Text()
  Text()
  Image(
    Modifier.drawBehind {
      drawIntoCanvas {
         drawRect() //black
         drawRect() //white
      }
    }
  )
}
👌 1
a
I did it with ConstraintLayout, looks good now:
Copy code
Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        
        Text(...)
        Text(...)
        Spacer(modifier = Modifier.height(10.dp + ProfileImageSize / 2))

        ConstraintLayout(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
        ) {
            val (image, grid) = createRefs()

            Image(
                painter = rememberImagePainter(
                    profile.avatarUrl,
                    builder = { crossfade(true); transformations(CircleCropTransformation()) }
                ),
                contentDescription = stringResource(R.string.profile_photography_avatar_desc),
                modifier = Modifier
                    .constrainAs(image) {
                        top.linkTo(<http://parent.top|parent.top>)
                        centerHorizontallyTo(parent)
                    }
                    .offset(y = -ProfileImageSize / 2)
                    .size(ProfileImageSize)
            )

            PostsGrid(
                posts = profile.posts,
                modifier = Modifier
                    .constrainAs(grid) {
                        top.linkTo(image.bottom)
                        bottom.linkTo(parent.bottom)
                        centerHorizontallyTo(parent)
                    }
                    .fillMaxSize(),
                onPostClick = {}
            )
        }
    }
👍 2