How to Implement IconButton in Jetpack Compose?

Jetpack Compose IconButton

In this article, we’ll learn how to implement IconButton in Jetpack Compose.

Prerequisites:

This article talks about the Material 2 Icon Buttons. If you want the latest Material 3 version, follow this link.

For this article, create an empty Jetpack Compose project and open MainActivity. Create a MyUI() composable and call it from the onCreate().

// we need the following packages
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Paid
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
fun MyUI() {

}

We will write our code in the MyUI().

Next, open the app-level gradle file and add the following dependency.

implementation "androidx.compose.material:material-icons-extended:$compose_version"

It contains material icons. Its size is large. So, if you are using it in your project, don’t forget to enable proguard.

Jetpack Compose provides IconButton API. It looks like this:

@Composable
fun IconButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable () -> Unit
)

onClick – A lambda that is called when the user taps on the icon.

modifierThe modifier for changing the layout.

enabled – Whether the button is clickable or not.

interactionSource – It is used to observe and customize the interactions. For example, we can disable the ripple effect.

content – The content to be drawn inside the IconButton. It is typically an Icon() composable.

Let us understand the parameters with use cases.

Simple IconButton Example:

For a basic icon button, onClick is mandatory.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        }
    ) {
        Icon(imageVector = Icons.Outlined.Paid, contentDescription = "")
    }
}

Output:

Simple IconButton Example in Jetpack Compose

Material icon dependency provides icons with different styles. Take a look at the icons article to learn more about them.

IconButton Size:

An IconButton has an overall minimum touch target size of 48 x 48dp, to meet accessibility guidelines. We can change it using the size modifiers.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        }
    ) {
        Icon(
            modifier = Modifier.size(size = 100.dp),
            imageVector = Icons.Outlined.Paid,
            contentDescription = ""
        )
    }
}

Output:

IconButton Size

IconButton Color:

The tint parameter of Icon() helps us to set the icon color.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        }
    ) {
        Icon(
            modifier = Modifier.size(size = 100.dp),
            imageVector = Icons.Outlined.Paid,
            contentDescription = "",
            tint = Color.Green
        )
    }
}

Output:

IconButton Color Tint

Related: Theme Colors in Jetpack Compose

Disable IconButton:

To disable the icon button, pass false to the enabled parameter. Once disabled, the icon turns gray and doesn’t accept the user input.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        },
        enabled = false
    ) {
        Icon(
            modifier = Modifier.size(size = 100.dp),
            imageVector = Icons.Outlined.Paid,
            contentDescription = ""
        )
    }
}

Output:

Disable IconButton

IconButton with Text:

If you want to show text along with the icon, add a Row layout in the content block and place the Icon() and Text() inside the row.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        }
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            Icon(
                modifier = Modifier.size(36.dp),
                imageVector = Icons.Outlined.Paid,
                contentDescription = ""
            )
            Spacer(modifier = Modifier.width(width = 8.dp))
            Text(text = "Subscription")
        }
    }
}

Output:

IconButton with Text

Run the above code and tap on the button. You will see an ugly ripple effect. Let’s remove it.

Removing Ripple Effect:

There are multiple ways to remove the ripple effect in Jetpack Compose. Let us use the MutableInteractionSource API.

@Composable
fun MyUI() {
    val contextForToast = LocalContext.current.applicationContext

    IconButton(
        onClick = {
            Toast.makeText(contextForToast, "Click!", Toast.LENGTH_SHORT).show()
        },
        interactionSource = NoRippleInteractionSource()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            Icon(
                modifier = Modifier.size(36.dp),
                imageVector = Icons.Outlined.Paid,
                contentDescription = ""
            )
            Spacer(modifier = Modifier.width(width = 8.dp))
            Text(text = "Subscription")
        }
    }
}

class NoRippleInteractionSource : MutableInteractionSource {

    override val interactions: Flow<Interaction> = emptyFlow()

    override suspend fun emit(interaction: Interaction) {}

    override fun tryEmit(interaction: Interaction) = true
}

Output:

Removing Ripple Effect

Note: You can also create a button with text and icon using the TextButton and OutlinedButton APIs.

This is all about IconButton() in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.

Related Articles:

References:

Leave a Comment