How to Create Jetpack Compose Text and Button UI in Android (Kotlin Guide)

How to Create Jetpack Compose Text and Button UI in Android (Kotlin Guide)


If you’re starting Android UI with Jetpack Compose, you’ll love how quickly you can build clean interfaces without XML. In this step-by-step guide, we’ll show you exactly how to create Jetpack Compose Text and Button UI using Material 3, style them with themes and typography, handle clicks, and preview everything right inside Android Studio. This tutorial is written for students, beginners, and anyone learning Kotlin/Java for Android app development.

What is Jetpack Compose and why use it for Android UI?

Android Jetpack Compose preview with Text above a Material 3 button in a Column layout
Compose preview: Text above a Material 3 button arranged in a Column.

Jetpack Compose is Android’s modern toolkit for building native UI with Kotlin. Instead of writing XML layouts, you describe UI with composable functions. It’s:

  • Declarative: UI is a function of state, so UI updates automatically when data changes.
  • Kotlin-first: No XML or findViewById needed.
  • Material 3 ready: Use theme-aware components like Text and Button that adapt to light/dark themes and accessibility settings.

For beginners, Compose reduces boilerplate and makes learning Android UI much more approachable. If you’re looking for Jetpack Compose basics for beginners, mastering Text and Button is the perfect starting point.

Project setup (Material 3 + Compose BOM)

Jetpack Compose button press updating UI state on Android with Material 3 styling
Before-and-after: a Compose button tap triggers a simple UI state update.

Add the Compose BOM to keep versions aligned and include Material 3 components. In your app module’s build.gradle (Kotlin DSL shown), add:

Kotlin
dependencies {
// Compose BOM manages versions for Compose libraries
implementation(platform("androidx.compose:compose-bom:<latest-version>"))

// Material 3 UI components
implementation("androidx.compose.material3:material3")

// Activity integration for setContent { }
implementation("androidx.activity:activity-compose")

// Optional: tooling for Previews
debugImplementation("androidx.compose.ui:ui-tooling")
implementation("androidx.compose.ui:ui-tooling-preview")
}

Tip: Always check the latest Compose BOM version in the Android docs or release notes. We’ll use Material 3 (androidx.compose.material3) since it’s the recommended design system for new apps.

Build flow: How to create Jetpack Compose Text and Button UI
1) Setup
Add BOM + Material 3

→
2) Composables
Create Text + Button

→
3) State
remember { mutableStateOf }

→
4) Layout
Column/Row + Modifiers

→
5) Theme
Typography + ColorScheme

→
6) Preview/Test
@Preview + clicks

Create a minimal Compose screen with Text and Button

Below is a simple screen that shows a greeting and a button that increases a counter on click. This is a common example for a Jetpack Compose tutorial for Kotlin beginners.

MainActivity (Kotlin)

Kotlin
Code
class="cd-package">import android.os.Bundle
class="cd-package">import androidx.activity.ComponentActivity
class="cd-package">import androidx.activity.compose.setContent
class="cd-package">import androidx.compose.foundation.layout.*
class="cd-package">import androidx.compose.material3.*
class="cd-package">import androidx.compose.runtime.*
class="cd-package">import androidx.compose.ui.Alignment
class="cd-package">import androidx.compose.ui.Modifier
class="cd-package">import androidx.compose.ui.text.font.FontWeight
class="cd-package">import androidx.compose.ui.unit.dp
class="cd-package">import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme { // uses Material 3 theme (typography, colorScheme)
                CounterScreen()
            }
        }
    }
}

class="cd-annotation">@Composable
fun CounterScreen() {
    var count by remember { mutableStateOf(0) }

    // Create simple Android UI with Compose step by step
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp), // padding around the column
        verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterVertically),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        // Jetpack Compose Text composable
        Text(
            text = "Hello, Compose!",
            style = MaterialTheme.typography.titleLarge,
            color = MaterialTheme.colorScheme.onBackground
        )

        // Another Text that shows state
        Text(
            text = "You tapped $count times",
            fontSize = 18.sp,
            fontWeight = FontWeight.Medium
        )

        // Jetpack Compose Button composable with onClick
        Button(
            onClick = { count++ },
            modifier = Modifier
                .heightIn(min = 48.dp) // keep target size accessible
        ) {
            Text("Tap me")
        }
    }
}

How Text works in Compose

The Text composable is a Material 3 component that automatically picks typography and colors from MaterialTheme. This makes your app theme-aware and accessible by default. Here are common properties you’ll use:

  • text: The string to display.
  • style: Use MaterialTheme.typography (e.g., titleLarge, bodyMedium).
  • color: From MaterialTheme.colorScheme (e.g., onBackground).
  • maxLines and overflow: Handle long text with ellipses.
  • fontSize, fontWeight, letterSpacing: Direct font styling when needed.

Text with ellipsis and modern overflow modes

Kotlin
Code
class="cd-package">import androidx.compose.ui.text.style.TextOverflow

class="cd-annotation">@Composable
fun EllipsisSamples() {
    Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
        Text(
            text = "A very long title that will not fit on one line in smaller screens",
            style = MaterialTheme.typography.titleMedium,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis // end ellipsis
        )
        Text(
            text = "This text shows start ellipsis when it is too long to render fully",
            maxLines = 1,
            overflow = TextOverflow.StartEllipsis
        )
        Text(
            text = "Middle ellipsis keeps the end of the string visible, useful for file names.txt",
            maxLines = 1,
            overflow = TextOverflow.MiddleEllipsis
        )
    }
}

Auto-size text to fit

If a container is constrained (like a card or chip), you can auto-size text so it fits nicely. Use BasicText with TextAutoSize:

Kotlin
Code
class="cd-package">import androidx.compose.foundation.text.BasicText
class="cd-package">import androidx.compose.foundation.text.TextAutoSize
class="cd-package">import androidx.compose.ui.text.style.TextAlign

class="cd-annotation">@Composable
fun AutoSizeTextCard(title: String, modifier: Modifier = Modifier) {
    Surface(
        modifier = modifier,
        shape = MaterialTheme.shapes.medium,
        color = MaterialTheme.colorScheme.surfaceVariant
    ) {
        Box(Modifier.padding(12.dp)) {
            BasicText(
                text = title,
                // Step-based auto-size tries sizes between min and max until it fits
                autoSize = TextAutoSize.StepBased(
                    minFontSize = 12.sp,
                    maxFontSize = 22.sp
                ),
                // Optional text alignment via style or ParagraphStyle
                // You can also use TextAlign.Center with Text composable
            )
        }
    }
}

Links inside Text (without deprecated ClickableText)

To add a tappable link in text, build an AnnotatedString with LinkAnnotation and show it using Text or BasicText. This replaces the now-deprecated ClickableText.

Kotlin
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.link.LinkAnnotation
import androidx.compose.ui.text.withLink
import androidx.compose.material3.Text

@Composable
fun LinkedText() {
val annotated = buildAnnotatedString {
append("Read the ")
withLink(LinkAnnotation.Url("https://developer.android.com")) {
append("Android Docs")
}
append(" to learn more.")
}
Text(annotated)
}

This approach integrates better with accessibility and Material semantics while keeping your code clean and modern.

Create and style Buttons in Compose

Material 3 offers multiple button types. Use the one that matches the emphasis you want:

  • Button: Primary, filled.
  • FilledTonalButton: Secondary emphasis.
  • ElevatedButton: Subtle elevation.
  • OutlinedButton: Low emphasis with outline.
  • TextButton: Minimal emphasis, text-only.

Choose the right Material 3 Button (Compose)
Button Type Emphasis Default Look Use When Compose API
Button High (primary) Filled primary container Main call‑to‑action (Submit, Continue) Button { Text(...) }
FilledTonalButton Medium Tonal (softer fill) Secondary actions that still stand out FilledTonalButton { Text(...) }
ElevatedButton Medium‑low Light fill + elevation When subtle separation from background helps ElevatedButton { Text(...) }
OutlinedButton Low Transparent + outline Secondary/tertiary actions (Cancel, Learn more) OutlinedButton { Text(...) }
TextButton Minimal Text only, no fill Inline or least‑prominent actions TextButton { Text(...) }

Examples with onClick

Kotlin
@Composable
fun ButtonGallery(onPrimaryClick: () -> Unit) {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Button(onClick = onPrimaryClick) { Text("Primary Button") }

FilledTonalButton(onClick = { /* TODO */ }) { Text("Tonal Button") }

ElevatedButton(onClick = { /* TODO */ }) { Text("Elevated Button") }

OutlinedButton(onClick = { /* TODO */ }) { Text("Outlined Button") }

TextButton(onClick = { /* TODO */ }) { Text("Text Button") }
}
}

Customize colors, shape, and padding

Kotlin
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults

@Composable
fun StyledPrimaryButton(onClick: () -> Unit, label: String) {
Button(
onClick = onClick,
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary
),
modifier = Modifier
.heightIn(min = 48.dp) // recommended min touch target
.padding(horizontal = 4.dp)
) {
// The Button already applies appropriate internal padding and typography
Text(
text = label,
style = MaterialTheme.typography.labelLarge
)
}
}

Best practice: keep interactive targets at least 48 dp in height/width, and prefer using Material components because they meet accessibility guidelines by default.

Put it together: a simple Compose screen, step by step

Let’s build a compact screen that demonstrates the following:

  • Title with ellipsis
  • Auto-sized subtitle
  • Primary button that changes state
  • Secondary outlined action
Kotlin
Code
class="cd-annotation">@Composable
fun TextAndButtonDemo() {
    var subscribed by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text(
            text = "Welcome to Jetpack Compose Basics for Beginners – A Practical Walkthrough",
            style = MaterialTheme.typography.titleLarge,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis
        )

        AutoSizeTextCard(
            title = "Build Android UI with Jetpack Compose (auto-sizing title)",
            modifier = Modifier.fillMaxWidth()
        )

        Button(
            onClick = { subscribed = !subscribed },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text(if (subscribed) "Unsubscribe" else "Subscribe")
        }

        OutlinedButton(
            onClick = { /* open details */ },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Learn more")
        }
    }
}

When to use Text vs. BasicText

  • Text: Use for most app text. It integrates with Material 3 theming, typography, and colors.
  • BasicText: Use for advanced scenarios (e.g., auto-size text, custom layout behavior) when you don’t need Material styling.

Accessibility and theming tips

  • Use sp for font sizes so the user’s system settings scale your text appropriately.
  • Prefer theme styles: MaterialTheme.typography.* and MaterialTheme.colorScheme.* to keep design consistent and accessible.
  • Buttons already merge label semantics; you don’t need to set contentDescription for the text inside a Button.
  • Maintain minimum 48 dp touch targets.

Quick checklist: How to create Jetpack Compose Text and Button UI
  • Dependencies set: Compose BOM, Material 3, Activity Compose, Tooling Preview.
  • Wrap your UI with MaterialTheme { ... } so Text and Button use proper colors/typography.
  • Use Text with style = MaterialTheme.typography.* and handle long strings via maxLines + TextOverflow.
  • Create actions with Button(onClick = { ... }) { Text("Label") }; keep height ≥ 48.dp.
  • Store UI state with remember { mutableStateOf(...) } so Text updates when Button is clicked.
  • Prefer theme colors (MaterialTheme.colorScheme) over hard-coded colors.
  • Add @Preview composables for quick iteration; test dark mode with uiMode.
  • For links in text, use LinkAnnotation with Text/BasicText (avoid deprecated ClickableText).
  • Use BasicText + TextAutoSize when text must fit tight spaces.

Preview and test your Compose UI in Android Studio

Compose Previews let you see your composables without running the app. You can even preview dark mode.

Kotlin
import androidx.compose.ui.tooling.preview.Preview
import android.content.res.Configuration

@Preview(showBackground = true, name = "Light")
@Preview(
showBackground = true,
name = "Dark",
uiMode = Configuration.UI_MODE_NIGHT_YES
)
@Composable
fun Preview_TextAndButtonDemo() {
MaterialTheme {
TextAndButtonDemo()
}
}

To test behavior like onClick, use Compose UI tests with createAndroidComposeRule and performClick on nodes matching text or test tags. For beginners, starting with Previews is often enough to iterate quickly.

Troubleshooting and common mistakes

  • Text doesn’t fit or gets cut off: Set maxLines and overflow, or use BasicText with TextAutoSize.
  • Colors look off: Ensure you’re using MaterialTheme.colorScheme and not hard-coded colors, unless necessary.
  • Buttons feel small or hard to tap: Ensure at least 48 dp height/width. Material 3 buttons include good defaults, but constraints can reduce size if you’re not careful.
  • Deprecated APIs for links: Don’t use ClickableText for hyperlinks; use LinkAnnotation with Text/BasicText instead.

Output / Result

After implementing the code above, you’ll see:

  • A themed screen with a title that truncates gracefully with an ellipsis.
  • An auto-sized subtitle that adapts to the container width.
  • A primary button that toggles state (e.g., Subscribe ↔ Unsubscribe) with each tap.
  • A secondary outlined button for a less prominent action.

This is the core of how to add text and button in Jetpack Compose and a solid foundation to build screens quickly.

FAQ

What is Jetpack Compose and how does it work for Android UI?

Jetpack Compose is Android’s modern, declarative UI toolkit. You build UI with Kotlin functions called composables. Compose updates the UI automatically when state changes, which reduces boilerplate and helps you move faster.

How do I add a Text composable in Jetpack Compose?

Use Text("Hello"). To keep it theme-aware, apply style = MaterialTheme.typography.* and colors from MaterialTheme.colorScheme. You can control maxLines and overflow to handle long text.

How do I create a Button with an onClick action in Compose?

Use Button(onClick = { /* action */ }) { Text("Click") }. Keep actions simple, and store UI state with remember { mutableStateOf(...) } so the UI updates automatically when users tap. For example: var count by remember { mutableStateOf(0) } then onClick = { count++ }.

How can I style fonts, colors, and padding for Text and Button in Compose?

Prefer Material theme styles for consistency. For Text: style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onBackground. For Buttons: use ButtonDefaults.buttonColors and shape to adjust appearance. Add external spacing with Modifier.padding().

How do I preview and test a Compose UI in Android Studio?

Add @Preview composables with showBackground = true and optionally dark mode previews. Use the Compose Preview panel to view changes instantly. For UI behavior tests, use Compose UI testing APIs to find nodes and perform clicks.

Key takeaways

  • Use Material 3 Text and Button for accessible, theme-aware UI.
  • Handle long text with maxLines and TextOverflow (including Start and Middle ellipses).
  • Use BasicText + TextAutoSize when text must fit constrained spaces.
  • For links, prefer LinkAnnotation with Text/BasicText.
  • Keep interactive elements at least 48 dp to meet accessibility guidelines.

Extend this tutorial

Now that you know How to create Jetpack Compose Text and Button UI, try these next steps:

  • Add icons to buttons with Icon and IconButton.
  • Use Scaffold and SnackbarHost to show messages on button clicks.
  • Create a create simple Android UI with Compose step by step layout using Column, Row, and Box.

Sources / Further reading

Conclusion

That’s it! You’ve learned the essentials of Android UI with Jetpack Compose: adding Text, creating Buttons with onClick, styling with Material 3, handling long text elegantly, and previewing your UI. Keep practicing by combining Text and Button with other Material components, and explore more patterns in this Kotlin Android Jetpack Compose tutorial series.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted