A Comprehensive Guide to Views in Android

A Comprehensive Guide to Views in Android

ยท

14 min read

Introduction

A View is a simple building block of a user interface. It is a small rectangular box that can be TextView, EditText, or even a button. It occupies the area on the screen in a rectangular area and is responsible for drawing and event handling.

View is a superclass of all the graphical user interface components.

open class View : Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource

where android.view.ViewGroup is the subclass is the base class for layouts

Here are some common subclasses of View in Android:

SubclassDescription
TextViewUsed to display text on the screen.
ImageViewUsed to display images or drawables.
ButtonUsed to trigger actions when clicked.
EditTextUsed to accept user input as text.
CheckBoxUsed to represent a binary choice (checked or unchecked).
RadioButtonUsed to represent a single choice from a group of options.
ProgressBarUsed to show the progress of an operation.
SeekBarUsed to select a value from a range by sliding the end
ListViewUsed to display a scrollable list of items.
RecyclerViewA more flexible and efficient version of ListView for displaying large datasets.

๐Ÿ’ฌ Understanding TextView in Android

Android TextView is simply a view that is used to display the text to the user and optionally allows us to modify or edit it.

The TextView class inherits from the View class & the ViewTreeObserver class

open class TextView : View, ViewTreeObserver.OnPreDrawListener

TextView inherits all the attributes of View Class & some common XML attributes for TextView are :

  • android:allowUndo controls, whether undo, is allowed to textview or not.

  • android:autoLink converts links to clickable links

  • android:autoText autocorrects the textual input

  • android:capitalize capitalizes the textual input

  • android:digits specifies numeric input to text

  • android:drawable<Location> specifies drawable at the location in the textview

  • android:drawablePadding adds padding to the drawable

  • android:ellipsize causes words that are longer than the view is wide to be ellipsized instead of broken in the middle

  • android:ems makes the TextView be exactly this many ems wide.

  • android:fontFamily specifies the font family for the text

  • android:gravity specifies how to align the text in the view, when the text is smaller than the view

  • android:hint specifies the hint msg to display when no text

  • android:inputType specifies the input type of the textview

  • android:password makes the characters displayed as a dot

  • android:text specifies the text to display

  • android:textColor android:textColorHighlight android:textColorHint android:textColorLink specify the text color

  • android:textSize android:textStyle specify the text appearance


Demonstration of TextView :

<androidx.constraintlayout.widget.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">

    <LinearLayout
        android:id="@+id/homeScreen"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        //textViews

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Here 3 different text views are taken under the LinearLayout which demonstrates almost all the possible XML attributes discussed:

<TextView
    android:id="@+id/introText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="100dp"
    android:text="this is an introduction to text views"
    android:paddingLeft="10dp"
    android:fontFamily="@font/sanfro"
    android:textStyle="bold"
    android:textSize="30sp"/>

gives a margin of 100dp with the top of the layout
adds a padding of 10dp at the left within the textview
assigns font family to the textView which is located inside the res/fonts directory named sanfro
makes the text bold and of 30sp

<TextView
    android:id="@+id/descText"
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_gravity="center"
    android:layout_marginTop="50dp"
    android:text="multi line text view in android, has some special attributes"
    android:textSize="20sp"
    android:textStyle="italic"
    android:textColor="#ff90"
    android:ellipsize="end"
    android:ems="3"/>

makes the view come to the centre of the layout
give a margin of 50dp with the textbox above it
assign the text size, colour and style

<TextView
    android:id="@+id/textImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    android:paddingLeft="20dp"
    android:text="text with drawable/image"
    android:textStyle="bold"
    android:textSize="24sp"
    android:drawableRight="@drawable/ic_launcher_background"
    android:drawablePadding="10dp"/>

adds a 50dp margin with the textbox above it
adds a padding of 20dp to the left within the textbox
gives text style and size
adds a drawable file at the right located in the res/drawable directory
add padding to the drawable within the textview

Demonstration of TextView in the functional Kotlin code :

import android.util.Log
import android.widget.TextView

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

        val textView = findViewById<TextView>(R.id.descText)
//we refer textView variable to the TextView resource with id descText
        val text  = textView.text.toString()
//we get is text and convert it into string using the toString() method
        Log.d("msg: ", text)
//we return that text in the logcat

        val heading = findViewById<TextView>(R.id.introText)
//we refer heading variable to the TextView resource with id introText
        heading.text = "Hi ${10/5}"
//we set the resource text

    }
}

โฏ๏ธ Understanding Button in Android

Android Button is a widget that is used to notice interactions and trigger actions in the application.

The Button Class extends the TextView class in Kotlin.

open class Button : TextView

Button inherits all the XML attributes of TextView and View class & some common XML attributes are :

  • android:onClick specifies the Kotlin function that is invoked in the activity when the button is clicked

  • android:background sets the background color/drawable on the Button.


Demonstration of Button :

<androidx.constraintlayout.widget.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">

    <TextView ... />

    <Button
        android:id="@+id/boldBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="BOLD"
        android:textColor="@color/white"
        android:layout_marginTop="45dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <TextView ... />


</androidx.constraintlayout.widget.ConstraintLayout>

Here our Root View is the constraint layout, that enables us to define layouts based on constraints to other layouts.

Demonstration of Button in the functional Kotlin code :

  • setOnClickListener - triggers when a button is clicked.

  • setOnLongClickListner - triggers when a button is pressed for a longer duration. requires an ending false boolean value to trigger. if true, doesn't trigger.

The curly brackets following the two click listeners are lambda expressions.

import android.graphics.Typeface
import android.os.Bundle
import android.widget.Button
import android.widget.TextView

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

        val boldButton = findViewById<Button>(R.id.boldBtn)
        val textbox = findViewById<TextView>(R.id.textView)

        boldButton.setOnClickListener{
//sets the text to bold
            textbox.setTypeface(null, Typeface.BOLD)
        }

        boldButton.setOnLongClickListener{
//changes the text
            textbox.text = "Bye!"
            false
//trigger the LongClickListener
        }
    }
}

โœ๏ธ Understanding EditText in Android

Android EditText is a user interface control that allows the user to enter or modify the text.

The EditText class inherits from the TextView Class

open class EditText : TextView

EditText inherits all the XML attributes of TextView and View class & some common attributes of EditText are :

  • android:inputType specifies the input type required. date, text, number. etc.

Demonstration of EditText :

<androidx.constraintlayout.widget.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">

    <EditText
        android:id="@+id/usernameET"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:hint="Username"
        android:inputType="text"
        android:layout_marginTop="100dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button ... />

</androidx.constraintlayout.widget.ConstraintLayout>

Here our Root Element in Constraint Layout, which has an EditText and a Button. The EditText has a text input type and a hint for the user to input a username.

Demonstration of EditText in the functional Kotlin code :

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText

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

        val inputUsername = findViewById<EditText>(R.id.usernameET)
        val btn = findViewById<Button>(R.id.btn)

        btn.setOnClickListener{
            val username = inputUsername.text.toString()
//storing the input in the username variable
            Log.d("Username: ", username)
//displaying the username value in the logcat
        }
    }
}

๐ŸŒ… Understanding ImageView in Android

Android ImageView is a user interface control that is used to display any type of image resource in the application.

ImageView class is a direct subclass of the Kotlin View Class

open class ImageView : View

Some common XML attributes for ImageView are :

  • android:adjustViewBounds adjust the bounds of the drawable to maintain its aspect ratio

  • android:cropToPadding crops the image to fit within the padding

  • android:maxHeight gives a maximum height to the View

  • android:maxWidth gives a maximum width to the View

  • android:scaleType specifies how the image should be resized or moved to match the view's size. Values include center, centerCrop, fitCenter, etc.

  • android:src specifies the drawable to set in the view

  • android:tint sets the tinting color of the image


Demonstration of ImageView :

<androidx.constraintlayout.widget.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">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/black"
        android:src="@drawable/ic_launcher_foreground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:tint="@color/white" />

    <Button ... />

</androidx.constraintlayout.widget.ConstraintLayout>

Here the Root Element is a Constraint Layout which has an ImageView and a Button. The ImageView has a default image named ic_launcher_foreground in the res/drawable directory.

Demonstration of ImageView in the functional Kotlin code :

import android.os.Bundle
import android.widget.Button
import android.widget.ImageView

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

        val image = findViewById<ImageView>(R.id.imageView)
        val btn = findViewById<Button>(R.id.changeBtn)

        btn.setOnClickListener{
            image.setImageResource(R.drawable.person)
//image resource should be stored in drawable folder
//change image resource of imageview to R.drawable.person on button click
        }
    }
}

๐Ÿฉป Understanding ImageButton in Android

Android ImageButton is a widget that is used to display a button having an image.

The ImageButton class inherits from the ImageView class

open class ImageButton : ImageView

ImageButton works exactly like a android.widget.Button, and the image on the button is added using android:src attribute or the setImageResource(int) method.

ImageButton inherits all the XML attributes of ImageView and View class


โœ… Understanding CheckBox in Android

Android CheckBox is a common widget that works as a Button and has two states, checked & unchecked.

The CheckBox class inherits from the CompoundButton class which is further inherited from the Button class

open class CheckBox : CompoundButton

CheckBox inherits all the XML attributes of TextView,View, Button & Compound Button class & some common attributes of CompoundButton are :

  • android:checked which specifies the initial checked state of the button

Demonstration of Checkbox :

<androidx.constraintlayout.widget.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">

    <TextView ... />

    <CheckBox
        android:id="@+id/pannerCheck"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Panner"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="-270dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <CheckBox
        android:id="@+id/cheeseCheck" .. />

    <CheckBox
        android:id="@+id/mushCheck" ..  />

</androidx.constraintlayout.widget.ConstraintLayout>

Here we define 3 Checkbox under our Root View Element.

Demonstration of CheckBox in the functional Kotlin code :

import android.os.Bundle
import android.util.Log
import android.widget.CheckBox

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

        val panner = findViewById<CheckBox>(R.id.pannerCheck)
        val cheese = findViewById<CheckBox>(R.id.cheeseCheck)
        val mushroom = findViewById<CheckBox>(R.id.mushCheck)

        panner.setOnCheckedChangeListener{ _, isChecked ->
            val text = "You want the following toppings: " + (if (isChecked) "Panner" else "") + (if (cheese.isChecked) "Cheese" else "") + (if (mushroom.isChecked) "Mushroom" else "")
            Log.d("Order: ", text)
        }
//following method is called when the state of the checkbox is changed
//where _ represents the compound button whose state is changed
//isChecked returns the state as a boolean value
//followed by a lambda expression 

        cheese.setOnCheckedChangeListener{ _, isChecked ->
            val text = "You want the following toppings: " + (if (panner.isChecked) "Panner" else "") + (if (isChecked) "Cheese" else "") + (if (mushroom.isChecked) "Mushroom" else "")
            Log.d("Order: ", text)
        }

        mushroom.setOnCheckedChangeListener{ _, isChecked ->
            val text = "You want the following toppings: " + (if (panner.isChecked) "Panner" else "") + (if (cheese.isChecked) "Cheese" else "") + (if (isChecked) "Mushroom" else "")
            Log.d("Order: ", text)
        }
    }
}


๐Ÿ•น๏ธ Understanding ToggleButton in Android

Android, ToggleButton is just like a switch containing two states either ON or OFF, unlike switch, it doesn't have a slider.

The ToggleButton class inherits from the CompoundButton class which is further inherited from the Button class

open class ToggleButton : CompoundButton

ToggleButton inherits all the XML attributes of TextView,View, Button & Compound Button class & some common attributes of ToggleButton are :

  • android:textOff specifies text when the button is off

  • android:textOn specifies text when the button is on

  • android:disabledAlpha specifies the alpha to apply to the indicator when disabled.


Demonstration of ToggleButton :

<androidx.constraintlayout.widget.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">

    <ToggleButton
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textOff="Off"
        android:textOn="On"
        android:textSize="32sp"
        android:disabledAlpha="0.5"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Demonstration of ToggleButton in the functional Kotlin code :

import android.os.Bundle
import android.util.Log
import android.widget.ToggleButton

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

        val btn = findViewById<ToggleButton>(R.id.btn)
        btn.setChecked(true)
//sets the state of the Button to ON
        btn.setOnCheckedChangeListener{ _, isChecked ->
            Log.d("Status:","You turned it" + (if (isChecked) "On" else "Off"))
        }
//following method is called when the state of the togglebutton is changed
//where _ represents the toggle button whose state is changed
//isChecked returns the state as a boolean value
//followed by a lambda expression 
    }
}

๐ŸŽš๏ธ Understanding Spinner in Android

Android Spinner is used to create a drop-down list on the screen. The spinner is loaded with data using an Adapter. The adapter sets the data as well as the layout for the items to be loaded in the Spinner.

The spinner class inherits from the AbsSpinner and DialogInterface.OnClickListener class

open class Spinner : AbsSpinner, DialogInterface.OnClickListener

Some common XML attributes for Spinner are :

  • android:entries which specifies the entries of the spinners dialog, if the entries are stored in the strings.xml file from the res/values directory
    which is inherited from the AbsSpinner Attributes

  • android:popupBackground which specifies the background drawable for the dropdown popup

  • android:prompt which specifies the prompt to display when the spinner dialog is shown i.e the heading of the dialog

  • android:spinnerMode which specifies the display mode for spinner options. 0 for dialog mode, and 1 for a dropdown list


Demonstration of Spinner :

Ways of linking data to the Spinners dialog :

<resources>
    <string name="app_name">spinner</string>
    <string-array name="gender">
        <item>Male</item>
        <item>Female</item>
    </string-array>
</resources>

adding data items to the strings.xml file in the res/values directory, in the form of a string array.

This string array can be linked to the spinner using the XML attribute :

<Spinner .. android:entries="@array/gender" .. />

Or in the Kotlin code file using the Adapter :

import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.Spinner

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

        val spinner = findViewById<Spinner>(R.id.spinner)
        val valuesGender = resources.getStringArray(R.array.gender)
//specify variable to our string array resource using 
//resources.getStringArray(int) method

        if (spinner != null) {
//we create an adapter, which is used to easily bind data 
//items to spinner objects
            val adapter = ArrayAdapter( this, android.R.layout.simple_spinner_item, valuesGender)
//using the ArrayAdapter method
//which takes (context, resource, objects) as values
            spinner.adapter = adapter
//setting the adapter to the spinner object
        }
    }
}

The data can also be linked directly from the Kotlin Code file by creating an array or list object and specifying the adapter and spinner all in the same block :

import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.Spinner

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

        val spinner = findViewById<Spinner>(R.id.spinner)

        val genderList = listOf("Male","Female")
        val adapter = ArrayAdapter<String>(this, com.google.android.material.R.layout.support_simple_spinner_dropdown_item, genderList)
        spinner.adapter = adapter

    }
}

Demonstration of Spinner in the functional Kotlin code :

When the user selects an item from the spinner's menu, the Spinner object receives an on-item-selected event. To define the selection event handler for a spinner, we need to implement the AdapterView.OnItemSelectedListener interface and the corresponding onItemSelected() callback method.

spinner.onItemSelectedListener = object :AdapterView.OnItemSelectedListener{
            override fun onItemSelected(adapter: AdapterView<*>?, view: View?, position: Int, id: Long) {
// An item is selected. You can retrieve the selected item using
// adapter.getItemAtPosition(position).
// position specifies the index of the data selected
                Toast.makeText(this@MainActivity, "You selected ${adapter?.getItemAtPosition(position).toString()}",Toast.LENGTH_SHORT).show()
//here we need to specify this@MainActivity 
//as we are inside an anonymous class
            }

            override fun onNothingSelected(adapter: AdapterView<*>?) {
                TODO("Not yet implemented")
            }
        }

๐ŸŽ›๏ธ Understanding RadioButton & RadioGroup in Android

Android Radio buttons let the user select one option from a set of mutually exclusive options. Because radio buttons are mutually exclusive, group them inside a RadioGroup widget i.e. android.widget.RadioGroup. The system ensures that only one radio button within a group can be selected at a time.

The RadioButton class inherits from the CompoundButton class which is further inherited from the Button class

open class RadioButton : CompoundButton

When several radio buttons live inside a radio group, checking one radio button unchecks all the others.

RadioButton inherits all the XML attributes of TextView,View, Button & Compound Button class


The RadioGroup inherits from the LinearLayout class

open class RadioGroup : LinearLayout

RadioGroup inherits all the XML attributes of ViewGroup, View & LinearLayout class & some common attributes of RadioGroup are :

  • android:orientation specifies the orientation of the child radio buttons

  • android:checkedButton specifies the default checked radio button


Demonstration of RadioButton & RadioGroup :

<androidx.constraintlayout.widget.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">

    <RadioGroup
        android:id="@+id/btnHead"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#dbeceb" .. >

        <TextView .. />

        <RadioButton
            android:id="@+id/wish1btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="10dp"
            android:paddingLeft="5sp"
            android:text="Wish 1"
            android:textSize="22sp"
            android:textStyle="bold" />

        <RadioButton .. />
        <RadioButton .. />
        <Button .. />
    </RadioGroup>

</androidx.constraintlayout.widget.ConstraintLayout>

Demonstration of RadioButton & RadioGroup in the functional Kotlin code :

import android.util.Log
import android.widget.Button
import android.widget.RadioButton
import android.widget.RadioGroup

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

        val submit = findViewById<Button>(R.id.submitBtn)
        val radioGroupWish = findViewById<RadioGroup>(R.id.btnHead)

//getting radio group selected status and text using button click event
        submit.setOnClickListener{
            val checkedButtonID = radioGroupWish.checkedRadioButtonId 
//radioGroup.checkedRadioButtonID returns the ID of the radiobutton checked
            val checkedButton = findViewById<RadioButton>(checkedButtonID)
            Log.d("Order: ",checkedButton.text.toString())
        }
    }
}

import android.os.Bundle
import android.util.Log
import android.widget.RadioButton
import android.widget.RadioGroup

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val radioGroupWish = findViewById<RadioGroup>(R.id.btnHead)

//getting radio group selected item using on checked change listener 
        radioGroupWish.setOnCheckedChangeListener(
            RadioGroup.OnCheckedChangeListener { _, checkedId ->
                val checkedBtn =  findViewById<RadioButton>(checkedId)
                Log.d("Order: ",checkedBtn.text.toString())
            })
    }
}


ย