Basics of composable

I create cross platform mobile apps with AI functionalities. Currently a PhD Scholar at Indira Gandhi Delhi Technical University for Women, Delhi. M.Tech in Artificial Intelligence (AI).
Jetpack Compose is Android’s modern toolkit for building native UI with a declarative approach. Unlike traditional XML-based layouts, Compose allows developers to define UI components directly in Kotlin using composable functions. In this blog, we’ll walk through the fundamental concepts that form the backbone of Compose development. We'll start by creating a new project, then dive into what makes a function composable, how to preview your UI, and how to use the Text composable effectively. We'll also explore modifiers—the building blocks for styling and layout in Compose—and understand why their order matters. Whether you're just starting or transitioning from XML, this guide will help you get comfortable with the essentials of Jetpack Compose.
Create New Project
If you want to make a project using jetpack compose you can either install jetpack compose into your project or use a template where jetpack compose is already installed. We will use the template “Empty Activity” where jetpack compose is already installed in this blog.
Create a new Project. Use the Template “Empty Activity”. Name the Project as “BasicsJC”.



Let the project build successfully and only then start making any changes. The build process can take upto 10 minutes. It might happen faster in your computer based on your system configuration.
Composable
In XML we used to have layout to write text view. Here in jetpack Compose, we don’t have any layout and instead we write the code in composable functions.
Annotations
We have two types of aanotations in Jetpack compose
@composable annotation:
@Composable is an annotation used to mark functions that describe UI components in Jetpack Compose.
Instead of creating UI in XML and then binding it in code, Compose lets you define UI directly in Kotlin functions. These functions can be nested, reused, and parameterized.
It must be used on any function that emits UI.
It does not return a view object — instead, it describes the UI layout.
Can call other @Composable functions.
Think of it as describing what the UI should look like, not how to build it imperatively
@preview annotation:
@Preview is used to annotate composable functions to render a preview of the UI in Android Studio’s design view, without running the app.
It allows developers to see and iterate on UI components quickly, improving productivity and visual design feedback.
We already have a default preview and composable function as shown below in MainActivity.kt

Remove extra code
Remove the extra code so your file will look something like below
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
// add the composable function call here
}
}
}
}
}
Text Composable
In Jetpack Compose, the Text composable is used to display text in your app's UI. It is highly customizable and forms a fundamental building block for creating responsive and styled user interfaces.
Create composable function from scratch
Write composable annotation as shown below
@composable
create a function called “DisplayText” which has no parameters as shown below:
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { _ ->
// add the function call here
DisplayText()
}
}
}
}
}
@Composable
fun DisplayText(){
Text(
text = "Hello World!!!"
)
}
Output is displayed on top bar (overlayed) and we will fix that using modifier in the later section. It is overlayed because we didn’t use inner padding.

Explanation:
This Kotlin code defines a basic Jetpack Compose application in Android. The main purpose of the code is to display the text "Hello World!!!" on the screen using a composable function.
The MainActivity class extends ComponentActivity, which is a base class used for Compose-enabled Android activities. Inside the onCreate() method, the enableEdgeToEdge() function is called, which allows the UI to draw behind system bars (like the status bar or navigation bar), giving more immersive layouts. Following that, the setContent block is invoked — this is where the UI is defined using Jetpack Compose instead of XML.
Within the setContent block, the custom theme BasicsJCTheme is applied. This theme wraps the UI components to provide consistent styling, such as colors, typography, and shapes across the app. Inside this theme, a Scaffold is used, which is a layout structure in Compose that provides basic material design structure like handling top bars, bottom bars, floating action buttons, and more. The modifier = Modifier.fillMaxSize() ensures that the scaffold takes up the full screen size.
Within the Scaffold, a composable function named DisplayText() is called. This function is defined below and marked with the @Composable annotation, which means it can be used to define UI components in Jetpack Compose. Inside DisplayText(), a simple Text composable displays the message "Hello World!!!" on the screen.
In summary, this code demonstrates a minimal Jetpack Compose setup where a single line of text is displayed using a composable function inside a scaffold, all while applying a consistent app theme. It showcases how to structure a Compose-based UI using modern Android practices.
Parameters
We have used the Text Composable (Text). This text composable has multiple parameters as described below:
text
Type:
StringThe actual string content you want to display. This is the only required parameter.
Example:
Text(text = "Welcome to Compose")
modifier
Type:
ModifierUsed to decorate or add behavior to the
Text(e.g., padding, background, click handling).Example:
Text(text = "Hello", modifier = Modifier.padding(8.dp))
color
Type:
ColorSets the color of the text.
Example:
Text(text = "Hello", color =Color.Red)
fontSize
Type:
TextUnitSets the size of the text, typically using
sp(scale-independent pixels).Example:
Text(text = "Hello", fontSize = 20.sp)
fontStyle
Type:
FontStyleApplies a style to the text such as
FontStyle.ItalicorFontStyle.Normal.Example:
Text(text = "Italic text", fontStyle = FontStyle.Italic)
fontWeight
Type:
FontWeightControls the thickness of the text (e.g.,
FontWeight.Bold,FontWeight.Light).Example:
Text(text = "Bold Text", fontWeight = FontWeight.Bold)
fontFamily
Type:
FontFamilyDefines the font family to use, including custom fonts or built-in ones like
FontFamily.Serif.Example:
Text(text = "Custom Font", fontFamily = FontFamily.Monospace)
letterSpacing
Type:
TextUnitAdds spacing between characters.
Example:
Text(text = "Spaced", letterSpacing = 2.sp)
textDecoration
Type:
TextDecorationAdds decorations like underline or line-through.
Example:
Text(text = "Underlined", textDecoration = TextDecoration.Underline)
textAlign
Type:
TextAlignAligns text within its container (e.g.,
TextAlign.Center,TextAlign.End).Example:
Text( text = "Centered Text", textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth() )
lineHeight
Type:
TextUnitSets the height of each line in the text block.
Example:
Text(text = "Line\nHeight", lineHeight = 30.sp)
overflow
Type:
TextOverflowHandles how text behaves when it overflows its bounds. Common values:
Ellipsis,Clip,Visible.Example:
Text(text = "Long text...", maxLines = 1, overflow = TextOverflow.Ellipsis)
softWrap
Type:
BooleanDetermines whether text should wrap onto the next line.
Example:
Text(text = "Wrapped text", softWrap = true)
maxLines
Type:
IntLimits the number of lines for the text. Useful in combination with
overflow.Example:
Text(text = "Line1\nLine2", maxLines = 1)
onTextLayout
Type:
TextLayoutResult.() -> UnitCallback that gives access to layout information after the text is measured and laid out.
Useful for measuring text, truncation, or performing layout-dependent logic.
Example:
Text( text = "Measure me", onTextLayout = { result -> val lineCount = result.lineCount } )
style
Type:
TextStyleAllows setting multiple text properties in one place. Can override other individual parameters if used.
Example:
Text( text = "Styled text", style = TextStyle( color = Color.Blue, fontSize = 18.sp, fontWeight = FontWeight.SemiBold ) )

Modifiers
In Jetpack Compose, Modifier is a powerful concept used to decorate or adjust the behavior and layout of composables. Think of it as a flexible toolkit that allows you to:
Add padding, background, or border
Control size and alignment
Handle user interactions
Add animations and effects
Customize layout constraints
Modifiers are applied in a chain, and their order matters, because each modifier wraps the previous one.
Modifiers is a part of parameters in composable function.
We are currently seeing the Displayed Text “Hello world!!!” on top of time on the top bar. We want to add appropriate spacing. We can do this using modifiers.
Updated code with modifier:
package com.igdtuw.basicsjc
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.igdtuw.basicsjc.ui.theme.BasicsJCTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BasicsJCTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
DisplayText(modifier = Modifier.padding(innerPadding))
}
}
}
}
}
@Composable
fun DisplayText(modifier: Modifier){
Text(
text = "Hello World!!!",
modifier = modifier
)
}

Commonly Used Modifiers
Here are some frequently used modifiers in Compose:
padding()
Adds space inside the composable.
Text("Hello", modifier = Modifier.padding(16.dp))
background()
Sets a background color or shape.
Text("With Background", modifier = Modifier.background(Color.Yellow))
fillMaxSize()
Expands the composable to fill the available space.
Box(modifier = Modifier.fillMaxSize())
fillMaxWidth()
Expands the composable to fill the available width.
Box(modifier = Modifier.fillMaxWidth())
fillMaxHeight()
Expands the composable to fill the available Height.
Box(modifier = Modifier.fillMaxHeight())
size()
Sets an explicit width and height.
Box(modifier = Modifier.size(100.dp))
width()
Set width independently
Box(modifier = Modifier.width(200.dp))
height()
Set height independently
Box(modifier = Modifier.height(100.dp))
align()
Aligns a composable within a parent layout (used in
Box,Column, etc.).Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Text("Centered Text", modifier = Modifier.align(Alignment.BottomEnd)) }
clickable()
Makes a composable respond to click events.
Text("Click Me", modifier = Modifier.clickable { /* handle click */ })
border()
Adds a border around the composable.
Box(modifier = Modifier.border(2.dp, Color.Black))
clip()
Clips the content to a shape (e.g., rounded corners).
Image( painter = painterResource(id = R.drawable.image), contentDescription = null, modifier = Modifier.clip(RoundedCornerShape(8.dp)) )
offset()
Shifts the composable by a specific distance on the X and Y axes.
Text("Offset Text", modifier = Modifier.offset(x = 10.dp, y = 20.dp))
alpha()
Controls the transparency of the composable.
Text("Faded Text", modifier = Modifier.alpha(0.5f))
zIndex()
Controls the draw order when composables overlap.
Box(modifier = Modifier.zIndex(1f))
Modifier Order Matters
The order in which modifiers are applied changes the behavior:
// Padding inside the background (good)
Text(
"Hello",
modifier = Modifier
.padding(8.dp)
.background(Color.Gray)
)
// Background wraps the text before padding (may look different)
Text(
"Hello",
modifier = Modifier
.background(Color.Gray)
.padding(8.dp)
)
After Words
Understanding the basics of Composables is the first essential step toward building modern Android UIs with Jetpack Compose. From creating a new project to exploring how @Composable functions work, we've laid a strong foundation for building declarative and efficient UI components. We also examined the Text composable and its various parameters, giving you control over content presentation. Lastly, we explored the powerful world of Modifiers, which play a crucial role in defining layout, appearance, and interactivity — and how their order can significantly affect behavior. With these fundamentals in place, you're well-equipped to start experimenting with more complex layouts and dynamic UI elements in Compose. Keep exploring, and happy coding!




