Created
September 4, 2025 07:41
-
-
Save kururu-abdo/751ba69482d2303dcbff227b71c907d8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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