I designed a simple animated custom button with AnimatedContainer. When the button is clicked, its shadow disappears and its size shrinks by 10 pixels and returns to its previous state after 120 milliseconds. The icon widget on the button moves in harmony with the animation, but the text widget does not. What I want is either both of them move or neither of them.
You can see the problem more clearly in the video
IAnimatedButton(
onTap: () {},
margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.sports_esports, size: 32),
boxWidth16,
Text(
'howPlay'.tr,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
)
class IAnimatedButton extends StatefulWidget {
const IAnimatedButton(
{super.key,
required this.onTap,
this.backColor,
required this.margin,
required this.child});
final void Function()? onTap;
final Widget child;
final Color? backColor;
final EdgeInsetsGeometry? margin;
@override
State<IAnimatedButton> createState() => _IAnimatedButtonState();
}
class _IAnimatedButtonState extends State<IAnimatedButton> {
bool isPressed = false;
Size? size;
double? height;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(
(_) {
size = context.size;
height = size!.height - 16;
},
);
}
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: height ?? 0,
maxHeight: 80,
minWidth: 0,
maxWidth: double.maxFinite),
child: Center(
child: GestureDetector(
onTap: () async {
height = size!.height - 26;
setState(() => isPressed = !isPressed);
await Future.delayed(const Duration(milliseconds: 120));
height = size!.height - 16;
setState(() => isPressed = !isPressed);
widget.onTap == null ? null : widget.onTap!();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.all(16),
margin: widget.margin,
height: height,
decoration: BoxDecoration(
color: widget.backColor ?? Get.theme.colorScheme.primaryContainer,
borderRadius: BorderRadiuses.dialogRadius,
boxShadow: [
isPressed
? BoxShadow(
color: colorDarken(widget.backColor ??
Get.theme.colorScheme.primaryContainer),
offset: const Offset(0, 0),
)
: BoxShadow(
color: colorDarken(widget.backColor ??
Get.theme.colorScheme.primaryContainer),
offset: const Offset(-4, 4),
),
],
),
alignment: Alignment.center,
child: widget.child,
),
),
),
);
}
}
I assigned the lone Text widget as a child and it doesn’t work in many different scenarios