Open Source

Flutter package

haptic_kit

Haptic feedback, vibration and animated widgets for Flutter — the right haptic at the right moment.

v2.1.223.3k / month32 likesMITAndroid · iOS9 animated widgets

API reference

The full public API: Haptics, Vibration, HapticPattern, presets, capability detection, exceptions and widget signatures.

source: README.md

API

Library exports

A single import brings in everything: six primitive classes, three enums, a sealed exception hierarchy, two amplitude constants and nine animated widgets. Signatures below are taken verbatim from the package source.

dart
import 'package:haptic_kit/haptic_kit.dart';
SymbolKindSummary
HapticsclassShort, semantic taps: impact, notification, selection, prepare.
VibrationclassLonger vibrations: one-shot, custom waveforms, predefined effects, cancel.
HapticPatternclassFluent builder for Core Haptics / amplitude event sequences.
HapticEventclassA single event (intensity + sharpness) inside a HapticPattern.
VibrationPatternsclassReady-made presets — heartbeat, alarm, success, failure, …
HapticCapabilitiesclassRuntime snapshot of what the current device can do.
HapticImpactStyleenumImpact tap styles: light, medium, heavy, soft, rigid.
HapticNotificationStyleenumNotification styles: success, warning, error.
PredefinedEffectenumOS predefined effects: tick, click, doubleClick, heavyClick.
VibrationExceptionsealed classBase class for every error thrown by the package.
UnsupportedHapticExceptionclassDevice cannot render the requested capability.
InvalidVibrationArgumentExceptionclassA parameter is out of range or invalid.
PlatformVibrationExceptionclassNative call failed or the plugin is not registered.
kMaxAmplitudeconst intMaximum amplitude value (255).
kMinAmplitudeconst intMinimum perceptible amplitude (1).
HapticBouncewidgetTap → squash → recoil → elastic settle with impact haptics.
HapticPulsewidgetLooping breathing scale pulse that ticks on every beat.
HapticRatingwidgetStar rating with a cascading fill + a tick per star.
HapticShakewidgetExternally-triggered error wiggle.
HapticSliderwidgetSlider that ticks on each detent crossing.
HapticStepperwidget−/+ counter with bouncing buttons.
HapticTogglewidgetAnimated switch with a selection tick on flip.
PressAndHoldToConfirmwidgetLong-press with a progress ring + densifying ticks.
SlideToConfirmwidgetDrag the handle to the end to confirm.

API

Haptics

Short, semantic haptic taps tied to UI events, exposed as static methods on Haptics. Named Haptics (not HapticFeedback) to avoid clashing with Flutter's own HapticFeedback from package:flutter/services.dart.

Hapticsdart
static Future<void> impact(HapticImpactStyle style)
static Future<void> notification(HapticNotificationStyle style)
static Future<void> selection()
static Future<bool> prepare()

Returns: impact, notification and selection return Future<void>. prepare() returns Future<bool> true when the platform actually pre-warmed something (iOS), false when the call is a no-op (Android).

Exampledart
await Haptics.impact(HapticImpactStyle.medium);
await Haptics.notification(HapticNotificationStyle.success);
await Haptics.selection();

// Optional: pre-warm the generators for the lowest-latency next tap.
final warmed = await Haptics.prepare(); // true on iOS, false on Android

HapticImpactStyle

dart
enum HapticImpactStyle {
  light,   // iOS: .light   Android: EFFECT_TICK
  medium,  // iOS: .medium  Android: EFFECT_CLICK
  heavy,   // iOS: .heavy   Android: EFFECT_HEAVY_CLICK
  soft,    // iOS 13+, falls back to light
  rigid,   // iOS 13+, falls back to heavy
}

HapticNotificationStyle

dart
enum HapticNotificationStyle {
  success, // Confirms a successful action
  warning, // Warns about a non-fatal issue
  error,   // Signals a failure
}

API

Vibration

Longer-form vibration on Vibration — one-shot durations, custom waveforms, predefined OS effects and cancellation. All methods are static.

Amplitude constantsdart
/// Matches Android's VibrationEffect.MAX_AMPLITUDE.
const int kMaxAmplitude = 255;

/// Minimum amplitude that still produces a perceptible vibration.
const int kMinAmplitude = 1;

Vibration.vibrate

Vibrate for duration. Amplitude is silently clamped on devices without amplitude control.

dart
static Future<void> vibrate({
  required Duration duration,
  int? amplitude,
})
ParameterTypeReq.DefaultDescription
durationDurationYesHow long to vibrate. Must be > 0 ms.
amplitudeint?NonullStrength in 1..255. Silently clamped on devices without amplitude control. null = device default.

Returns: Future<void>.

Throws: InvalidVibrationArgumentException when duration is zero or negative, or when amplitude is set outside [1, 255].

Vibration.vibrateWaveform

Play a custom waveform. On iOS without Core Haptics support the call falls back to a sequence of system vibrations approximating timings.

dart
static Future<void> vibrateWaveform({
  required List<Duration> timings,
  List<int>? amplitudes,
  int repeat = -1,
})
ParameterTypeReq.DefaultDescription
timingsList<Duration>YesOff/on durations, starting with an off period (Android createWaveform convention). Must not be empty.
amplitudesList<int>?NonullSame length as timings, values in [0, 255] (0 = pause). null = default strength.
repeatintNo-1Index in timings to loop from, or -1 for no loop.

Returns: Future<void>.

Throws: InvalidVibrationArgumentException when timings is empty, when amplitudes length differs from timings or holds a value outside [0, 255], or when repeat is neither -1 nor a valid index.

Exampledart
// Three pulses with growing amplitude.
await Vibration.vibrateWaveform(
  timings: const [
    Duration.zero,
    Duration(milliseconds: 100),
    Duration(milliseconds: 100),
    Duration(milliseconds: 100),
    Duration(milliseconds: 100),
    Duration(milliseconds: 100),
  ],
  amplitudes: const [0, 80, 0, 160, 0, 255],
);

Vibration.playPredefined

Trigger one of the platform's predefined effects. Android API 29+ uses VibrationEffect.createPredefined; older Android and iOS translate to the closest equivalent.

dart
static Future<void> playPredefined(PredefinedEffect effect)

Returns: Future<void>.

PredefinedEffectdart
enum PredefinedEffect {
  tick,        // Android: EFFECT_TICK
  click,       // Android: EFFECT_CLICK
  doubleClick, // Android: EFFECT_DOUBLE_CLICK
  heavyClick,  // Android: EFFECT_HEAVY_CLICK
}

Vibration.cancel

Stop any vibration started by this plugin.

dart
static Future<void> cancel()

Returns: Future<void>.

API

HapticPattern builder

A fluent builder for custom event sequences — CHHapticPattern on iOS, a createWaveform on Android where intensity maps to amplitude and sharpness is ignored. Each builder instance holds its own state and is single-use.

HapticEvent

A single event in a pattern.

dart
const HapticEvent({
  required double intensity,             // 0.0..1.0 — overall strength
  required double sharpness,             // 0.0..1.0 — perceptual sharpness (iOS only)
  Duration duration = Duration.zero,     // non-zero = continuous event
  Duration relativeTime = Duration.zero, // offset from pattern start
})
ParameterTypeReq.DefaultDescription
intensitydoubleYes0.0–1.0 — overall strength of the event.
sharpnessdoubleYes0.0–1.0 — perceptual sharpness (iOS only; ignored on Android, which has no equivalent).
durationDurationNoDuration.zeroIf non-zero, the event is continuous for this duration; otherwise it is a single tap.
relativeTimeDurationNoDuration.zeroOffset from pattern start at which this event begins.

Throws: An assertion error when intensity or sharpness is outside [0, 1].

HapticPattern.builder

Start a new pattern, then chain tap, continuous, pause and addEvent before calling play.

dart
factory HapticPattern.builder()

HapticPattern tap({
  required double intensity,
  required double sharpness,
})

HapticPattern continuous({
  required Duration duration,
  required double intensity,
  required double sharpness,
})

HapticPattern pause(Duration duration)
HapticPattern addEvent(HapticEvent event)

int get length                 // Number of events queued so far.
List<HapticEvent> get events   // Snapshot of the current event list.

Future<void> play()

Returns: tap, continuous, pause and addEvent return the same HapticPattern for chaining; play() returns Future<void>.

Throws: InvalidVibrationArgumentException from continuous/pause when the duration is <= 0 ms, and from play when the pattern has no events. play may also throw UnsupportedHapticException on devices with neither Core Haptics nor a waveform-amplitude vibrator.

Exampledart
await HapticPattern.builder()
    .tap(intensity: 0.4, sharpness: 0.6)
    .pause(const Duration(milliseconds: 80))
    .tap(intensity: 1.0, sharpness: 0.9)
    .continuous(
      duration: const Duration(milliseconds: 250),
      intensity: 0.7,
      sharpness: 0.3,
    )
    .play();

API

VibrationPatterns presets

Ready-to-use waveforms and haptic patterns on VibrationPatterns. Each entry returns a Future<void> so you can await playback in UI callbacks.

VibrationPatternsdart
static Future<void> heartbeat()
static Future<void> notification()
static Future<void> alarm({bool repeat = true})
static Future<void> tick()
static Future<void> doubleTap()
static Future<void> success()
static Future<void> failure()
static Future<void> chargeUp({
  Duration duration = const Duration(milliseconds: 600),
})
PresetWhat it feels like
heartbeat()Two short pulses mimicking a heartbeat.
notification()Three escalating pulses — typical incoming-notification pattern.
alarm({bool repeat = true})Long ringing pattern — alarms / incoming calls. Loops by default.
tick()Single very short tick — a hair stronger than a selection tap.
doubleTap()Two quick, equal taps — a double-tap acknowledgement.
success()Confirmation: light tap → strong tap.
failure()Failure / cancel: two strong taps.
chargeUp({Duration duration = const Duration(milliseconds: 600)})Long ramp from soft to strong — a “charging up” moment.

API

Capability detection

Query what the current device can do before reaching for an advanced capability. Call HapticCapabilities.query() once on app start (or the first user interaction) and cache the result — the values do not change at runtime.

dart
static Future<HapticCapabilities> query()

Returns: Future<HapticCapabilities> — a snapshot with the following fields.

ParameterTypeReq.DefaultDescription
hasVibratorboolDevice has any kind of vibrator hardware.
hasAmplitudeControlboolDevice can render variable-amplitude waveforms. Android: Vibrator.hasAmplitudeControl() (API 26+); iOS: true when Core Haptics is available.
supportsCustomPatternsboolCustom HapticPatterns with intensity + sharpness. Android: API 26+ with amplitude control; iOS: Core Haptics devices (iPhone 8+).
supportsPredefinedEffectsboolVibrationEffect.createPredefined (Android API 29+). Always false on iOS — predefined calls map to the closest impact style instead.
supportsImpactFeedbackboolUIImpactFeedbackGenerator-style taps. iOS: true on iOS 10+; Android: true on API 23+ even without an amplitude-controlled vibrator.
Graceful degradationdart
final caps = await HapticCapabilities.query();
if (caps.supportsCustomPatterns) {
  await VibrationPatterns.success();
} else {
  await Haptics.notification(HapticNotificationStyle.success);
}

API

Exceptions

Every error thrown by haptic_kit is a subclass of the sealed VibrationException, so an exhaustive switch can handle them all.

dart
sealed class VibrationException implements Exception {
  const VibrationException(this.message);
  final String message;
}

class UnsupportedHapticException extends VibrationException {
  const UnsupportedHapticException(super.message);
}

class InvalidVibrationArgumentException extends VibrationException {
  const InvalidVibrationArgumentException(super.message);
}

class PlatformVibrationException extends VibrationException {
  const PlatformVibrationException(super.message, {this.code});
  final String? code;
}
ExceptionThrown when
InvalidVibrationArgumentExceptionA parameter is out of range (negative duration, amplitude > 255, mismatched lists, …).
UnsupportedHapticExceptionThe device cannot render the requested capability.
PlatformVibrationExceptionThe native side returned an error or the plugin is not registered.

API

Animated widgets

Nine production-ready widgets that pair an animation with the matching haptic. Constructor signatures are shown below; for the full parameter tables, defaults and examples see the Animated widgets page. Widgets exposing a State class are driven externally via a GlobalKey.

HapticBounce

Tap wrapper that squashes, recoils past its resting size and settles with an elastic wobble. Fires impact(light) on press-down and medium on release.

HapticBouncedart
const HapticBounce({
  super.key,
  required this.child,
  this.onTap,
  this.bounceOnRelease = true,
  this.pressedScale = 0.92,
  this.overshootScale = 1.12,
  this.pressDuration = const Duration(milliseconds: 110),
  this.releaseDuration = const Duration(milliseconds: 480),
  this.haptics = true,
  this.behavior = HitTestBehavior.opaque,
})
Full parameters →

PressAndHoldToConfirm

Hold to confirm with a progress ring and a 12-tick schedule that escalates selectionlight mediumheavy.

PressAndHoldToConfirmdart
const PressAndHoldToConfirm({
  super.key,
  required this.child,
  required this.onConfirm,
  this.holdDuration = const Duration(seconds: 2),
  this.ringSize = 96,
  this.ringStrokeWidth = 6,
  this.ringColor,
  this.showRingAtFingerPosition = true,
})

State (via GlobalKey<PressAndHoldToConfirmState>): void reset() re-arms the widget after a confirmation.

Full parameters →

HapticToggle

Custom-drawn switch with a spring-back animation and a selection tick on flip. Controlled — the caller owns value.

HapticToggledart
const HapticToggle({
  super.key,
  required this.value,
  required this.onChanged,
  this.activeColor,
  this.inactiveColor = const Color(0xFF3A3A3C),
  this.thumbColor = Colors.white,
  this.width = 56,
  this.height = 32,
  this.duration = const Duration(milliseconds: 220),
})
Full parameters →

HapticSlider

Slider that fires a haptic tick whenever the value crosses a discrete detent — like the iOS picker wheel.

HapticSliderdart
const HapticSlider({
  super.key,
  required this.value,
  required this.onChanged,
  this.min = 0.0,
  this.max = 1.0,
  this.divisions,
  this.tickEvery,
  this.label,
  this.activeColor,
  this.tickStyle = HapticImpactStyle.light,
  this.endTickStyle = HapticImpactStyle.medium,
})
Full parameters →

HapticStepper

−/+ counter with bouncing buttons and a number that slides. Each press fires light; hitting min/max fires heavy.

HapticStepperdart
const HapticStepper({
  super.key,
  required this.value,
  required this.onChanged,
  this.min = 0,
  this.max = 99,
  this.step = 1,
})
Full parameters →

HapticShake

Externally-triggered horizontal wiggle + notification(error) — the classic “wrong password” shake.

HapticShakedart
const HapticShake({
  super.key,
  required this.child,
  this.amplitude = 10.0,
  this.duration = const Duration(milliseconds: 420),
  this.haptics = true,
})

State (via GlobalKey<HapticShakeState>): Future<void> shake() plays the shake once (restarts if already shaking).

Full parameters →

HapticPulse

Looping “breathing” scale pulse that fires a haptic tap on every beat — the attention-getter counterpart to HapticShake.

HapticPulsedart
const HapticPulse({
  super.key,
  required this.child,
  this.minScale = 1.0,
  this.maxScale = 1.08,
  this.period = const Duration(milliseconds: 600),
  this.autoPlay = true,
  this.pulseCount,
  this.impactStyle = HapticImpactStyle.light,
  this.haptics = true,
})

State (via GlobalKey<HapticPulseState>): bool get isPulsing, void start(), void stop().

Full parameters →

SlideToConfirm

Drag the handle from edge to edge to confirm, with light ticks at 25% / 50% / 75% and a heavy impact at 100%.

SlideToConfirmdart
const SlideToConfirm({
  super.key,
  required this.onConfirmed,
  this.label = 'Slide to confirm',
  this.height = 64,
  this.handleIcon = Icons.arrow_forward,
  this.confirmedIcon = Icons.check,
  this.trackColor,
  this.handleColor,
  this.textColor,
})

State (via GlobalKey<SlideToConfirmState>): void reset() re-arms the widget after a confirmation.

Full parameters →

HapticRating

Star rating that fills with a cascading animation, firing one selection tick per star as it lights up.

HapticRatingdart
const HapticRating({
  super.key,
  required this.value,
  required this.onChanged,
  this.starCount = 5,
  this.size = 36,
  this.spacing = 6,
  this.activeColor = Colors.amber,
  this.inactiveColor = const Color(0xFF3A3A3C),
  this.cascadeDelay = const Duration(milliseconds: 65),
})
Full parameters →

Let's make something together.

If you have any questions about a new project or other inquiries, feel free to contact us. We will get back to you as soon as possible.

Codigee
We are using cookies. Learn more