Building a Twitter Profile Clone Using Jetpack Compose

Building a Twitter Profile Clone Using Jetpack Compose

Starting With Jetpack Compose

·

3 min read

I started learning Jetpack Compose recently. Building android UI now feels programmatic. I managed to build the profile page although it's not a near perfect match clone, I learnt some basic skills working with Jetpack Compose

This were some of the takeaways:

  • Using Rows
  • Using Columns
  • Loading Images from drawable resource directory
  • Defining theme Colors
  • Overriding theme color
  • Using Box component to stack components
  • Material theme
  • Defining a composable
  • Previewing a composable

Below is a code snippet that entails usage of above mentioned items.

View Composable

@Composable
fun profile(){
    Column(modifier = Modifier
        .fillMaxSize()
        .background(color = MaterialTheme.colors.background)){
        Row(
            modifier = Modifier
                .padding(
                    start = 15.dp,
                    top = 15.dp, end = 15.dp, bottom = 8.dp
                )
                .fillMaxWidth()
        ) {
            Image(
                painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24),
                contentDescription = "Back Arrow",
                modifier = Modifier.align(Alignment.CenterVertically)
            )
            Spacer(modifier = Modifier.width(20.dp))
            Column() {
                Text(text = "John Mwai",
                    color = Color.White,
                    fontSize= 20.sp,
                    fontWeight = FontWeight.Bold,
                    style = MaterialTheme.typography.body1
                )
                Spacer(modifier = Modifier.height(1.dp))
                Text(text = "814 tweets",
                    style = MaterialTheme.typography.caption,
                    color = Color.Gray,
                    fontSize = 13.sp)
            }
        }

        Box(
            modifier = Modifier
                .height(220.dp)
                .fillMaxSize()
        ){
            Box(modifier = Modifier
                .fillMaxWidth()) {
                Image(
                    painter = painterResource(id = R.drawable.header_image),
                    contentDescription = "Header Image")
            }

            Box( modifier = Modifier
                .fillMaxSize()
                .padding(start = 15.dp, bottom = 15.dp),
                contentAlignment = Alignment.BottomStart
            ){
                Image(painter = painterResource(
                    id = R.drawable.photo),
                    contentDescription = "Profile Picture",
                    modifier = Modifier
                        .clip(CircleShape)
                        .size(120.dp)
                        .border(
                            2.dp, MaterialTheme.colors.background,
                            CircleShape
                        ))
            }

            Box( modifier = Modifier
                .fillMaxSize()
                .padding(
                    start = 1.dp,
                    top = 15.dp, end = 15.dp, bottom = 40.dp
                ),
                contentAlignment = Alignment.BottomEnd
            ){
                OutlinedButton(onClick = { /*TODO*/ },
                    shape = CircleShape,
                    border= BorderStroke(1.dp, Color.Gray,),
                    colors = ButtonDefaults.buttonColors(
                        backgroundColor = MaterialTheme.colors.background,
                        contentColor = Color.White)
                ) {
                    Text(text = "Edit profile",
                        style = MaterialTheme.typography.body1,
                        fontWeight = FontWeight.Bold)
                }
            }
        }

        Column(
            modifier = Modifier.padding(15.dp)
        ) {
            Column {
                Text(text = "John Mwai",
                    color = Color.White,
                    fontSize= 20.sp,
                    fontWeight = FontWeight.Bold,
                    style = MaterialTheme.typography.body1
                )
                Spacer(modifier = Modifier.height(1.dp))
                Text(text = "@HelloMwai",
                    style = MaterialTheme.typography.caption,
                    color = Color.Gray,
                    fontSize = 13.sp)

                Spacer(modifier = Modifier.height(15.dp))
                Text(text = "#android #backend #kotlin",
                    style = MaterialTheme.typography.caption,
                    color = Color(0xFF1D98F0),
                    fontSize = 13.sp)
                Spacer(modifier = Modifier.height(1.dp))
                Text(text = "Eternal student, Software developer,Programmer",
                    style = MaterialTheme.typography.caption,
                    color = Color.White,
                    fontSize = 13.sp)
                Spacer(modifier = Modifier.height(15.dp))
                Text(text = "watch me build, \nwatch me write, \nwatch me fail, \nwatch me succeed",
                    style = MaterialTheme.typography.caption,
                    color = Color.White,
                    fontSize = 13.sp)
                Spacer(modifier = Modifier.height(5.dp))
                Row(horizontalArrangement = Arrangement.SpaceBetween) {
                    Icon(painter = painterResource(R.drawable.location), tint = Color.Gray , contentDescription = "DOB")
                    Spacer(modifier = Modifier.width(2.dp))
                    Text("World",
                        color = Color.Gray,)
                    Spacer(modifier = Modifier.width(15.dp))
                    Icon(painter = painterResource(R.drawable.ic_baseline_link), tint = Color.Gray , contentDescription = "DOB")
                    Spacer(modifier = Modifier.width(2.dp))
                    Text("github.com/mwaijohn",
                        color = Color(0xFF1D98F0),)
                }
                Spacer(modifier = Modifier.height(0.5.dp))
                Row(horizontalArrangement = Arrangement.SpaceAround) {
                    Icon(painter = painterResource(R.drawable.balloon), tint = Color.Gray , contentDescription = "DOB")
                    Spacer(modifier = Modifier.width(2.dp))
                    Text("Born September 10, 1996",
                        color = Color.Gray,)
                    Spacer(modifier = Modifier.width(15.dp))
                    Icon(painter = painterResource(R.drawable.date), tint = Color.Gray , contentDescription = "DOB")
                    Spacer(modifier = Modifier.width(2.dp))
                    Text("Joined March 2017",
                        color = Color.Gray)
                }
                Spacer(modifier = Modifier.height(4.dp))
                Row(horizontalArrangement = Arrangement.SpaceAround) {
                    Row(){
                        Text("706",
                            color = Color.White,
                            fontWeight = FontWeight.Bold
                        )
                        Spacer(modifier = Modifier.width(7.dp))
                        Text("Following",
                            color = Color.Gray)
                    }
                    Spacer(modifier = Modifier.width(5.dp))
                    Row(){
                        Text("298",
                            color = Color.White,
                            fontWeight = FontWeight.Bold)
                        Spacer(modifier = Modifier.width(7.dp))
                        Text("Followers",
                            color = Color.Gray)
                    }
                }
            }
        }
    }

Preview Composable

@Preview(showBackground = true, showSystemUi = true)
@Composable
fun ProfilePreview() {
    ComposeTwitterProfileTheme  {
        profile()
    }
}

Showing composable content in MainActivity

 ComposeTwitterProfileTheme {
                profile()
}

Output

output.jpg

Desired Output

capture.png