Search code examples
androidkotlingradleandroid-jetpack-composeandroid-jetpack-compose-material3

How to add a color when a button is pressed without ripple effect?


I want to remove ripple effect from button, but still have onSurface color on it.

For example, this is button before pressing

enter image description here

i want to achieve this after pressing button.

enter image description here

Here is my current code.

val MyRippleConfiguration =
            RippleConfiguration(color = Color.Red, rippleAlpha = RippleAlpha(0f,0f,0f,0f))
        CompositionLocalProvider(LocalRippleConfiguration provides MyRippleConfiguration){
            Button(
                modifier = Modifier.fillMaxWidth().padding(4.dp).bounceClickEffect(),
                onClick = {
                }) {
                Text(
                    text = "Sign up free",
                    color = colorResource(id = R.color.black),
                    fontWeight = FontWeight.Bold,
                    fontSize = 16.sp
                )
            }
        }
fun Modifier.bounceClickEffect() = composed {
    var isPressed by remember { mutableStateOf(false) }
    val scale by animateFloatAsState(if (isPressed) 0.98f else 1f)

    this
        .graphicsLayer {
            scaleX = scale
            scaleY = scale
        }
        .pointerInput(isPressed) {

            awaitPointerEventScope {
                isPressed = if (isPressed) {
                    waitForUpOrCancellation()
                    false
                } else {
                    awaitFirstDown(false)
                    true
                }
            }
        }
}

i tried to change values of RippleAlpha object but i were unable to achieve it.


Solution

  • I were able to achieve the questions in two ways.

    1. First solution provided by how-to-change-button-background-color-on-click

    Here is the solution in my case.

    var color by remember { mutableStateOf(Color.White) }
    
        TextButton(modifier = Modifier
            .bounceClickEffect(Color.Transparent, Color.Transparent)
            .pointerInteropFilter {
                when (it.action) {
                    MotionEvent.ACTION_DOWN -> {
                        color = Color.Gray
                    }
    
                    MotionEvent.ACTION_UP -> {
                        color = Color.White
                    }
                }
                true
            },onClick ={
        }, colors = ButtonDefaults.textButtonColors(containerColor = Color.Transparent)){
            Text(text="Log in", fontSize = 16.sp,fontWeight =  FontWeight.Bold, color = color)
        }
    
    1. Second solution is to use animateColorAsState on Modifier

       fun Modifier.bounceClickEffect(pressedColor:Color,releasedColor:Color) = 
       composed {
       var isPressed by remember { mutableStateOf(false) }
       val scale by animateFloatAsState(if (isPressed) 0.98f else 1f)
       val backgroundColor by animateColorAsState(if (isPressed) pressedColor else 
       releasedColor)
      
       this
          .graphicsLayer {
           scaleX = scale
           scaleY = scale
       }
       .background(
           color = backgroundColor,
           shape = RoundedCornerShape(20.dp)
       ) // Apply color to background
       .pointerInput(isPressed) {
      
           awaitPointerEventScope {
               isPressed = if (isPressed) {
                   waitForUpOrCancellation()
                   false
               } else {
                   awaitFirstDown(false)
                   true
               }
           }
       }
       .height(40.dp)
       }
      

    I just specify a lighter shade at the beginning then a darker shade