Implementing Haptic Feedback for Mobile Apps
Button clicked but user didn't feel it—and clicked again. Double form submission, double order, double payment. Haptic feedback is not UI decoration, it's confirmation mechanism at physical level.
How iOS and Android Differ in Haptics
iOS centers on UIFeedbackGenerator and its three subclasses: UIImpactFeedbackGenerator for tactile impacts of different intensity (.light, .medium, .heavy, .rigid, .soft), UISelectionFeedbackGenerator for picker scrolling, UINotificationFeedbackGenerator for system events (.success, .warning, .error). Generators require explicit prepare() call before use—without it vibration delays 150–200 ms because Taptic Engine needs initialization time. Missing prepare() is most common mistake.
From iOS 17 UICanvasFeedbackGenerator for drawing and CHHapticEngine from Core Haptics for fully custom patterns: can specify intensity and frequency curve over time via CHHapticEvent and CHHapticParameterCurve. Allows, for example, ramping vibration on long press or pulsing pattern for notifications.
On Android before API 31 only Vibrator with primitive patterns via VibrationEffect.createWaveform(). Starting Android 12 (API 31) VibrationEffect.Composition with predefined primitives: PRIMITIVE_CLICK, PRIMITIVE_TICK, PRIMITIVE_THUD, PRIMITIVE_SPIN and others. Problem—fragmentation: specific primitive support depends on manufacturer and device model. Method Vibrator.areAllPrimitivesSupported() mandatory before use. On devices without support need graceful fallback to VibrationEffect.createOneShot().
In Flutter—HapticFeedback from flutter/services.dart with methods lightImpact(), mediumImpact(), heavyImpact(), selectionClick(). For finer iOS control can call CHHapticEngine directly via MethodChannel. Android Flutter uses Vibrator under hood, limiting capabilities on old API.
In React Native—react-native-haptic-feedback or built-in Vibration API. First library gives access to native types on both platforms, but requires platform and API version checks at runtime.
Typical Implementation Mistakes
Haptic without support check. UIFeedbackGenerator silently ignores calls on simulator, but on device without Taptic Engine (iPad mini 4, old iPod touch) prepare() and impactOccurred() also don't crash—simply nothing happens. This is expected Apple behavior. Android differs: Vibrator.hasVibrator() and hasAmplitudeControl() must be checked explicitly.
Haptic overuse in animations. Vibration on every scroll animation frame kills battery and annoys user. UISelectionFeedbackGenerator.selectionChanged() should only call when selected element changes, not on each offset change.
Ignoring system setting. iOS since 13 propagates "System Haptic" setting via CHHapticEngine, but UIFeedbackGenerator automatically respects this setting. Custom patterns via CHHapticEngine require checking CHHapticEngine.capabilitiesForHardware().supportsHaptics and setting engine.playsHapticsOnly.
What's Included
Analyze interactive app elements: buttons, swipes, sliders, pickers, pull-to-refresh, drag-and-drop, error notifications. For each type select intensity and pattern matching Apple HIG and Material Design 3 system guidelines. Implement native calls for each platform with fallback logic. Test on real devices—iOS simulator doesn't reproduce tactile response correctly.
If custom patterns needed (game effects, specific UI events), design CHHapticPattern with intensity curves and deliver via CHHapticPatternPlayer.
Timeline: 1 day for basic standard generator integration. Custom Core Haptics patterns and cross-platform library—2–3 days.







