Android Constraint Layout
Here's a short tutorial on how to use ConstraintLayout in Android.
Recommended reading
The reading below on this page is intended to just be an introduction to ConstraintLayout, and not a complete description of how to use all the functionality it contains. For all details about how to use it, check out the documentation for ConstraintLayout.
ConstraintLayout
The ConstraintLayout is a layout in which the children can be positioned relative to each other (a child can be positioned below another child, or above another child, or to the right of another child, etc.), or relative to the parent's edges (below the parent's top edge, or above the parent's bottom edge, or to the right of the parent's left edge, etc.). It is very similar to the RelativeLayout, but offers more functionality.
The ConstraintLayout is not part of the Android framework, but developed by Google in a separate library that is part of Android Jetpack. To add the library to your Android Studio Project, follow the instructions at the Declaring dependencies section.
Use the correct namespace!
Since the ConstraintLayout is not part of the Android framework, it does not put its own specific attributes in the XML namespace http://schemas.android.com/apk/res/android (usually called android), but instead in the namespace http://schemas.android.com/apk/res-auto, which one usually call app.
A child in ConstraintLayout can have layout_width and layout_height set to wrap_content/match_parent, in which case the child will have the size specified by these two attributes (as usual).
Example
Example showing how to add two Views to a ConstraintLayout.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
In the example above, we haven't told the ConstraintLayout where the children should be positioned, so both TextViews are positioned in top left corner by default (that's why we can't see the first TextView; it's behind the second TextView!).
To tell the ConstraintLayout where a child should be positioned horizontally, we can add one of the following attributes (known as a constraint) to the child:
app:layout_constraintLeft_toLeftOfapp:layout_constraintLeft_toRightOfapp:layout_constraintRight_toLeftOfapp:layout_constraintRight_toRightOf
The value can either be parent, or the id of one of the other child Views in the ConstraintLayout.
Similarly, to tell the ConstraintLayout where a child should be positioned vertically, we can add one of the following attributes to the child:
app:layout_constraintTop_toTopOfapp:layout_constraintTop_toBottomOfapp:layout_constraintBottom_toTopOfapp:layout_constraintBottom_toBottomOf
The value can either be parent, or the id of one of the other child Views in the ConstraintLayout.
Supporting Right-to-Left devices
To support layouts for people reading from right to left, use Start instead of Left and End instead of Right in the attribute names, e.g. use layout_constraintStart_toEndOf instead of layout_constraintLeft_toRightOf.
Example
Example showing how to position one View in the top right corner, and another View in the bottom left corner.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
Example
Example showing how to position two Views in the top right corner (one below the other).
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/first_text_view"
app:layout_constraintRight_toRightOf="parent"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
Example
Example showing how to position two Views diagonally in the top right corner.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/first_text_view"
app:layout_constraintRight_toLeftOf="@id/first_text_view"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
Repetition
To tell the ConstraintLayout where a child should be positioned horizontally, we can add one of the following attributes (known as a constraint) to the child:
app:layout_constraintLeft_toLeftOfapp:layout_constraintLeft_toRightOfapp:layout_constraintRight_toLeftOfapp:layout_constraintRight_toRightOf
The value can either be parent, or the id of one of the other child Views in the ConstraintLayout.
Similarly, to tell the ConstraintLayout where a child should be positioned vertically, we can add one of the following attributes to the child:
app:layout_constraintTop_toTopOfapp:layout_constraintTop_toBottomOfapp:layout_constraintBottom_toTopOfapp:layout_constraintBottom_toBottomOf
The value can either be parent, or the id of one of the other child Views in the ConstraintLayout.
Instead of giving a child it's size through the layout_width and layout_height attributes, you can specify two horizontal (or two vertical) constraints, and the child can get its width (or height) from the constraints instead. When a child has two horizontal constraints (or two vertical constraints) and you want the child to get its size through the constraints you should set the layout_width (or layout_height) to 0dp.
Example
Example showing how to position two Views next to each other horizontally:
- The first one is as small as possible
- The second one should occupy the rest of the remaining space
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_text_view"
app:layout_constraintRight_toRightOf="parent"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
If a child has a size smaller than what is specified by two horizontal/vertical constraints, the child will be centered instead of growing to cover the space.
Example
Example showing how to position two Views next to each other, and center the second View in the rest of the available space.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_text_view"
app:layout_constraintRight_toRightOf="parent"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
To control where in the rest of the available space the child is positioned (center by default), use the app:layout_constraintHorizontal_bias/app:layout_constraintVertical_bias attribute. The value is number between 0 and 1, where:
0means at the start- ...
0.5means in the middle (default)- ...
1means at the end
Example
Example showing how to position two Views next to each other, and placing the second View 90% to the right of the rest of the available space.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_text_view"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.9"
android:background="#0000ff"
android:text="Text 2" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
When you have a multiple children getting their sizes from the constraints in the same "chain", they by default get an equal amount of the remaining space available.
Example
Example showing how to position three Views next to each other, and let the last two share the remaining available space equally.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_text_view"
app:layout_constraintRight_toLeftOf="@id/third_text_view"
android:id="@+id/second_text_view"
android:background="#0000ff"
android:text="Text 2" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/second_text_view"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/third_text_view"
android:background="#ffff00"
android:text="Text 3" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
If you want the remaining space to be distributed differently among the children, you can use the attribute layout_constraintHorizontal_weight/layout_constraintVertical_weight to indicate how many shares of the remaining vertical space they should occupy.
Example
Example showing how to position three Views next to each other, and let the second occupy one third of the remaining space, and the third to occupy 2 thirds of the remaining space.
<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"
android:background="#ff0000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/first_text_view"
android:background="#00ff00"
android:text="Text 1" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_text_view"
app:layout_constraintRight_toLeftOf="@id/third_text_view"
app:layout_constraintHorizontal_weight="1"
android:id="@+id/second_text_view"
android:background="#0000ff"
android:text="Text 2" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/second_text_view"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_weight="2"
android:id="@+id/third_text_view"
android:background="#ffff00"
android:text="Text 3" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}
Bigger example
Example
Example showing how to use a <ConstraintLayout> to implement a layout with main content and a row with 3 navigation buttons at the bottom.
<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"
android:background="#ff0000">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/first_button"
app:layout_constraintLeft_toLeftOf="parent"
android:id="@+id/main_content_text_view"
android:background="#00ff00"
android:gravity="center"
android:text="I'm the main content!" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/main_content_text_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/second_button"
android:id="@+id/first_button"
android:text="Page 1" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/main_content_text_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/first_button"
app:layout_constraintRight_toLeftOf="@id/third_button"
android:id="@+id/second_button"
android:text="Page 2" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/main_content_text_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/second_button"
app:layout_constraintRight_toRightOf="parent"
android:id="@+id/third_button"
android:text="Page 3" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.app.Activity
import android.os.Bundle
class MyActivity : Activity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
}
}