Jetpack Compose: Pass onClick event to a function

Introduction

Jetpack Compose, Android's modern toolkit for building native UI, emphasizes declarative programming to make UI design simpler and more intuitive. In traditional Android development, managing user interactions, such as button clicks, often involves multiple layers of XML layouts and listener implementations. However, Jetpack Compose removes this complexity, making it easier to manage UI interactions through composable functions.

This example demonstrates how to handle onClick events in Jetpack Compose by passing these events to functions. By breaking down this Kotlin example, we can explore how button clicks increment or decrement a counter and how UI components are structured within a Scaffold. This code provides a clean and organized way to manage state and UI actions, illustrating key Compose concepts like state management and composable functions.

MainActivity Setup

In the MainActivity.kt file, the code starts with the MainActivity class, extending AppCompatActivity, which is the base class for activities in Android. The onCreate function, the entry point of the activity, uses setContent to set up the Compose UI. Instead of using an XML layout, setContent takes a composable function—in this case, GetScaffold—which defines the overall structure of the UI. This pattern demonstrates how Jetpack Compose allows developers to completely eliminate XML layouts, relying solely on Kotlin code to manage the UI.

The activity lifecycle is still managed by the underlying Android framework, but Compose handles the UI rendering. This paradigm shift from XML to declarative UI programming greatly simplifies the development process by allowing UI and logic to be handled in one place.

Creating the Scaffold

The GetScaffold function sets up a basic scaffold layout, which is a common pattern in Jetpack Compose. The Scaffold component provides a structure with slots for standard UI elements like a TopAppBar, floating action buttons, and a body for content. In this case, a TopAppBar displays a title, and the main content is rendered by the MainContent composable.

The TopAppBar has a simple setup, with a text title and a background color. Meanwhile, the scaffold's background color is customized to a light tone. This shows how easily Jetpack Compose allows developers to modify layout properties using arguments like backgroundColor.

MainContent and State Management

In MainContent, a column layout is used to align UI components vertically. The code demonstrates a key concept in Jetpack Compose—state management—using the remember and mutableStateOf functions to manage the counter value. remember ensures that the state persists across recompositions, and mutableStateOf provides a reactive state variable that updates the UI whenever the counter value changes.

The Column composable arranges the Text and buttons with spacing and alignment settings. The Text composable displays the current value of the counter, while multiple buttons allow users to manipulate this value.

Handling onClick Events

The core functionality of this example revolves around the buttons, each of which modifies the counter value in different ways. The GetButton composable is a reusable component that takes two parameters: a text string for the button label and an onClick function, which is passed as an event handler.

Several buttons are defined in MainContent, with each one triggering a different modification of the counter when clicked. The onClick lambda is where the event-handling logic resides. For example, the button labeled "Add One" increments the counter by one, while "Add Two" and "Add Five" increase it by two and five, respectively. The "Minus Three" button, on the other hand, decrements the counter by three.

Reusable Button Component

The GetButton composable is designed to be flexible and reusable. It uses the Button composable from the Material Design library, which takes an onClick parameter and a shape to customize its appearance. The RoundedCornerShape(8.dp) argument ensures that the button has rounded corners, giving it a more polished look.

By defining the button layout and padding within GetButton, this composable can be reused with different click handlers and text labels without repeating the layout logic. The separation of concerns—defining how the button looks and how it behaves—makes this a highly modular and readable approach to UI design.

Summary

This Kotlin example effectively demonstrates how Jetpack Compose simplifies state management and UI interactions by passing onClick events to functions. With composables like GetScaffold, MainContent, and GetButton, the code highlights the declarative nature of Compose, making it easy to manage both UI layout and state logic in a clean, readable manner.

By leveraging features like mutableStateOf and reusable components, this example illustrates the power of Jetpack Compose to create dynamic and responsive user interfaces. The simplicity of managing onClick events directly within composable functions underscores how Jetpack Compose transforms Android development into a more intuitive and fluid experience for developers.


MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedObjectState: Bundle?) {
        super.onCreate(savedObjectState)
        setContent {
            GetScaffold()
        }
    }


    @Composable
    fun GetScaffold() {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = {
                        Text(
                            text = "Compose - Pass onClick event to function"
                        )
                    },
                    backgroundColor = Color(0xFFB9966a),
                )
            },
            content = { MainContent() },
            backgroundColor = Color(0xFFfaf0e6)
        )
    }


    @Composable
    fun MainContent() {
        val counter = remember { mutableStateOf(0)}

        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(8.dp),
            modifier = Modifier
                .fillMaxSize()
                .padding(12.dp)
        ) {
            Text(
                text = "Counter " + counter.value,
                style = MaterialTheme.typography.h4,
                modifier = Modifier.padding(24.dp)
            )

            GetButton(text = "Add One", onClick = {counter.value++})

            GetButton(text = "Add Two") {
                counter.value +=2
            }

            GetButton(text = "Add Five") {
                counter.value +=5
            }

            GetButton(text = "Minus Three") {
                counter.value -=3
            }
        }
    }


    @Composable
    fun GetButton(
        text:String,
        onClick: ()-> Unit,
    ){
        Button(
            onClick = onClick,
            shape = RoundedCornerShape(8.dp)
        ){
            Text(
                text = text,
                Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
            )
        }
    }
}
More android jetpack compose tutorials