tangent_haptic_feedback 0.0.1
tangent_haptic_feedback: ^0.0.1 copied to clipboard
A powerful, type-safe haptic feedback library for iOS using Core Haptics. Create custom haptic patterns with parameter curves.
import 'package:flutter/material.dart';
import 'package:tangent_haptic_feedback/tangent_haptic_feedback.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TangentHapticFeedback Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const HapticDemoPage(),
);
}
}
class HapticDemoPage extends StatefulWidget {
const HapticDemoPage({super.key});
@override
State<HapticDemoPage> createState() => _HapticDemoPageState();
}
class _HapticDemoPageState extends State<HapticDemoPage> {
@override
void initState() {
super.initState();
// Prepare the haptic engine for reduced latency
TangentHapticFeedback.prepare();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Haptic Patterns'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildSection('Simple Taps', [
_PatternButton('Light Tap', HapticPatterns.lightTap),
_PatternButton('Medium Tap', HapticPatterns.mediumTap),
_PatternButton('Heavy Tap', HapticPatterns.heavyTap),
]),
_buildSection('Feel Variations', [
_PatternButton('Soft', HapticPatterns.soft),
_PatternButton('Rigid', HapticPatterns.rigid),
]),
_buildSection('UI Feedback', [
_PatternButton('Selection', HapticPatterns.selection),
_PatternButton('Double Click', HapticPatterns.doubleClick),
_PatternButton('Triple Click', HapticPatterns.tripleClick),
]),
_buildSection('Notifications', [
_PatternButton('Success', HapticPatterns.success),
_PatternButton('Warning', HapticPatterns.warning),
_PatternButton('Error', HapticPatterns.error),
]),
_buildSection('Expressive', [
_PatternButton('Heartbeat', HapticPatterns.heartbeat),
_PatternButton('Buzz', HapticPatterns.buzz),
_PatternButton('Long Buzz', HapticPatterns.longBuzz),
]),
_buildSection('Curved Patterns', [
_PatternButton('Explosion', HapticPatterns.explosion),
_PatternButton('Engine Rev', HapticPatterns.engineRev),
_PatternButton('Pulse Wave', HapticPatterns.pulseWave),
_PatternButton('Impact Decay', HapticPatterns.impactDecay),
_PatternButton('Charge Up', HapticPatterns.chargeUp),
]),
_buildSection('Composition', [
_PatternButton(
'Heartbeat x3',
HapticPatterns.heartbeat.repeat(3, gap: const Duration(milliseconds: 400)),
),
_PatternButton(
'Success + Buzz',
HapticPatterns.success.then(HapticPatterns.buzz),
),
_PatternButton(
'Double Tap (scaled 50%)',
HapticPatterns.doubleClick.scaled(0.5),
),
]),
_buildSection('Custom Builder', [
_PatternButton(
'Custom Pattern',
HapticPatternBuilder()
.tap(intensity: 0.4)
.waitMs(50)
.tap(intensity: 0.7)
.waitMs(50)
.tap(intensity: 1.0)
.waitMs(100)
.rumble(
duration: const Duration(milliseconds: 200),
intensity: 0.5,
)
.build(),
),
_PatternButton(
'Fade In + Out',
HapticPatternBuilder()
.fadeIn(duration: const Duration(milliseconds: 300))
.fadeOut(duration: const Duration(milliseconds: 300))
.build(),
),
]),
],
),
);
}
Widget _buildSection(String title, List<_PatternButton> buttons) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
),
Wrap(
spacing: 8,
runSpacing: 8,
children: buttons.map((b) => _buildButton(b.label, b.pattern)).toList(),
),
const SizedBox(height: 8),
],
);
}
Widget _buildButton(String label, HapticPattern pattern) {
return FilledButton.tonal(
onPressed: () => TangentHapticFeedback.play(pattern),
child: Text(label),
);
}
}
class _PatternButton {
final String label;
final HapticPattern pattern;
const _PatternButton(this.label, this.pattern);
}