Getting started with ConstraintLayout in Kotlin - Part 5: building a simple app using ConstraintLayout
You will need Android Studio 3+ installed on your machine. Familiarity with Android development will be helpful. You should have completed the previous parts of the series.
In the previous parts of the series, we looked into ConstraintLayout
and how you can use them to develop Android applications.
In this tutorial, we will use what we learned to create a sample application using ConstraintLayout
. It is expected that you have completed the previous four parts of the series. We will replicate the design below using ConstraintLayout
.
Prerequisites
To follow along in this part of the series you must have:
- Completed the previous parts of the series.
- Android Studio installed on your machine. You can check here for the latest stable versions available. A minimum version of 3.0 is recommended.
- A basic knowledge on Android development and the ability to navigate through the Android Studio IDE.
Building our app layout
To get started, create your Android project in Android Studio. In the wizard, enter your project name, let’s name it ConstraintLayoutSample. Enter your package name for the application and select a minimum SDK of 19. Choose an Empty Activity template and leave the name as MainActivity
. After this, Android studio will build your project and prepare it for you.
During the course of building this application, we will use a circular image view and we need a library for this.
Open your app build.gradle
file and add this dependency:
implementation 'de.hdodenhof:circleimageview:2.2.0'
implementation 'com.android.support:design:28.0.0-rc01'
Go ahead and sync your files after adding it.
We will implement the design in the MainActivity
layout file. Open the activity_main.xml
and replace it with this:
<!-- File: ./app/src/main/res/layout/activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
[...]
</android.support.constraint.ConstraintLayout>
Above, we added the opening and closing tags of the ConstraintLayout
. Within it, we will place our other views.
The first element we will add is the image of the artist. The image is included in our repository in the drawable folder as avicii.jpg
. Paste this snippet inside the ConstraintLayout
tag replacing any previous default views that may have existed there:
<ImageView
android:id="@+id/avinciiImage"
android:layout_width="wrap_content"
android:layout_height="260dp"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/avicii" />
As seen above, the image is constrained to the top of the layout, the start, and the end. The image has an height of 260dp
and a scaleType
of fitXY
, which means it stretches the image to fit the size of the ImageView
.
Next, we will add a View
, which we can customise to give the image an orange overlay. In the same file, paste the following code:
<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="260dp"
android:alpha="0.7"
android:background="#FF602D"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/avinciiImage" />
The view has the same height as the image and similar constraints. It has an orange background whose opacity is reduced slightly using the alpha
attribute. This view is constrained to the top of the image.
Notice, from the design, that the elements on the left side of the layout all start from the same point, so, instead of applying margins to each, we will use a guideline.
Add this snippet to your layout:
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="20dp" />
Above, we have a starting guideline of 20dp
. Since all the elements on the right end at the same point also, we will apply a guideline for that too.
To do this, add the following to your layout XML
:
<android.support.constraint.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="20dp" />
Finally, let’s add a horizontal guideline to the layout. To do this, add the following code to the XML layout file:
<android.support.constraint.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="20dp" />
At this point, your design should look like this:
Let’s start adding other views.
Switch back to the text view by clicking Text and then add the following ImageView
after the guideline we added above:
<ImageView
android:id="@+id/imageView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/guideline4"
app:srcCompat="@drawable/ic_close" />
Above, we used a vector drawable file and we referenced it using app:srcCompat
. The image is constrained to the top guideline and the left guideline.
Next, let’s create the vector drawable file we referenced above. Click File > New > Vector Asset. In the vector modal, set the name to ic_close
, and click the Clip Art button then search for the close icon. Next, set the color of the icon to #ffffff
then click Next > Finish.
Next, let’s add the TextView
to hold the name of the artist:
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Avincii"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline"
android:textColor="#FFF"
android:textSize="32sp"
app:layout_constraintBottom_toBottomOf="@+id/avinciiImage"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
In the design, this text is close to the center between the top guideline and the bottom of the image. So we added a top and bottom constraint to the view.
Next, let’s add the smaller text under the artist name. Add this snippet to your layout:
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Trance/ House"
android:textColor="#FFF"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/textView" />
For the START RADIO text add this snippet:
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="START RADIO"
android:textColor="#FFF"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/avinciiImage"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
This view is constraint to the bottom of the image, the starting left guideline and the bottom of the TextView
added before this.
After that, add the +FOLLOW text like this:
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="+FOLLOW"
android:textColor="#FFF"
android:textSize="18sp"
app:layout_constraintStart_toEndOf="@+id/textView3"
app:layout_constraintTop_toTopOf="@+id/textView3" />
This TextView
is constrained such that it starts at the end of the start radio text. It is also constrained to the top of the start radio TextView
, which means, its vertically aligned with it.
Next, let’s add the Top tracks text and the play icon using chains. Add this to your layout:
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Top tracks"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/imageView6"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/view" />
<ImageView
android:id="@+id/imageView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="@+id/textView5"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/textView5"
app:layout_constraintTop_toTopOf="@+id/textView5"
app:srcCompat="@drawable/ic_play_circle" />
These two views are chained using the spread_inside
chain mode. This means, they are attached to the end of the chain, in this case, the guidelines. If we had more than two views, the views inside would be spread evenly.
Next, let’s create the vector drawable file we referenced above. Click File > New > Vector Asset. In the vector modal, set the name to ic_play_circle
, and click the Clip Art button then search for the play circle outline icon. Next, set the color of the icon to #000
then click Next > Finish.
Next, we lets add more guidelines. Add this to your layout:
<android.support.constraint.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.2" />
<android.support.constraint.Guideline
android:id="@+id/guideline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.85" />
As we mentioned earlier, guidelines prevent repetitive margins. For the guidelines we created above, we opted to use percent.
Your layout should look like this now:
The first guideline is placed at the 20% of the layout and the second at 85%.
Next, let’s add an image for the first track as seen on the design we are implementing. We are using a circular image view. Add this to your snippet:
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/profile_image"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="8dp"
android:src="@drawable/album"
app:civ_border_color="#FF000000"
app:civ_border_width="2dp"
app:layout_constraintBottom_toBottomOf="@+id/textView7"
app:layout_constraintEnd_toStartOf="@+id/guideline5"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/textView6" />
The image above is constrained to the start guideline and it ends before the start of the 0.2
percent guideline. It is also constrained to the top tracks text.
Next, let’s add the name of the first track:
<TextView
android:id="@+id/textView6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Wake me up"
android:textColor="#232323"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/guideline6"
android:layout_marginStart="10dp"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
This textview is constrained to the start of the 0.2
percent guideline and a start margin of 10dp
was also added. It’s also constrained to end at the 0.85
percent guideline, and finally, it’s constrained to the bottom of top tracks text.
Next, let’s add a text under the song title:
<TextView
android:id="@+id/textView7"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="True"
android:layout_marginStart="10dp"
app:layout_constraintEnd_toStartOf="@+id/guideline6"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/textView6" />
We then add an horizontal line as seen in the design:
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:layout_marginTop="4dp"
android:background="#232323"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/profile_image" />
Next we need to add options icon for the track as seen in the design. To do this, add the following code to the layout file:
<ImageView
android:id="@+id/imageView7"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/textView7"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/guideline6"
app:layout_constraintTop_toTopOf="@+id/textView6"
app:srcCompat="@drawable/ic_more_vert" />
This icon is aligned to the bottom of the True text. That means it ends on the same vertical position as the text. It also starts on the same vertical position as the title of the song - Wake me up.
Next, let’s create the vector drawable file we referenced above. Click File > New > Vector Asset. In the vector modal, set the name to ic_more_vert
, and click the Clip Art button then search for the more vert icon. Next, set the color of the icon to #000
then click Next > Finish.
As seen in the design, we have two tracks. Since they have the same design, we just duplicated and made few constraint adjustments.
Add this to your layout:
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/profile_image2"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginTop="8dp"
android:src="@drawable/album"
app:civ_border_color="#FF000000"
app:civ_border_width="2dp"
app:layout_constraintBottom_toBottomOf="@+id/textView9"
app:layout_constraintEnd_toStartOf="@+id/guideline5"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/textView8" />
<TextView
android:id="@+id/textView8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Levels"
android:textColor="#232323"
android:textSize="15sp"
android:textStyle="bold"
android:layout_marginStart="10dp"
app:layout_constraintEnd_toStartOf="@+id/guideline6"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/view2" />
<TextView
android:id="@+id/textView9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="Stories"
android:layout_marginStart="10dp"
app:layout_constraintEnd_toStartOf="@+id/guideline6"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/textView8" />
<View
android:id="@+id/view3"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:layout_marginTop="4dp"
android:background="#232323"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline5"
app:layout_constraintTop_toBottomOf="@+id/profile_image2" />
<ImageView
android:id="@+id/imageView8"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="@+id/textView9"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/guideline6"
app:layout_constraintTop_toTopOf="@+id/textView8"
app:srcCompat="@drawable/ic_more_vert" />
Finally, let’s add the FloatingActionButton
like so:
<android.support.design.widget.FloatingActionButton
android:id="@+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
app:elevation="16dp"
app:backgroundTint="#FF602D"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:srcCompat="@drawable/ic_shuffle" />
Next, let’s create the vector drawable file we referenced above. Click File > New > Vector Asset. In the vector modal, set the name to ic_shuffle
, and click the Clip Art button then search for the shuffle icon. Next, set the color of the icon to #fff
then click Next > Finish.
You can remove the application toolbar by updating it in your styles.xml
file:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources>
Now, If you run your app, you should see this:
Conclusion
This ends our constraint layout part series. In this series, we have learned about Android’s most powerful layout system. In this part, we went through the process of building a layout from ground up using ConstraintLayout
.
You can find the repository for this project here.
17 September 2018
by Neo Ighodaro