Android ViewGroups : LinearLayout, RelativeLayout

Filed Under: Android

Today we’ll be discussing two important ViewGroups: LinearLayout, RelativeLayout.
ViewGroup is a container to hold views. All activity, fragment layouts generally are ViewGroups
ViewGroups are extended from Views and are specifically used as containers.

Following are some of the common ViewGroups in Android:

  • LinearLayout
  • RelativeLayout
  • FrameLayout
  • TableLayout
  • CoordinatorLayout
  • ConstraintLayout

Android LinearLayout

LinearLayout is a ViewGroup that aligns all of its child views in one direction: vertically or horizontally.
The android:orientation attribute is used to set the direction in xml.

Horizontal LinearLayout


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_green_light"
        android:text="Button 1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_purple"
        android:text="Button 1" />

</LinearLayout>

By default the orientation is horizontal and the gravity is left aligned.
android-kotlin-horizontal-linearlayout

Vertical LinearLayout


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:gravity="end"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_green_light"
        android:text="Button 1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_purple"
        android:text="Button 1" />

</LinearLayout>

The gravity end represents right. We can use right or end interchangeably. Similarly for left gravity we can use start. start and end are the preferred values to ensure that the layout behaviour is correct in right to left locales.
android:gravity can have either of the following : left, start, right, end, top, bottom, center, center_horizontal, center_vertical.

This is how right aligned Vertical LinearLayout looks:

Layout Weights

LinearLayout allows us to set weights on the child views that’ll signify the share of width or height that particular view uses from its parent view.
For this, we need to specify android:weightSum to the LinearLayout and android:layout_weight attributes in the child view.

To create a LinearLayout with each of the child views with equal width we do the following in our XML Layout.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:weightSum="3"
    android:layout_height="match_parent">

    <Button
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_green_light"
        android:text="Button 1" />

    <Button
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 2" />

    <Button
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button 3" />

</LinearLayout>
  • With the layout_weight set on the child views, we need to assign the width as 0dp since the widths would be automatically calculated using the Layout Weights in LinearLayout.
  • Similarly, if the orientation is vertical and Layout Weights are specified, we need to specify the layout_height as 0dp since it’ll be calculated automatically from the layout_weight attribute.

android-kotlin-linearlayout-weighted

Nested LinearLayout

The following XML layout example shows Nested Layouts, horizontal and vertical with the Layout Weights placed.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="3">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"
        android:weightSum="0.8">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.4"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.2"
            android:src="@mipmap/ic_launcher" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.2"
            android:src="@mipmap/ic_launcher" />

    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1.2"
        android:gravity="center"
        android:weightSum="1.5">

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:layout_weight="0.5"
            android:background="@android:color/holo_green_light"
            android:text="Button 1" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.6"
            android:text="Button 2" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|right"
            android:layout_weight="0.4"
            android:text="Button 3" />


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:weightSum="1.5">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.4"
            android:background="@android:color/holo_green_light"
            android:text="Androidly 1" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.7"
            android:background="@android:color/black"
            android:gravity="center"
            android:text="Androidly 2"
            android:textColor="@android:color/white" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.4"
            android:background="@android:color/holo_purple"
            android:text="Androidly 3"
            android:textColor="@android:color/white" />


    </LinearLayout>

</LinearLayout>

We’ve set layout weights on each of the child LinearLayouts. The gravity attribute is used to set the gravity of all the child views. The layout_gravity is used to set the gravity of a ChildView relative to the layout.

The output looks like this:
android-kotlin-nested-layouts

LinearLayout Programmatically

We can do the above XML stuff in our Kotlin Activity class too.
We can add the buttons in the LinearLayout using addView() function on the instance. It’ll attach the view passed to the end of the layout.
To add the child view in a particular position in our LinearLayout we can pass the index as the second argument in our addView() function.

Let’s say our activity_main.xml code in our Android Studio Kotlin Project looks like this:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal"
    android:weightSum="3">


</LinearLayout>

The following code adds child views in the LinearLayout Programmatically in our MainActivity.kt class.


package net.androidly.androidlylayouts

import android.graphics.drawable.GradientDrawable
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutCompat
import android.widget.Button
import kotlinx.android.synthetic.main.activity_main.*
import android.widget.LinearLayout


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        linearLayout.weightSum = 3f
        linearLayout.orientation = LinearLayout.VERTICAL


        val params = LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, 0)
        params.weight = 1f

        var button = Button(this)
        button.text = "Androidly Button 1"
        button.setBackgroundColor(ContextCompat.getColor(this, android.R.color.holo_purple))
        button.layoutParams = params


        linearLayout.addView(button)

        button = Button(this)
        button.text = "Androidly Button 2"
        button.setBackgroundColor(ContextCompat.getColor(this, android.R.color.holo_green_dark))
        button.layoutParams = params
        linearLayout.addView(button, 0)

        button = Button(this)
        button.text = "Androidly Button 3"
        button.setBackgroundColor(ContextCompat.getColor(this, android.R.color.holo_red_dark))
        button.layoutParams = params
        linearLayout.addView(button, linearLayout.childCount - 1)
    }
}

Setting weightSum property programmatically requires a floating value.
For each of the Buttons, we’ve created a LayoutParams instance in which we’ve set the layout_weight using the property weight, again a floating value.
To get the current number of child views present in the LinearLayout, we use the property childCount.

The output looks like this:
android-kotlin-linearlayout-programmatically
We’ve set the second button on the top, and the third button at the index one less that childcount(3-1=2), hence it comes up in the middle and the the first button is at the bottom.

Android RelativeLayout

RelativeLayout as the name suggests is used to align the views relative to each other as well as relative to it’s parent view.
An xml layout using RelativeLayout with child views aligned to parents is given below.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    

    <Button
        android:text="Center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />


    <Button
        android:text="Center-H"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

    <Button
        android:text="Center-V"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true" />

    <Button
        android:text="Center-VR"
        android:layout_width="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentEnd="true" />

    <Button
        android:text="Parent-BL"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />


    <Button
        android:text="Parent-RT"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true" />

    <Button
        android:text="Parent-LT"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    
</RelativeLayout>

By default in a RelativeLayout, a view would be positioned at top-left.

  • layout_centerVertical = true sets the view in the vertical center. By default, it’ll be the left aligned.
  • layout_centerHorizontal = true sets the view in the horizontal center. By default, it’ll be the top aligned.
  • layout_centerInParent = true sets the view in the horizontal and vertical center of the parent.
  • layout_alignParentEnd/Right = true aligns the view to the right end of the view.

android-kotlin-relative-layout-parent-aligned

Can you try the setting buttons at those positions yourself?

Relative to siblings

  • layout_above = “@+id/sibling_id” is used to set the current child above the sibling.
  • layout_below sets it below.
  • layout_alignLeft/layout_alignStart = "@+id/sibling_id" aligns the left margins of the current child with the sibling
  • layout_alignRight/layout_alignEnd = "@+id/sibling_id" aligns the right margins of the current child with the sibling.
  • Similarly alignBottom and alignTop align for the bottom and top respectively.
  • android:layout_toEndOf/android:layout_toRightOf = "@+id/sibling_id" puts the child to the right of the sibling.
  • android:layout_alignBaseline="@+id/sibling_id" aligns the bottom baseline.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:text="1"
        android:background="@android:color/holo_red_dark"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />


    <Button
        android:id="@+id/button2"
        android:text="2"
        android:background="@android:color/holo_blue_dark"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button1" />


    <Button
        android:id="@+id/button3"
        android:text="3"
        android:background="@android:color/darker_gray"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button4" />

    <Button
        android:id="@+id/button4"
        android:text="4"
        android:background="@android:color/holo_orange_light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button1"
        android:layout_alignRight="@+id/button1"
        android:layout_alignEnd="@+id/button1"/>

    <Button
        android:id="@+id/button5"
        android:text="5"
        android:background="@android:color/holo_purple"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/button2"
        android:layout_toEndOf="@+id/button2"
        />

    <Button
        android:id="@+id/button6"
        android:text="6"
        android:background="@android:color/holo_green_light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/button2"
        android:layout_toEndOf="@+id/button2"
        android:layout_alignBaseline="@+id/button2"
        />

</RelativeLayout>

android-kotlin-relative-layout-sibling-aligned

RelativeLayout Programmatically

We can set the child views using rules in our Kotlin Activity class.
Following is our activity_main.xml class:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


</RelativeLayout>

The MainActivity.kt class is given below


package net.androidly.androidlylayouts


import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.RelativeLayout
import kotlinx.android.synthetic.main.activity_main.*
import android.view.ViewGroup


class MainActivity : AppCompatActivity() {

    val ID_1 = 1
    val ID_2 = 2
    val ID_3 = 3


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

        var button = Button(this)
        button.text = "1"
        button.id = ID_1

        val lp = RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT)
        lp.addRule(RelativeLayout.CENTER_IN_PARENT)


        button.layoutParams = lp

        relativeLayout.addView(button)

        button = Button(this)
        button.text = "2"
        button.id = ID_2

        val params = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        params.addRule(RelativeLayout.BELOW, ID_1)
        button.layoutParams = params

        relativeLayout.addView(button)

        button = Button(this)
        button.text = "3"
        button.id = ID_3

        val lp2 = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        params.addRule(RelativeLayout.LEFT_OF, ID_2)
        button.layoutParams = lp2

        relativeLayout.addView(button)

    }
}

We need to use addRule to set the child relative to parents and each other.

This brings an end to this tutorial on LinearLayout and RelativeLayout. Now we can create them in XML as well as Programmatically in our Kotlin classes in Android.

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