Android Constraint Layout using Kotlin

Filed Under: Android

In this tutorial, we will discuss the Android ConstraintLayout attributes. We will learn how to position views based on constraints through XML layout and programmatically using Kotlin.

What is Android ConstraintLayout?

Android Constraint is RelativeLayout with additional features. They were introduced to prevent too many nested layouts. They flatten out the layouts.

Some of the constraint layout featrues are:

  • Positioning sides of a view relative to sides of another view.
  • ConstraintSets
  • Setting horizontal/vertical bias
  • Chaining and grouping views together
  • Barriers
  • Setting the percent of width or height the view would occupy on the screen.
  • Circular positioning the views.

Constraint Layout Dependencies

Please add the following dependency in your build.gradle file for constraint layout support.

implementation 'com.android.support.constraint:constraint-layout:1.1.2'

Let’s look into some examples of using constraint layout in android apps.

Positioning Views Relative to one another

Let’s drag and drop a view into the center of the screen.

android constraint layout xml basic

As you see in the above GIF, the Button is positioned in the center of the screen with each side having the constraint to the parent view.

We can remove either a single constraint or all as shown below.

android constraint layout remove constraints

The cross button is used to remove ALL constraints. Clicking the circle would remove the constraint of that specific side.

You can drag the same circle to create a new constraint.

setting constraints

Let’s look at the XML layout for the above design.

<?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">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintStart_toEndOf="@+id/button2"
        app:layout_constraintTop_toBottomOf="@+id/button2" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

The parent refers to the root view.

The list of XML attributes to position views by each other’s sides(top/left/bottom/right) is as follows.

android constraint layout xml attributes

We can align two views by their baselines as well.

constraint layout baseline

Let’s learn how to create constraints programmatically using Kotlin.

ConstraintSet

The ConstraintSet instance is defined to set the constraints programmatically.

The activity_main.xml does not contain anything inside the ConstraintLayout tag. Let’s look at the main activity Kotlin code.

package net.androidly.androidlyconstraintlayout

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.constraint.ConstraintLayout
import android.support.constraint.ConstraintSet
import android.widget.Button
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    val ID_1 = 1
    val ID_2 = 2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = Button(this)
        button.text = "Button"
        button.id = ID_1
        val lp = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT)
        button.layoutParams = lp
        constraintLayout.addView(button)

        val button2 = Button(this)

        button2.text = "Button2"
        button2.id = ID_2
        constraintLayout.addView(button2)

        val constraintSet = ConstraintSet()
        //Copy all the previous constraints present in the constraint layout.
        constraintSet.clone(constraintLayout)

        constraintSet.connect(ID_1, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP)
        constraintSet.connect(ID_1, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
        constraintSet.connect(ID_1, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT)
        constraintSet.connect(ID_1, ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT)

        constraintSet.connect(ID_2, ConstraintSet.BOTTOM, ID_1, ConstraintSet.TOP)
        constraintSet.connect(ID_2, ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT)
        constraintSet.connect(ID_2, ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT)
        constraintSet.applyTo(constraintLayout)

    }
}

The clone() function is used to copy all the previous constraints defined in the constraint layout.

In the above code, we are setting the first button in the center of the layout and the second button is on top of it.

The connect() function has an additional fifth parameter as well for margin values.

The equivalent of parent in XML layout is ConstraintSet.PARENT_ID.

Horizontal and Vertical Bias

android constraint layout bias

The attributes for setting bias are: app:layout_constraintVertical_bias and app:layout_constraintHorizontal_bias.

They expect a value between 0 and 1, and 0.5 is the default value.

Chaining and Grouping of Constraints

Chains are used to evenly space views horizontally or vertically.

android constraint layout chains

The xml layout code:

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toTopOf="@+id/button5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button4" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="Button"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread_inside" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />
</android.support.constraint.ConstraintLayout>

The chain styles can be of the following types.

  • spread
  • spread inside
  • packed
  • weighted

The weighted style requires setting weight on each of the views. The view with most weight occupies the most space.

The app:layout_constraintHorizontal_weight is used to set the weights in a horizontal chain.

Groups are used to toggle the visibility of a group of views together.

Add the following inside XML code to the previously defined constraint layout.

<android.support.constraint.Group
              android:id="@+id/group"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:visibility="invisible"
              app:constraint_referenced_ids="button4,button9" />

Barriers

A Barrier is used to create a virtual divider or a guideline on a group of views based on the largest view in the group.

This virtual divider can be connected with other child views.

android constraint layout barrier

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="TextView\nTextView\nTextView\nTextView\nTextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="TextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="textView, textView2" />

    <Button
        android:id="@+id/button7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/barrier" />

</android.support.constraint.ConstraintLayout>

ConstraintLayout Percentage Width and Height

Constraint Layouts support percentage width and height, just like LinearLayout.

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="TextView\nTextView\nTextView\nTextView\nTextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:text="TextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView\nTextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="textView, textView2"
        tools:layout_editor_absoluteY="331dp" />

    <Button
        android:id="@+id/button7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/barrier" />

</android.support.constraint.ConstraintLayout>

For percentage width, you have to set the Button’s width to 0dp and vice-versa for percentage height.

android constraint layout percentage width

Circular Positioning of Constraint Layout

We can position the views at radial distances and angles from one another. The app:layout_constraintCircle is used to reference the view, which would act as the center of the circle.

The app:layout_constraintCircleRadius and app:layout_constraintCircleAngle are used to set the radius distance from the center of the circle and the angle at which our view would be positioned.

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:text="Hello"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hi"
        android:textSize="18sp"
        app:layout_constraintCircleRadius="100dp"
        app:layout_constraintCircleAngle="45"
        app:layout_constraintCircle="@+id/textView"/>


    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Another"
        android:textSize="18sp"
        app:layout_constraintCircleRadius="100dp"
        app:layout_constraintCircleAngle="135"
        app:layout_constraintCircle="@+id/textView"/>


</android.support.constraint.ConstraintLayout>

constraint layout circular positioning

Leave a Reply

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

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages