Does anyone know how to add a gradient background to CupertinoSliverAppBar?
This is actually a bit difficult - as you mentioned the CupertinoSliverAppBar doesn't support 'flexibleSpace' or anything like it, so you're stuck with trying to use the backgroundColor which doesn't do what you need either.
I'd recommend opening an issue on the Flutter repo stating that it isn't possible and why you'd like to do it. They probably won't take action on it right away but if they're aware that people would like to do it it, it might happen.
Not all hope is lost for an immediate fix though, we can cheat! (although I'm hoping you'll use a less terifyingly ugly gradient when you write your version)
What I've done is subclassed Border, and then overridden what it draws so that it draws a gradient you pass in before drawing the actual border. This works because it's given a paint context that covers the entire app bar, and draws over the background of the appbar but below its content (hopefully - it seems to be below the title at least so I assume it's below everything else too). The background color is still drawn under the appbar so if your gradient is somewhat transparent you'll probably want to set the backgroundColor to Colors.transparent.
Here's the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(GradientAppBar());
class GradientCheatingBorder extends Border {
const GradientCheatingBorder({
this.gradient,
BorderSide top = BorderSide.none,
BorderSide right = BorderSide.none,
BorderSide bottom = BorderSide.none,
BorderSide left = BorderSide.none,
}) : super(top: top, right: right, bottom: bottom, left: left);
const GradientCheatingBorder.fromBorderSide(BorderSide side, {this.gradient})
: super.fromBorderSide(side);
factory GradientCheatingBorder.all({
Color color = const Color(0xFF000000),
double width = 1.0,
BorderStyle style = BorderStyle.solid,
Gradient gradient,
}) {
final BorderSide side =
BorderSide(color: color, width: width, style: style);
return GradientCheatingBorder.fromBorderSide(side, gradient: gradient);
}
final Gradient gradient;
@override
void paint(
Canvas canvas,
Rect rect, {
TextDirection textDirection,
BoxShape shape = BoxShape.rectangle,
BorderRadius borderRadius,
}) {
if (gradient != null) {
canvas.drawRect(
rect,
Paint()
..shader = gradient.createShader(rect)
..style = PaintingStyle.fill,
);
}
super.paint(
canvas,
rect,
textDirection: textDirection,
shape: shape,
borderRadius: borderRadius,
);
}
}
class GradientAppBar extends StatefulWidget {
@override
_GradientAppBarState createState() => _GradientAppBarState();
}
class _GradientAppBarState extends State<GradientAppBar> {
@override
Widget build(BuildContext context) {
return CupertinoApp(
home: CustomScrollView(
slivers: <Widget>[
CupertinoSliverNavigationBar(
largeTitle: Text("Title"),
border: GradientCheatingBorder.fromBorderSide(
BorderSide.none,
gradient: LinearGradient(colors: [Colors.black, Colors.white]),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
Container(
color: Colors.blue,
height: 500,
),
Divider(),
Container(
color: Colors.black12,
height: 500,
),
Divider(),
Container(
color: Colors.lightBlue,
height: 500,
),
Divider(),
Container(
color: Colors.lightGreen,
height: 500,
),
Divider(),
],
),
),
],
),
);
}
}
Benjamin
Currently a freelance mobile & frontend developer, I have worked on a great variety of projects over the past decade. Always curious about the latest technological trends, I follow the cutting edge innovations and strive to stay up to date. I love a challenge and live by the motto difficult takes a day. Impossible takes a week.
Updated on December 11, 2022Comments
-
Benjamin over 1 year
I am trying to add a gradient background to a
CupertinoSliverAppBar
in a Flutter app but I cannot seem to figure out how to do it. TheSliverAppBar
has aflexibleSpace
property that would accept a gradient but theCupertinoSliverAppBar
only has abackgroundColor
property.Alternatively, if it were possible to move the title in the
flexibleSpace
more to the left, I could go with that. But I cannot figure that out either.I read these:
And this issue opened on the Flutter repository: https://github.com/flutter/flutter/issues/25144
@rmtmckenzie does the trick! It is worth noting this also works with
CupertinoSliverNavigationBar
. Also, all transition animations are preserved except for that of the background for which you will bee seeing thebackgroundColor
property being animated. You can cheat by using one of the gradient's colors as thebackgroundColor
but it is not perfect. The gradient is indeed rendered below the content. See below:-
Benjamin about 5 years@rmtmckenzie any ideas ?
-
Hussnain Haidar about 4 yearspub.dev/packages/gradientscaffoldwidget CupertinoPageGradientScaffold method.
-
Nithin Sai about 4 yearsAlso, I wanted to know if we can add an image background to Cupertino sliver nav bar?? Anyone?
-
Benjamin about 4 years@NithinSai I have created a PR for that (and gradient): github.com/flutter/flutter/pull/33177. It still needs a little cleanup to pass the tests
-
Nithin Sai about 4 years@Benjamin that's a great idea! Thanks
-
-
Benjamin about 5 yearsIt may be ugly, but it is damn clever! Thank you!
-
Benjamin about 5 yearsthere is no flexibleSpace in the CupertinoSliverNavigationBar.