有谁知道如何向 Cupertino SliverAppBar 添加渐变背景?
Does anyone know how to add a gradient background to CupertinoSliverAppBar?
我想在 Flutter 应用程序中向 CupertinoSliverAppBar
添加渐变背景,但我似乎不知道该怎么做。 SliverAppBar
有一个 flexibleSpace
属性 可以接受渐变,但 CupertinoSliverAppBar
只有一个 backgroundColor
属性.
或者,如果可以将 flexibleSpace
中的标题向左移动一些,我可以这样做。但我也想不通。
我读了这些:
并且这个问题在 Flutter 存储库中打开:https://github.com/flutter/flutter/issues/25144
@rmtmckenzie 成功了!值得注意的是,这也适用于 CupertinoSliverNavigationBar
。此外,所有过渡动画都会保留,但您将看到 backgroundColor
属性 动画的背景除外。您可以通过使用一种渐变颜色作为 backgroundColor
来作弊,但这并不完美。渐变确实呈现在内容下方。见下文:
这实际上有点困难 - 正如您提到的 CupertinoSliverAppBar 不支持 'flexibleSpace' 或类似的东西,因此您不得不尝试使用无法满足您需要的 backgroundColor要么。
我建议您在 Flutter 存储库上提出一个问题,说明这是不可能的,以及您为什么要这样做。他们可能不会立即对此采取行动,但如果他们意识到人们愿意这样做,它可能会发生。
不过,并不是所有希望立即修复的希望都破灭了,我们可以作弊! (虽然我希望你在编写版本时使用不那么丑陋的渐变)
我所做的是对 Border 进行子类化,然后覆盖它绘制的内容,以便在绘制实际边框之前绘制您传入的渐变。这是可行的,因为它给出了一个覆盖整个应用栏的绘制上下文,并在应用栏的背景上绘制但低于其内容(希望 - 它似乎至少在标题下方,所以我认为它也在其他所有内容下方)。背景颜色仍然绘制在 appbar 下,因此如果您的渐变有点透明,您可能需要将 backgroundColor 设置为 Colors.transparent.
代码如下:
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(),
],
),
),
],
),
);
}
}
你可以试试这个
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Colors.red,
Colors.blue
],
),
),
),
我想在 Flutter 应用程序中向 CupertinoSliverAppBar
添加渐变背景,但我似乎不知道该怎么做。 SliverAppBar
有一个 flexibleSpace
属性 可以接受渐变,但 CupertinoSliverAppBar
只有一个 backgroundColor
属性.
或者,如果可以将 flexibleSpace
中的标题向左移动一些,我可以这样做。但我也想不通。
我读了这些:
并且这个问题在 Flutter 存储库中打开:https://github.com/flutter/flutter/issues/25144
@rmtmckenzie 成功了!值得注意的是,这也适用于 CupertinoSliverNavigationBar
。此外,所有过渡动画都会保留,但您将看到 backgroundColor
属性 动画的背景除外。您可以通过使用一种渐变颜色作为 backgroundColor
来作弊,但这并不完美。渐变确实呈现在内容下方。见下文:
这实际上有点困难 - 正如您提到的 CupertinoSliverAppBar 不支持 'flexibleSpace' 或类似的东西,因此您不得不尝试使用无法满足您需要的 backgroundColor要么。
我建议您在 Flutter 存储库上提出一个问题,说明这是不可能的,以及您为什么要这样做。他们可能不会立即对此采取行动,但如果他们意识到人们愿意这样做,它可能会发生。
不过,并不是所有希望立即修复的希望都破灭了,我们可以作弊! (虽然我希望你在编写版本时使用不那么丑陋的渐变)
我所做的是对 Border 进行子类化,然后覆盖它绘制的内容,以便在绘制实际边框之前绘制您传入的渐变。这是可行的,因为它给出了一个覆盖整个应用栏的绘制上下文,并在应用栏的背景上绘制但低于其内容(希望 - 它似乎至少在标题下方,所以我认为它也在其他所有内容下方)。背景颜色仍然绘制在 appbar 下,因此如果您的渐变有点透明,您可能需要将 backgroundColor 设置为 Colors.transparent.
代码如下:
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(),
],
),
),
],
),
);
}
}
你可以试试这个
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Colors.red,
Colors.blue
],
),
),
),