Skip to content

Instantly share code, notes, and snippets.

@kururu-abdo
Created September 4, 2025 07:41
Show Gist options
  • Save kururu-abdo/751ba69482d2303dcbff227b71c907d8 to your computer and use it in GitHub Desktop.
Save kururu-abdo/751ba69482d2303dcbff227b71c907d8 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(body: Center(child: VibrateIcon())),
);
}
}
class VibrateIcon extends StatefulWidget {
@override
_VibrateIconState createState() => _VibrateIconState();
}
class _VibrateIconState extends State<VibrateIcon> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Offset> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400), // Duration for one full vibration cycle
);
// Define the full vibration motion using TweenSequence for a shake effect
_animation = TweenSequence<Offset>(
<TweenSequenceItem<Offset>>[
TweenSequenceItem<Offset>(
tween: Tween<Offset>(begin: Offset.zero, end: const Offset(8.0, 0.0)),
weight: 0.25, // Move right (first quarter of animation duration)
),
TweenSequenceItem<Offset>(
tween: Tween<Offset>(begin: const Offset(8.0, 0.0), end: const Offset(-8.0, 0.0)),
weight: 0.50, // Move from right to left (middle half of animation duration)
),
TweenSequenceItem<Offset>(
tween: Tween<Offset>(begin: const Offset(-8.0, 0.0), end: Offset.zero),
weight: 0.25, // Move from left back to center (last quarter of animation duration)
),
],
).animate(CurvedAnimation(parent: _controller, curve: Curves.linear));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _onTapVibrate() {
// Stop any ongoing animation before starting a new one
if (_controller.isAnimating) {
_controller.stop();
}
// Reset the controller to the beginning and then play the animation once
_controller.reset();
_controller.forward();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _onTapVibrate,
child: AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: _animation.value,
child: const Icon(Icons.vibration, size: 50), // The vibration icon
);
},
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment