Android UI Essentials: Crafting Stunning & Interactive Interfaces
Comprehensive Guide to Views, Attributes, and Custom Drawables for Better Android Interfaces
Table of contents
Introduction to UI in Android
XML - eXtensible Markup Language is a markup language used to create layouts for application screen in Android Development.
Layout defines the structure of the User Interface in our application. Layout in Android is built using a combination of Views
and ViewGroup
. Layouts contain one and only one Root View
Element, that is the parent of all the child Views
and ViewGroups
.
View - a single building block of screen ui : acts as an element, which can display something at the interface or handle an event. Objects of view class are called
Widgets
Example - Text, ImageView, Button, etc.
ViewGroup - acts as an invisible container, which gives a layout to the view and
viewgroups declared under it. Objects of the ViewGroup class are called
Layouts
Example - ListView, GridView, LinearLayout, etc.
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 ofView
and is the base class for layouts.
<?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" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>
The above layout file consists of LinearLayout as the root element and it holds the TextView and Button element.
XML files are located inside the res/layout/
directory.
During the compilation of the application each XML layout file is compiled into a
View
resource. Load the layout resource in your app'sActivity.onCreate()
callback implementation. Do so by callingsetContentView()
, passing it the reference to your layout resource in the form:R.layout.layout_file_name
.
fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_layout)
}
Attributes
Every View and ViewGroup object has its own variety of XML attributes. Some attributes are specific to a View object. And some are common to all View objects because they are inherited from the root View
class, like the id
attribute.
Other attributes are layout parameters
, which are attributes that describe layout orientations of the View
object.
ID
Each View object has an integer ID associated with it, that uniquely identifies that View object. During the app compilation, an integer ID is assigned to the string ID given in the XML format.
<LinearLayout android:id="@+id/my_button" />
/* here @ indicates that it needs to be identified as an ID resource
+ indicates a new resource name that must be created and added
to the resources in the R.java file.
An ID doesn't need to be unique throughout the entire tree, but it must be unique within the part of the tree you search. It might often be the entire tree, so it's best to make it unique when possible.
Views can be referenced in the application by creating an instance of that View object and capturing it from the layout file.
val addButton: Button = findViewById(R.id.addBtn)
// here addBtn is the ID given in the XML file
Layout Parameters
Define layout parameters for the View that are appropriate for the ViewGroup it resides in. Every ViewGroup class implements a nested class that extends ViewGroup.LayoutParams
. This subclass contains property types that define the size and position of each child view based on that ViewGroup.
All view groups include a width and height, using layout_width
and layout_height
, and each view is required to define them.
You can specify width and height with exact pixel measurement, but more often we use :
wrap_content
: tells your view to size itself to the dimensions required by its content.match_parent
: tells your view to become as big as its parent view group allows.density-independent pixel units (
dp
)
Padding & Margins
Padding is used to offset the content of the view. However, the margin specifies the extra space the view takes inside the parent.
Padding can be set using the setPadding(int, int, int, int)
method and queried by calling getPaddingLeft()
, getPaddingTop()
, getPaddingRight()
, and getPaddingBottom()
.
However, it is more convenient to set them using the XML format.
<?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" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:padding="8dp"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:paddingBottom="4dp"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:paddingTop="4dp"
android:text="Hello, I am a Button" />
</LinearLayout>
More XML attributes under View
Class
android:alpha | float value: transparency value of view, for code: View.setAlpha(float) |
android:autoHandwritingEnabled | boolean value: stylus movement within view will trigger handwriting mode, for code: View.setAutoHandwritingEnabled(boolean) |
android:autofillHints | describes the content of view, for the autofill service to fill appropriate data. eg: password, username, for code: View.setAutofillHints(View.AUTOFILL_HINT_PASSWORD) |
android:background | drawable to use as background. for code: View.setBackgroundResource(int) |
android:backgroundTint | sets tint to apply to background, for code: View.setBackgroundTintList(ColorStateList) |
android:clickable | boolean value: defines whether this view reacts to click events, for code: View.setClickable(boolean) |
android:fadeScrollbars | boolean value: defines whether to fade out scrollbar, when they are not in use, for code: View.setScrollbarFadingEnabled(boolean) |
android:longClickable | boolean value, defines whether view reacts to long click events, for code: View.setLongClickable(boolean) |
android:onClick | defines method to invoke when view clicked, function should be declared in activity |
android:visibility | int value, controls visibility of the view, for code: View.setVisibility(int) → 0: visible, 1: invisible, 2:gone |
UI → Views
TextView
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 linksandroid:autoText
autocorrects the textual inputandroid:capitalize
capitalizes the textual inputandroid:digits
specifies numeric input to textandroid:drawableBottom
,android:drawableEnd
,android:drawableLeft
,android:drawableRight
,android:drawableStart
specifies drawable with the textviewandroid:drawablePadding
adds padding to the drawableandroid:ellipsize
causes words that are longer than the view is wide to be ellipsized instead of broken in the middleandroid:ems
makes the TextView be exactly this many ems wide.android:fontFamily
specifies the font family for the textandroid:gravity
specifies how to align the text within the viewandroid:hint
specifies the hint msg to display when no textandroid:inputType
specifies the input type of the textviewandroid:password
makes the characters displayed as a dotandroid:text
specifies the text to displayandroid:textColor
android:textColorHighlight
android:textColorHint
android:textColorLink
specify the text colorandroid:textSize
android:textStyle
specify the text appearanceandroid:scrollHorizontally
allow text to be scrolled horizontally
Demonstration of TextView :
<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..
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
}
}
Button
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 clickedandroid: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..
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
}
}
}
EditText
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..
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
}
}
}
ImageView
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 ratioandroid:cropToPadding
crops the image to fit within the paddingandroid:maxHeight
gives a maximum height to the Viewandroid:maxWidth
gives a maximum width to the Viewandroid: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 viewandroid: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..
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
}
}
}
ImageButton
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
CardView
CardView is a versatile widget provided by Android that is used to create a container with multiple views.
Some common XML attributes for CardView are :
app:cardCornerRadius
Sets the corner radius of the card.app:cardElevation
Sets the shadow elevation of the card.app:cardBackgroundColor
Changes the card’s background color.app:cardUseCompatPadding
Ensures consistent padding for the card across devices.app:cardPreventCornerOverlap
Prevents overlapping content from going outside the rounded corners.
Demonstration of CardView :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
//statements>
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="300dp"
app:cardCornerRadius="20dp"
app:cardElevation="20dp"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView ../>
<TextView ../>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Demonstration of CardView in functional Kotlin code :
val cardView = findViewById<CardView>(R.id.cardView)
cardView.setOnClickListener {
Toast.makeText(this, "Card clicked!", Toast.LENGTH_SHORT).show()
}
CheckBox
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..
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)
}
}
}
ToggleButton
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 offandroid:textOn
specifies text when the button is onandroid: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)
btn.setOnCheckedChangeListener{ _, isChecked ->
Log.d("Status:","You turned it" + (if (isChecked) "On" else "Off"))
}
}
}
Switch
Similar to the Toggle Button, but this one is from the Material Components Library.
open class SwitchMaterial : CompoundButton
Some common XML attributes for Switch are :
android:checked
Defines the initial state (on/off).app:thumbColor
Sets the color of the thumb (toggle).app:trackColor
Sets the color of the track.app:useMaterialThemeColors
If set to true, applies the Material theme colors automatically.
Demonstration of Switch :
<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:padding="16dp">
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/material_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/material_switch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Demonstration of Switch in functional Kotlin code :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: SwitchLayoutBinding = SwitchLayoutBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.materialSwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked)// The switch is checked.
else // The switch isn't checked.
}
}
}
Seek-bar
Widget that allows users to select a value from a continuous or discrete range by dragging a thumb (slider).
Some common XML attributes for Seek-bar are :
android:max
Sets the maximum value of the SeekBar.android:progress
Sets the current progress (default position of the thumb).android:thumb
Defines a custom drawable for the slider's thumb.android:secondaryProgress
Sets a secondary progress bar (useful for buffered progress in streaming apps).
Demonstration of Seek-bar :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout ..>
<SeekBar
android:id="@+id/seekbar"
android:max="100"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView .. />
</androidx.constraintlayout.widget.ConstraintLayout>
Demonstration of Seek-bar in functional Kotlin code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//statements..
val seekBar = findViewById<SeekBar>(R.id.seekbar)
val textView = findViewById<TextView>(R.id.textView)
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
textView.text = "Progress: " + p1.toString()
}
override fun onStartTrackingTouch(p0: SeekBar?) {
//statments
}
override fun onStopTrackingTouch(p0: SeekBar?) {
textView.text = "selected ${p0?.progress}"
}
})
}
}
Adding Custom Drawable to Seek-bar :
seekbar_thumb.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke android:color="#CDDC39"
android:width="4dp"/>
<solid android:color="@color/black"/>
<size android:height="24dp" android:width="24dp"/>
</shape>
seekbar_line.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="center_vertical">
<shape android:shape="rectangle">
<solid android:color="#605A5C"/>
<size android:height="5dp"/>
</shape>
</item>
</layer-list>
Adding to Seekbar View in XML :
<Seekbar
...
android:thumb="@drawable/seekbar_thumb"
android:progressDrawable="@drawable/custom_seekbar">
</Seekbar>
Spinner
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 thestrings.xml
file from theres/values
directoryandroid:popupBackground
which specifies the background drawable for the dropdown popupandroid:prompt
which specifies the prompt to display when the spinner dialog is shownandroid:spinnerMode
which specifies the display mode for spinner options(dialog, or dropdown)
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 :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { //statements..
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
val adapter = ArrayAdapter( this, android.R.layout.simple_spinner_item, valuesGender)
spinner.adapter = adapter
}
}
}
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 :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { //statements..
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<*>?) { }
}
RadioButton & RadioGroup
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
. RadioGroup 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 buttonsandroid:checkedButton
specifies the default checked radio button
Demonstration of RadioButton & RadioGroup :
<androidx.constraintlayout.widget.ConstraintLayout ..>
<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 :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { //statements..
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())
}
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { //statements..
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())
})
}
}
Custom Drawables for Views
Drawables in Android are graphics resources used to define backgrounds, shapes, state-based icons, or other visual elements for UI components. They are stored in the res/drawable
directory and can be created using XML or images.
Types of Drawables for Custom Views
Shape Drawable (
shape
)Used to create custom buttons, backgrounds, and borders.
Can define solid colors, gradients, strokes, corners, and padding.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="12dp"/>
<solid android:color="@color/blue"/>
<stroke android:width="2dp" android:color="@color/dark_blue"/>
<padding android:left="10dp" android:right="10dp"/>
</shape>
State List Drawable (
selector
)Allows different appearances based on user interaction (e.g., pressed, focused, disabled).
Used for buttons, text fields, or list items.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/dark_blue"/>
<item android:drawable="@color/blue"/>
</selector>
Gradient Drawable
Creates linear, radial, or sweep gradients as backgrounds.
Commonly used for app backgrounds and buttons.
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#FF5733" android:endColor="#C70039"
android:angle="270"/>
</shape>
Layer-List Drawable
Inset Drawable
Clip Drawable
Vector Drawables