How to Add a Bottom Border to Your SliverAppBar in Flutter
In Flutter, the SliverAppBar
widget offers a beautiful and dynamic way to display app bars. However, you might find yourself needing to add a bottom border to your SliverAppBar
to visually separate it from the content below. This article will guide you through the steps to achieve this elegant design element.
The Challenge: Adding a Bottom Border to SliverAppBar
One of the unique characteristics of SliverAppBar
is its ability to collapse and expand with scrolling. This dynamic behavior makes it challenging to add a simple bottom border that persists regardless of the app bar's state.
The Solution: Custom Painting and SliverPersistentHeader
The key to adding a bottom border to a SliverAppBar
lies in the combination of custom painting and the SliverPersistentHeader
widget. Let's break down the solution step-by-step.
-
Custom Painting: We'll use a custom paint function to draw a border at the bottom of the
SliverAppBar
. This will be handled by a separate widget that we'll define later. -
SliverPersistentHeader: The
SliverPersistentHeader
widget allows us to control the size and behavior of the header, ensuring that our custom border is always displayed at the bottom.
Implementing the Solution
Here's a practical example of how to implement this solution:
import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
const MyAppBar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 60,
maxHeight: 80,
child: Container(
color: Colors.blue,
child: const Center(
child: Text(
'My App',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
),
),
),
// Your other slivers go here
],
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
const _SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
@override
double get minExtent => minHeight;
@override
double get maxExtent => maxHeight;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Stack(
children: [
Container(
height: maxHeight,
color: Colors.blue,
child: child,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: CustomPaint(
size: Size.infinite,
painter: _BottomBorderPainter(),
),
),
],
);
}
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
class _BottomBorderPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.white
..strokeWidth = 2.0;
canvas.drawLine(Offset(0, 0), Offset(size.width, 0), paint);
}
@override
bool shouldRepaint(_BottomBorderPainter oldDelegate) => false;
}
In this code:
- We create a
SliverPersistentHeader
with aminHeight
andmaxHeight
to control the app bar's size. - Inside the
build
method of ourSliverAppBarDelegate
, we use aStack
to overlay our custom border on top of the app bar. - The
_BottomBorderPainter
class draws a white line along the bottom of the canvas, creating the bottom border effect.
Customization
The example uses a white border, but you can easily customize the color, thickness, and even add more complex border styles by modifying the Paint
object in the _BottomBorderPainter
.
Tips
- Ensure your
SliverPersistentHeader
is pinned (pinned: true
) to keep the bottom border visible even when theSliverAppBar
is collapsed. - You can adjust the
minHeight
andmaxHeight
values to control the size of yourSliverAppBar
. - For more complex border designs, explore other custom painting techniques or use a dedicated
Divider
widget.
Conclusion
Adding a bottom border to a SliverAppBar
in Flutter can enhance your app's visual appeal and provide clear separation between different content sections. By using custom painting and the SliverPersistentHeader
widget, you can achieve this effect with ease, creating a smooth and dynamic user experience.