Blog Infos
Author
Published
Topics
, , , ,
Published

Jetpack Compose is Android’s recommended modern toolkit for building native user interfaces. It streamlines and speeds up UI development on Android. Effortlessly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.

ConstraintLayout allows you to create large, complex layouts without using nested view groups, keeping the view hierarchy flat. Like RelativeLayout, it positions views based on their relationships to other views and the parent layout. However, ConstraintLayout is more flexible and easier to use, especially with Android Studio’s Layout Editor.

Constraint layout allows us to create responsive UI’s across resolutions.

We are familiar with building UI using ConstraintLayout in XML let’s see how to do it in JetpackCompose.

Let’s start with a basic example.

First you need to add the following gradle dependency in the build.gradle file.

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"

Vertical positioning:

Let’s write our first UI code

@Preview
@Composable
fun ConstraintLayoutView() {
var count by remember { mutableStateOf(0) }
ConstraintLayout(modifier = Modifier.fillMaxSize()) {
val (button, text) = createRefs()
Button(
onClick = { count++ },
modifier = Modifier.constrainAs(button) {
width = Dimension.value(200.dp)
height = Dimension.value(56.dp)
top.linkTo(parent.top, margin = 16.dp)
bottom.linkTo(parent.bottom, margin = 16.dp)
start.linkTo(parent.start, margin = 16.dp)
end.linkTo(parent.end, margin = 16.dp)
}
) {
Text("Click")
}
Text(
"Count:${count}",
Modifier.constrainAs(text) {
top.linkTo(button.bottom, margin = 16.dp)
start.linkTo(button.start, margin = 16.dp)
end.linkTo(button.end, margin = 16.dp)
}
)
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

Output of the above function:

Output

 

In the above example we have used:

  • @Preview to see preview of our UI.
  • I used remember as I want this UI to remember the count value.
  • I have added a Button and a TextView to the layout. I have given them the id’s button and text by this line val (button, text) = createRefs().
  • I have placed the button in the centre of the screen and given height and width to the button.
  • I have placed a TextView below this Button and on click of this button we will change the text.

To understand it in a much better way here is the XML layout for the above Composable function.

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="56dp"
android:text="CLick"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/button"
app:layout_constraintStart_toStartOf="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>
view raw gistfile1.txt hosted with ❤ by GitHub

Horizontal positioning:

Now let’s try using another example. Let’s say we want to achieve something like below.

We want to have two TextViews next to each other.

@Preview
@Composable
fun ConstraintLayoutView() {
ConstraintLayout(modifier = Modifier.fillMaxSize()) {
val (textTitle, textMore) = createRefs()
Text(
"This is a long title This is a long title This is a long title This is a long title",
modifier = Modifier.constrainAs(textTitle) {
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
end.linkTo(textMore.start, 8.dp)
width = Dimension.fillToConstraints
}
)
Text(
"Show More",
color = Color.Blue.copy(alpha = 0.5f),
modifier = Modifier.constrainAs(textMore) {
top.linkTo(parent.top, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
}
)
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

In the above example:

  • I have added two text views with id’s textTitle and textMore.
  • I have added textViewMore at the top end with respect to the parent.
  • I have added textViewTitle at the top of the parent and the end is relative to textMore at the start of it.
  • I have given width width = Dimension.fillToConstraints to textTitle which is equivalent to 0dp in XML layout.

Here is the XML layout equivalent for the above example to understand better:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="This is a long title This is a long title This is a long title This is a long title"
app:layout_constraintEnd_toStartOf="@+id/textMore"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textMore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Show More"
android:textColor="@android:color/holo_blue_dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
view raw gistfile1.txt hosted with ❤ by GitHub

Percentage ratio:

Consider we want to add an ImageView with width match parent and height equivalent to 40% percent of the total screen height.

Here is the code

Job Offers

Job Offers


    Senior Android Developer

    SumUp
    Berlin
    • Full Time
    apply now

OUR VIDEO RECOMMENDATION

Jobs

@Preview
@Composable
fun ConstraintLayoutView() {
ConstraintLayout(modifier = Modifier.fillMaxSize()) {
val (image, textMore) = createRefs()
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentScale = ContentScale.Crop,
contentDescription = "",
modifier = Modifier.constrainAs(image) {
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
end.linkTo(parent.end, 8.dp)
height = Dimension.percent(0.4f)
width = Dimension.matchParent
}
)
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

Output:

In the above example

  • height = Dimension.percent(0.4f) sets height in ratio with the Screen height
  • width = Dimension.matchParent sets width match parent

The XML equivalent of the above example would be:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_launcher_background"
app:layout_constraintHeight_percent="0.4"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
view raw gistfile1.txt hosted with ❤ by GitHub

Guideline and Barrier:

Consider we have two TextViews both of them can have text of variable length and below these two TextViews I want to place a Button. We can not not place a button relative to any TextView as their lengths may vary.

Following is the code to Achieve UI like above:

@Preview
@Composable
fun ConstraintLayoutView() {
ConstraintLayout(modifier = Modifier.fillMaxSize()) {
val (text1, text2, button) = createRefs()
val guideline = createGuidelineFromStart(0.5f)
val barrier = createBottomBarrier(text1, text2)
Button(
onClick = { },
modifier = Modifier.constrainAs(button) {
width = Dimension.value(200.dp)
height = Dimension.value(56.dp)
top.linkTo(barrier, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
}
) {
Text("I am below two views")
}
Text(
"this is a variable lenght text",
Modifier.constrainAs(text1) {
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
end.linkTo(guideline, margin = 8.dp)
width = Dimension.fillToConstraints
}
)
Text(
"this is another textview with variable lenght",
Modifier.constrainAs(text2) {
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(guideline, margin = 8.dp)
end.linkTo(parent.end, margin = 8.dp)
width = Dimension.fillToConstraints
}
)
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

In above example

  • I have created text1, text2 and button.
  • I have created a horizontal guideline at 50 percent of the width val guideline = createGuidelineFromStart(0.5f) and a barrier below text1 and text2 val barrier = createBottomBarrier(text1, text2).
  • I have placed text1 and text2 relative to parent and guideline.
  • I have placed a button below the barrier where text1 and text2 ends.

The XML equivalent of the above example would be:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="this is a variable lenght text"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/text1"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<TextView
android:text="this is another textview with variable lenght"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/text2"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
app:barrierDirection="bottom"
app:constraint_referenced_ids="text1,text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="I am below two views"
android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/barrier"
android:layout_width="200dp"
android:layout_height="56dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
view raw gistfile1.txt hosted with ❤ by GitHub

Conclusion:

ConstraintLayout in Jetpack Compose simplifies Android UI creation with precise layout control and flexibility. Its declarative approach empowers developers to compose complex UIs effortlessly. Seamlessly integrating Material Design principles ensures consistent and appealing interfaces. By leveraging ConstraintLayout, developers streamline UI development for faster iteration and improved user experiences. Its ongoing evolution promises continued innovation, shaping the future of Android app design uniquely.

This article is previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
In this part of our series on introducing Jetpack Compose into an existing project,…
READ MORE
blog
In the world of Jetpack Compose, where designing reusable and customizable UI components is…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu