Flutter Custom Widgets & Animations: The Complete Guide to Mastering UI
FlutterPulseThis article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!🚀

Customizing Widgets and Animations in Flutter with Example
Customizing Widgets and Animations in Flutter with Example
🚀Supercharge Your UI: Customizing Widgets and Animations in Flutter (With Code Examples)
Flutter is famous for its "everything's a widget" approach. While the Material and Cupertino widget libraries are vast, Flutter's true power lies in your ability to create custom widgets and design unique animations that differentiate your app.
Learning to customize these building blocks is essential for any developer who aspires to build professional and memorable user interfaces (UIs).
Parte 1:Creating Custom Widgets (The Building Block)
A custom widget is simply an encapsulation of one or more pre-existing widgets. This improves code reuse, readability, and makes your application easier to maintain.
🧱 Example: A Reusable Profile Button (ProfileButton)
Instead of building a Row with a CircleAvatar and aTextEvery time a profile needs to be displayed, we create a custom widget.
Code for profile_button.dart:
import 'package:flutter/material.dart';
class ProfileButton extends StatelessWidget {
// Custom properties defined in the constructor
final String userName;
final String imageUrl;
final VoidCallback onTap;
const ProfileButton({
Key? key,
required this.userName,
required this.imageUrl,
required this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
radius: 20,
),
const SizedBox(width: 10),
Text(
userName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
}
Use in the application (main.dart):
// ... inside the build() method of a widget
ProfileButton(
userName: 'Alice',
imageUrl: 'https://ejemplo.com/avatar.jpg', // Replace with a real URL
onTap: () {
print('Perfil de Alice pulsado');
},
),
💡 Why is this important?
- Reusability: Use it
ProfileButtonin your sidebar, header, or anywhere else without repeating your design code. - Encapsulation: If you decide to change the font or size of your avatar, you only need to modify one file (
profile_button.dart).
Parte 2: Custom Animations (Bringing UI to Life)
Animations transform a static UI into a dynamic user experience. Flutter offers two types:
- Implicit Animations (Easy): These use widgets like
AnimatedContainer,AnimatedOpacity, orAnimatedSize. Simply change a property and the widget animates automatically. - Explicit Animations (Custom): These use
AnimationControllerandTweenfor full control over the transition. TheAnimatedBuilderwidget is the key tool for this.
✨ Example: A Pulsing Container with AnimatedBuilder
We'll create a container that rhythmically changes scale and color, as if it were "pulsing" (useful for status indicators).
codePulsingContainer (requires a StatefulWidget):
import 'package:flutter/material.dart';
class PulsingContainer extends StatefulWidget {
const PulsingContainer({super.key});
@override
State<PulsingContainer> createState() => _PulsingContainerState();
}
class _PulsingContainerState extends State<PulsingContainer>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnimation;
late Animation<Color?> _colorAnimation;
@override
void initState() {
super.initState();
// 1. Initialize the controller for 1 second
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1000),
)..repeat(reverse: true); //
// 2. Defines the scale animation (Tween)
_scaleAnimation = Tween<double>(begin: 1.0, end: 1.15).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
// 3. Defines the color animation (Tween)
_colorAnimation = ColorTween(
begin: Colors.blue.shade300,
end: Colors.blue.shade700,
).animate(_controller);
}
@override
Widget build(BuildContext context) {
// 4. Use AnimatedBuilder to rebuild just the widget
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.scale(
scale: _scaleAnimation.value,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: _colorAnimation.value, // Color animado
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: _colorAnimation.value!.withOpacity(0.5),
blurRadius: 10,
),
],
),
child: child,
),
);
},
child: const Center(
child: Text('Pulse', style: TextStyle(color: Colors.white)),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Use in the application (main.dart):
// ... inside the build() method of a widget
Center(
child: PulsingContainer(),
),
Conclusion
Customizing widgets and animations in Flutter isn't just a way to enhance your UI; it's a fundamental practice for creating clean code architecture and delivering an exceptional user experience. By mastering these techniques, you'll transform your app from a simple functional tool into a polished and engaging digital product.