David Cruz

ConstraintLayout loves Jetpack Compose

blogpost thumbnail created by davthecoder

or the last few years, ConstraintLayout was an effective way to create complex UI for our Android applications.
With Constraint Layout you were able to build a complete UI without the need of any of the old fashion Layout containers such as Linear Layout, RelativeLayout,… and the list goes on.

A few months ago Google has released the first stable version of Jetpack Compose and with it the need of every Developer to explore, learn and adapt to this new way to create UI in our Android applications. However, for developers like me, giving up Constraint Layout is pretty much a huge No-No and the need of learning a new way to create UI’s is pretty much something not looking forwards to it, and something we (at least I) not looking at all to do anytime soon even if is required.

I do believe the Google team understood this issue very well and they create the library to use constraint layouts to be used with compose so… happy days 🥳.
The library can be used in your project by adding the following line in your build.gradle file with the rest of your Compose libraries:

implementation ‘androidx.constraintlayout:constraintlayout-compose:1.0.0-rc01’

Please double check the version in to this link:
https://developer.android.com/jetpack/androidx/releases/constraintlayout

Quick disclaimer: I am not saying you are not able to do complex UI with other Compose components such as Column, Row, Box…
Just I do personally prefer to use ConstraintLayouts for Fluent and efficient daily work as I am used to.

Now the question is:
“How can I translate my ConstraintLayout knowledge in to the equivalent in Compose?”

The simple answer is: Is pretty much the same.
but at the same time is way different so let me explain.

The concept behind is the same:

left of my view to parent left, and top of my view to bottom of another view…

But you need to achieve that in Kotlin and it feels sometimes like you are creating old fashion views programmatically :

// Example old fashion programmatic view creation
// NOTE: please disregard this part as is not related
val textView = TextView(context)
.... code ...
addView(textView)
source: https://giphy.com/gifs/justviralnet-funny-cat-catexe-QAIB3wwvcS5RvmwZI4

Anyway, in few examples, we will see how is not that hard to get used to it and after few lines of code, you will be up and running, creating an even better complex UI.
let start from the basics:

// In XML
<androidx.constraintlayout.widget.ConstraintLayout>
// Code
</androidx.constraintlayout.widget.ConstraintLayout>
// In Jetpack Compose ConstraintLayout
@Composable
fun ConstraintCompose() {
ConstraintLayout {
// Code
}
}

If you want to make your ConstraintLayout on Width and Height MatchParent:

// In XML
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
// Code
</androidx.constraintlayout.widget.ConstraintLayout>
// In Jetpack Compose ConstraintLayout
@Composable
fun ConstraintCompose() {
ConstraintLayout(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()

) {
// Code
}
}

Simple and easy, right?
Cool. lets start with juicy parts.

In this example we will create 2 different Views to interact with them:

// In XML
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="android.R.color.cyan"
<!-- This center the view in parent -->
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="FIRST"/> <TextView
android:id="@+id/text2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="android.R.color.green"
<!-- This center the view below text1-->
app:layout_constraintStart_toStartOf="@id/text1"
app:layout_constraintEnd_toEndOf="@id/text1"
app:layout_constraintTop_toBottomOf="@id/text1"
android:text="SECOND"/>
</androidx.constraintlayout.widget.ConstraintLayout>// In Jetpack Compose ConstraintLayout
@Composable
fun ConstraintCompose() {
// this are the id reference (very important)
val (text1, text2) = createRefs()
ConstraintLayout(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
) {
Text(
modifier = Modifier
.size(100.dp)
.background(color = Color.Cyan, shape = Shapes.large)
.constrainAs(text1) {
centerTo(parent)
},
text = "FIRST"
)
Text(
modifier = Modifier
.size(100.dp)
.background(color = Color.Green, shape = Shapes.large)
.constrainAs(text2) {
top.linkTo(anchor = text1.bottom)
start.linkTo(anchor = text1.start)
end.linkTo(anchor = text1.end)
},
text = "SECOND"
)

}
}

The above example will look like the screenshot above attached.

demo above screenshot constraintlayout in compose
demo above screenshot constraintlayout in compose
demo with 2 views, centre in parent and centre below the first view

As we can see in this small example, ConstraintLayout for Jetpack compose is more concise, with less code we can achieve the same as we did before using purely XML.

However this is not all, because ConstraintLayouts mix perfectly with other UI code from compose, but, that would be something to see on the next blog for ConstraintLayout in Jetpack Compose :)

Android Lead, Kotlin developer & Blogger