Icon Toggle Button in Jetpack Compose (with Examples)

Jetpack Compose Icon Toggle Button

In this article, we’ll learn how to implement the icon toggle button in Jetpack Compose with the help of examples.

Prerequisites:

This article talks about Material 2 icon toggle buttons. If you want the Material 3 version, follow this link.

What is the Icon Toggle Button in Jetpack Compose?

An icon toggle button has two states – on and off. We can change its state by tapping on it.

Example:

Removing the Ripple Effect

If you want to follow along with this article, create an empty Compose project and open MainActivity. Create a composable called MyUI() and call it from the onCreate() method.

// add the following packages
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.IconToggleButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
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
private fun MyUI() {
   
}

We’ll write our code in the MyUI().

Jetpack Compose provides IconToggleButton API. It looks like this:

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

checked – Whether this button is checked or not.

onCheckedChange – A lambda that is called when the user taps on the icon. It provides a boolean variable that shows if the button is on or off.

modifier – The modifier to change the layout of the icon.

enabled – To enable or disable the input events.

interactionSource – We can observe and customize the interactions. For instance, we can disable the ripple effect.

content – The content of the icon button. This is typically an icon.

Simple Icon Toggle Button:

checked and onCheckedChange parameters are mandatory for the proper functioning of the button.

@Composable
private fun MyUI() {
    var checked by remember {
        mutableStateOf(true) // initially checked
    }

    IconToggleButton(
        checked = checked,
        onCheckedChange = { _checked ->
            checked = _checked
        }
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = "Favorite Item",
            tint = if (checked) Color.Magenta else Color.LightGray // icon color
        )
    }
}

Output:

Simple Icon Toggle Button

Related: Colors in Jetpack Compose

Icon Toggle Button Size:

We can change the icon size by using the size modifiers like size(), height(), etc.

@Composable
private fun MyUI() {
    var checked by remember {
        mutableStateOf(true) // initially checked
    }

    IconToggleButton(
        checked = checked,
        onCheckedChange = { _checked ->
            checked = _checked
        }
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = "Favorite Item",
            modifier = Modifier
                .size(48.dp),
            tint = if (checked) Color.Magenta else Color.LightGray
        )
    }
}

Output:

Icon Toggle Button

Related: Button onClick Animation using Scale Property

From the output, you can see that there is an ugly ripple effect on the icon. Let’s remove it.

Removing the Ripple Effect:

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

@Composable
private fun MyUI() {
    var checked by remember {
        mutableStateOf(true)
    }

    IconToggleButton(
        checked = checked,
        onCheckedChange = { _checked ->
            checked = _checked
        },
        interactionSource = NoRippleInteractionSource()
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = "Favorite Item",
            modifier = Modifier
                .size(48.dp),
            tint = if (checked) Color.Magenta else Color.LightGray
        )
    }
}

class NoRippleInteractionSource : MutableInteractionSource {

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

    override suspend fun emit(interaction: Interaction) {}

    override fun tryEmit(interaction: Interaction) = true
}

Output:

Removing the Ripple Effect

Animating Color:

To animate the color changes, use the animateColorAsState API.

@Composable
private fun MyUI() {
    var checked by remember {
        mutableStateOf(true)
    }

    val tint by animateColorAsState(
        targetValue = if (checked) Color.Magenta else Color.LightGray
    )

    IconToggleButton(
        checked = checked,
        onCheckedChange = { _checked ->
            checked = _checked
        },
        interactionSource = NoRippleInteractionSource()
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = "Favorite Item",
            modifier = Modifier
                .size(48.dp),
            tint = tint
        )
    }
}

class NoRippleInteractionSource : MutableInteractionSource {

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

    override suspend fun emit(interaction: Interaction) {}

    override fun tryEmit(interaction: Interaction) = true
}

Output:

Animating Color

Related: Expandable Card Animation

This is all about the icon toggle button in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.

References:

Related Articles:

Leave a Comment