Custom AppBar with Gradient Background
Creating a custom AppBar with a gradient background can significantly enhance your app’s visual appeal. This guide will show you how to implement a stylish gradient AppBar in Flutter.
Why Use Gradient AppBar?
- Enhanced visual appeal
- Modern design aesthetic
- Brand consistency
- Better user experience
- Stand out from competitors
- Professional look and feel
Implementation Steps
-
Basic Gradient AppBar
class GradientAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List<Color> colors; final List<double> stops; const GradientAppBar({ required this.title, this.colors = const [Colors.blue, Colors.purple], this.stops = const [0.0, 1.0], }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: colors, stops: stops, begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: AppBar( title: Text(title), backgroundColor: Colors.transparent, elevation: 0, ), ); } @override Size get preferredSize => Size.fromHeight(kToolbarHeight); }
-
Advanced Gradient AppBar with Actions
class AdvancedGradientAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List<Color> colors; final List<double> stops; final List<Widget> actions; final Widget? leading; final bool centerTitle; final double height; const AdvancedGradientAppBar({ required this.title, this.colors = const [Colors.blue, Colors.purple], this.stops = const [0.0, 1.0], this.actions = const [], this.leading, this.centerTitle = true, this.height = kToolbarHeight, }); @override Widget build(BuildContext context) { return Container( height: height, decoration: BoxDecoration( gradient: LinearGradient( colors: colors, stops: stops, begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: AppBar( title: Text( title, style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), backgroundColor: Colors.transparent, elevation: 0, actions: actions, leading: leading, centerTitle: centerTitle, ), ); } @override Size get preferredSize => Size.fromHeight(height); }
-
Animated Gradient AppBar
class AnimatedGradientAppBar extends StatefulWidget implements PreferredSizeWidget { final String title; final List<List<Color>> colorSets; final Duration duration; const AnimatedGradientAppBar({ required this.title, this.colorSets = const [ [Colors.blue, Colors.purple], [Colors.purple, Colors.red], [Colors.red, Colors.orange], ], this.duration = const Duration(seconds: 5), }); @override _AnimatedGradientAppBarState createState() => _AnimatedGradientAppBarState(); @override Size get preferredSize => Size.fromHeight(kToolbarHeight); } class _AnimatedGradientAppBarState extends State<AnimatedGradientAppBar> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; int _currentIndex = 0; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: widget.duration, ); _animation = Tween<double>(begin: 0, end: 1).animate(_controller) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) { _currentIndex = (_currentIndex + 1) % widget.colorSets.length; _controller.reset(); _controller.forward(); } }); _controller.forward(); } @override Widget build(BuildContext context) { final currentColors = widget.colorSets[_currentIndex]; final nextColors = widget.colorSets[(_currentIndex + 1) % widget.colorSets.length]; return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: [ Color.lerp(currentColors[0], nextColors[0], _animation.value)!, Color.lerp(currentColors[1], nextColors[1], _animation.value)!, ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: AppBar( title: Text(widget.title), backgroundColor: Colors.transparent, elevation: 0, ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }
-
Scroll-Aware Gradient AppBar
class ScrollAwareGradientAppBar extends StatefulWidget implements PreferredSizeWidget { final String title; final List<Color> colors; final ScrollController scrollController; const ScrollAwareGradientAppBar({ required this.title, required this.colors, required this.scrollController, }); @override _ScrollAwareGradientAppBarState createState() => _ScrollAwareGradientAppBarState(); @override Size get preferredSize => Size.fromHeight(kToolbarHeight); } class _ScrollAwareGradientAppBarState extends State<ScrollAwareGradientAppBar> { double _scrollOffset = 0; @override void initState() { super.initState(); widget.scrollController.addListener(_onScroll); } void _onScroll() { setState(() { _scrollOffset = widget.scrollController.offset; }); } @override Widget build(BuildContext context) { final opacity = (1 - (_scrollOffset / 200)).clamp(0.0, 1.0); return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: widget.colors.map((color) { return color.withOpacity(opacity); }).toList(), begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: AppBar( title: Text( widget.title, style: TextStyle( color: Colors.white.withOpacity(opacity), ), ), backgroundColor: Colors.transparent, elevation: 0, ), ); } @override void dispose() { widget.scrollController.removeListener(_onScroll); super.dispose(); } }
Advanced Features
-
Custom Gradient Patterns
class PatternGradientAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List<Color> colors; final CustomPainter pattern; const PatternGradientAppBar({ required this.title, required this.colors, required this.pattern, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: colors, begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: CustomPaint( painter: pattern, child: AppBar( title: Text(title), backgroundColor: Colors.transparent, elevation: 0, ), ), ); } @override Size get preferredSize => Size.fromHeight(kToolbarHeight); }
-
Blur Effect
class BlurredGradientAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final List<Color> colors; final double blurRadius; const BlurredGradientAppBar({ required this.title, required this.colors, this.blurRadius = 10, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient( colors: colors, begin: Alignment.topLeft, end: Alignment.bottomRight, ), ), child: BackdropFilter( filter: ImageFilter.blur( sigmaX: blurRadius, sigmaY: blurRadius, ), child: AppBar( title: Text(title), backgroundColor: Colors.transparent, elevation: 0, ), ), ); } @override Size get preferredSize => Size.fromHeight(kToolbarHeight); }
-
Interactive Gradient
class InteractiveGradientAppBar extends StatefulWidget implements PreferredSizeWidget { final String title; final List<Color> colors; const InteractiveGradientAppBar({ required this.title, required this.colors, }); @override _InteractiveGradientAppBarState createState() => _InteractiveGradientAppBarState(); @override Size get preferredSize => Size.fromHeight(kToolbarHeight); } class _InteractiveGradientAppBarState extends State<InteractiveGradientAppBar> { Offset _dragPosition = Offset.zero; @override Widget build(BuildContext context) { return GestureDetector( onPanUpdate: (details) { setState(() { _dragPosition += details.delta; }); }, child: Container( decoration: BoxDecoration( gradient: LinearGradient( colors: widget.colors, begin: Alignment( _dragPosition.dx / 100, _dragPosition.dy / 100, ), end: Alignment( -_dragPosition.dx / 100, -_dragPosition.dy / 100, ), ), ), child: AppBar( title: Text(widget.title), backgroundColor: Colors.transparent, elevation: 0, ), ), ); } }
Best Practices
-
Design Considerations
- Choose complementary colors
- Consider brand guidelines
- Ensure text readability
- Test on different devices
- Consider dark mode
- Maintain consistency
-
Performance
- Optimize gradient calculations
- Cache gradient values
- Minimize rebuilds
- Use const constructors
- Profile performance
- Handle memory efficiently
-
Accessibility
- Ensure contrast ratios
- Support screen readers
- Provide alternative text
- Consider color blindness
- Test with assistive tools
- Follow guidelines
Common Use Cases
-
Brand Identity
- Company colors
- Logo integration
- Brand consistency
- Visual recognition
- Marketing alignment
- User association
-
User Experience
- Visual hierarchy
- Navigation clarity
- Status indication
- Context awareness
- User feedback
- Interaction cues
-
App Categories
- Social media apps
- E-commerce platforms
- Entertainment apps
- Productivity tools
- Health applications
- Educational apps
Conclusion
Creating a custom gradient AppBar in Flutter can significantly enhance your app’s visual appeal and user experience. By following these guidelines and implementing the provided examples, you can create beautiful and functional gradient AppBars that make your app stand out.