Вы можете использовать несколько подходов к этой проблеме. Я бы предпочел использовать AnimationController, который повторяется.
animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
)
..forward()
..repeat(reverse: true);
Вы можете, например, анимировать размер отступа вокруг кнопки. Я бы использовал круглые контейнеры вокруг IconButton.
Для этого вам нужно инициализировать AnimationController в вашем состоянии. Помните об утилизации, когда жизненный цикл виджета заканчивается.
Вот пример кода и дартпада:
https://codepen.io/orestesgaolin/pen/MWajRGV
https://dartpad.dartlang.org/ca4838f17ea6061cf0212a4b689eaf2a
И полный исходный код можно найти в этой сущности
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Animated Icon',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController animationController;
@override
void initState() {
super.initState();
animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
)
..forward()
..repeat(reverse: true);
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
child: Center(
child: AnimatedBuilder(
animation: animationController,
builder: (context, child) {
return Container(
decoration: ShapeDecoration(
color: Colors.white.withOpacity(0.5),
shape: CircleBorder(),
),
child: Padding(
padding: EdgeInsets.all(8.0 * animationController.value),
child: child,
),
);
},
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: CircleBorder(),
),
child: IconButton(
onPressed: () {},
color: Colors.blue,
icon: Icon(Icons.calendar_today, size: 24),
),
),
),
),
),
);
}
}