Recap
As we have done LinearLayout in the past now we know the major factor that a view would prioritize LinearLayout is when:
- The view that we should make is simple.
- The view can be easily developed by
vertical
andhorizontal
orientation. - View does not have overlapping sub-views.
- Can be quickly made without thinking more about responsiveness.
- Can be imagined in a stack.
What if the view is complex? What if the view we should make has overlapping and inter-dependent sub-views?
Then we should use another view group knows as Constraint Layout.
ConstraintLayout
A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way.
Let's see the super basics of ConstraintLayout.
The image above shows views A,B,C inside a constraint layout. Constraint layout is totally about the relativeness
of the view to its environment views
and parent
.
Here the view A is constrained-top
(vertical) to its parent and constrained-start
(horizontal) to its parent. The A now has its horizontal
and vertical
constraint fulfilled and can be said to have valid constraint inside a ConstraintLayout.
To make a View be valid inside constraint layout, a view must ALWAYS have at least ONE HORIZONTAL
(start / end)
and ONE VERTICAL(top / bottom)
constraint.
View B also seems to be valid in the constraint layout as it as top
, start
and end
constraints. But View C only has start
and end
constraints. This is cause view to be invalid has C cannot define its vertical constraint in the constraint view.
To solve this we now define the top constraint for C as
Now this will be a valid ConstraintLayout with all views constrained.
Examples
To make constraint between two view components (a textview with another textview) we have to define id for the views. Below example shows a view with id
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/top_text"
android:textSize="27sp"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Android App Constraint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
- Here the TextView has
id
has top_text - Since it is inside a ConstraintLayout it has constraints fullfilment as:
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
Adding another view below the top_text
view in constraint layout
If we add the following code below the top_text component;
{Previous TextView Component Here}
<EditText
android:id="@+id/input_username"
android:hint="Username"
android:layout_marginTop="30dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_text"
android:layout_marginHorizontal="30dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
We can now have
- A new EditText view with id as
input_username
- has constraint below the
top_text
asapp:layout_constraintTop_toBottomOf="@id/top_text"
which defines that this view must have its TOP joined to BOTTOM of thetop_text
view - horizontal constrained are defined normally as
app:layout_constraintStart_toStartOf="parent"
andapp:layout_constraintEnd_toEndOf="parent"
Flexibility
If we want to put views in horizontal or vertical or nested forms, while using LinearLayout we should change orientations every time but for ConstraintLayout, just defining relative constraints is enough. ConstraintLayout solves the complexity of a view in a very flexible manner and we use this ViewGroup in 80% of the cases.
Examples in Git
You can refer to ConstraintLayout examples in learning MAD github project under the 02-constraint-layout branch.
Complete Example
Suppose you as a developer have to design a view given as
Visualization
- So on the first look I am seeing that the whole card component has some kind of radius, this is possible to achieve by using something called
CardView
- Then I can see that there are two sections, blue section with some details on it and white section with
ImageView
, some details andButtons
- So I will be making this view using the above visualized components along with ConstraintLayout
So the Appointment Card Component needs to be designed with:
- ConstraintLayout
- ImageView
- CardView
- MaterialButton (2021)
You can make a new file to make this component by right clicking on
layout
folder insideres
folder and selectinglayout resource file
. Give it a name aslayout_card_component
.
XML Code
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:layout_margin="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/main_card_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardCornerRadius="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#345EDC">
<TextView
android:id="@+id/text_appointment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Appointment Request"
android:textColor="@color/white"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/image_clock"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:src="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/text_appointment"
app:layout_constraintTop_toBottomOf="@id/text_appointment" />
<TextView
android:id="@+id/text_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="12 Jan 2020, 8am - 10am"
android:textColor="@color/white"
android:textSize="17sp"
app:layout_constraintBottom_toBottomOf="@id/image_clock"
app:layout_constraintStart_toEndOf="@id/image_clock"
app:layout_constraintTop_toTopOf="@id/image_clock" />
<ImageView
android:layout_width="10dp"
android:layout_height="30dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="25dp"
android:src="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/text_appointment" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/avatar"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:src="@color/purple_200"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/name"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:lines="2"
android:maxWidth="80dp"
android:text="Louis Patterson"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="@id/avatar"
app:layout_constraintEnd_toStartOf="@id/info"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="@id/avatar" />
<ImageView
android:id="@+id/info"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="30dp"
android:src="@color/purple_200"
app:layout_constraintBottom_toBottomOf="@id/avatar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/avatar" />
<com.google.android.material.button.MaterialButton
android:id="@+id/accept"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:backgroundTint="#FF345EDC"
android:text="ACCEPT"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/decline"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/avatar" />
<com.google.android.material.button.MaterialButton
android:id="@+id/decline"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:backgroundTint="#9E9E9E"
android:text="DECLINE"
app:cornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/accept"
app:layout_constraintTop_toTopOf="@id/accept" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
I have not used any images or extra views to make sure that when you copy and paste the above code will run without any problems.
Assignment 03
Try Making this page!
Best of Luck~
Submitting assignments must be done via github, please make the repository public so that I can see the task.