I want to create ripple animation using flutter. I already know ripple effect but this is not what I want , I want something which is here in the link
Asked
Active
Viewed 1.3k times
2 Answers
32
Output
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
lowerBound: 0.5,
duration: Duration(seconds: 3),
)..repeat();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Title")),
body: _buildBody(),
);
}
Widget _buildBody() {
return AnimatedBuilder(
animation: CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn),
builder: (context, child) {
return Stack(
alignment: Alignment.center,
children: <Widget>[
_buildContainer(150 * _controller.value),
_buildContainer(200 * _controller.value),
_buildContainer(250 * _controller.value),
_buildContainer(300 * _controller.value),
_buildContainer(350 * _controller.value),
Align(child: Icon(Icons.phone_android, size: 44,)),
],
);
},
);
}
Widget _buildContainer(double radius) {
return Container(
width: radius,
height: radius,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue.withOpacity(1 - _controller.value),
),
);
}

CopsOnRoad
- 237,138
- 77
- 654
- 440
-
I need one more help I want to align this in bottom center of whole layout. I am trying but not getting it – primo Apr 10 '19 at 12:24
-
2Wrap `AnimatedBuilder` in `Align` and change `alignment` to `Alignment.bottomCenter` – CopsOnRoad Apr 10 '19 at 12:28
-
6`with TickerProviderStateMixin ` Add this mixin to your state class, if you got error on vsync – Devinder Jhinjer May 20 '20 at 12:19
-
How can I add this animation on google map's current location(flutter)? – Rohit Luthra May 20 '20 at 13:41
-
@RohitLuthra Last time when I used Google maps, it wasn't supporting flutter regular widget to be displayed as marker, and there was an issue on Github, so not sure if you can display the widgets today. – CopsOnRoad May 21 '20 at 00:33
-
`CurvedAnimation` in your code does nothing. `AnimatedBuilder` API is broken as it does not pass `animation` controller to `builder` function. – mip Sep 13 '21 at 21:44
13
Here is another version using CustomPaint
import 'dart:math' as math show sin, pi, sqrt;
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
class Ripples extends StatefulWidget {
const Ripples({
Key key,
this.size = 80.0,
this.color = Colors.pink,
this.onPressed,
@required this.child,
}) : super(key: key);
final double size;
final Color color;
final Widget child;
final VoidCallback onPressed;
@override
_RipplesState createState() => _RipplesState();
}
class _CirclePainter extends CustomPainter {
_CirclePainter(
this._animation, {
@required this.color,
}) : super(repaint: _animation);
final Color color;
final Animation<double> _animation;
void circle(Canvas canvas, Rect rect, double value) {
final double opacity = (1.0 - (value / 4.0)).clamp(0.0, 1.0);
final Color _color = color.withOpacity(opacity);
final double size = rect.width / 2;
final double area = size * size;
final double radius = math.sqrt(area * value / 4);
final Paint paint = Paint()..color = _color;
canvas.drawCircle(rect.center, radius, paint);
}
@override
void paint(Canvas canvas, Size size) {
final Rect rect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
for (int wave = 3; wave >= 0; wave--) {
circle(canvas, rect, wave + _animation.value);
}
}
@override
bool shouldRepaint(_CirclePainter oldDelegate) => true;
}
class _RipplesState extends State<Ripples> with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Widget _button() {
return Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(widget.size),
child: DecoratedBox(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: <Color>[
widget.color,
Color.lerp(widget.color, Colors.black, .05)
],
),
),
child: ScaleTransition(
scale: Tween(begin: 0.95, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: const _PulsateCurve(),
),
),
child: widget.child,
),
),
),
);
}
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _CirclePainter(
_controller,
color: widget.color,
),
child: SizedBox(
width: widget.size * 2.125,
height: widget.size * 2.125,
child: _button(),
),
);
}
}
class _PulsateCurve extends Curve {
const _PulsateCurve();
@override
double transform(double t) {
if (t == 0 || t == 1) {
return 0.01;
}
return math.sin(t * math.pi);
}
}

jogboms
- 573
- 4
- 11
-
1
-
4Believe it or not, this is more performant than the accepted solution. CustomPainter is verbose, but performant AF, and even this chunk is better than java solutions in which you should install a library only for this – RegularGuy Sep 19 '20 at 20:44