Samrat
Samrat

Reputation: 708

How to perform a haptic feedback in Jetpack Compose

Using jetpack compose, for a clickevent how to perform haptic feedback. I am new to jetpack compose. This is what i tried -

val hapticFeedback = LocalHapticFeedback

@Composable
fun Tab() {
    Row() {
        Icon(imageVector = icon, contentDescription = text)
        if (selected) {
            // i tried both the following ways, none are working. 
            hapticFeedback.current.performHapticFeedback(
                HapticFeedbackType(10)
            )
            hapticFeedback.current.performHapticFeedback(HapticFeedbackType.TextHandleMove)
....
            Spacer(Modifier.width(12.dp))
            Text(text.uppercase(Locale.getDefault()))
        }
    }
}

I am able to see the text when it is getting selected, but not getting a subtle vibrating feedback.

Upvotes: 33

Views: 16977

Answers (5)

nglauber
nglauber

Reputation: 23894

In version rc-01 of Compose you can use only two types of Haptic Feedback: HapticFeedbackType.LongPress or HapticFeedbackType.TextHandleMove.

val haptic = LocalHapticFeedback.current
Row(
    Modifier.clickable {
        haptic.performHapticFeedback(HapticFeedbackType.LongPress)
    }
)

Upvotes: 48

ssindher11
ssindher11

Reputation: 247

For me, this worked well when the user presses down the button. Using Compose 1.2.0-beta01

val interactionSource = remember { MutableInteractionSource() }
val isPressed by interactionSource.collectIsPressedAsState()

val hapticFeedback = LocalHapticFeedback.current
LaunchedEffect(key1 = isPressed) {
    if (isPressed) {
        hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
    }
}

Upvotes: 5

Anders Ullnæss
Anders Ullnæss

Reputation: 946

On my phone (and other devices I've tested on) neither LongPress nor TextHandleMove makes the phone vibrate.

We worked around this before we moved to Compose like this:

import android.content.Context
import android.view.HapticFeedbackConstants
import android.view.View
import android.view.accessibility.AccessibilityManager

fun View.vibrate() = reallyPerformHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
fun View.vibrateStrong() = reallyPerformHapticFeedback(HapticFeedbackConstants.LONG_PRESS)

private fun View.reallyPerformHapticFeedback(feedbackConstant: Int) {
    if (context.isTouchExplorationEnabled()) {
        // Don't mess with a blind person's vibrations
        return
    }
    // Either this needs to be set to true, or android:hapticFeedbackEnabled="true" needs to be set in XML
    isHapticFeedbackEnabled = true

    // Most of the constants are off by default: for example, clicking on a button doesn't cause the phone to vibrate anymore
    // if we still want to access this vibration, we'll have to ignore the global settings on that.
    performHapticFeedback(feedbackConstant, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING)
}

private fun Context.isTouchExplorationEnabled(): Boolean {
    // can be null during unit tests
    val accessibilityManager = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager?
    return accessibilityManager?.isTouchExplorationEnabled ?: false
}

For now we still have to use this code and access it from Compose like in Daniele Segato's answer:

@Composable
fun VibratingButton() {
    val view = LocalView.current
    Button(onClick = {
        view.vibrate()
    }) { ... }
}

Upvotes: 14

Daniele Segato
Daniele Segato

Reputation: 12899

Currently (Compose UI 1.1.0-beta03) only LongPress and TextHandleMove are supported via

val haptic = LocalHapticFeedback.current
Button(onClick = {
    haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}) { ... }

as @nglauber answer said.

I guess it is because of the multi-platform support for Compose Desktop.

There's another way, however, if you are on Android and you do not need Compose Desktop compatibility, it's fairly easy to use it:

val view = LocalView.current
Button(onClick = {
    view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
}) { ... }

The HapticFeedbackConstants class has a lot of constants.

Upvotes: 30

Richard Onslow Roper
Richard Onslow Roper

Reputation: 6835

Add the feedback logic inside the Modifier.clickable {...} applied to the Row

Upvotes: -4

Related Questions