有谁知道如何向CupertinoSliverAppBar添加渐变背景?

时间:2019-05-09 08:54:44

标签: dart flutter flutter-cupertino

我正在尝试在Flutter应用程序中为CupertinoSliverAppBar添加渐变背景,但似乎无法弄清楚该如何做。 SliverAppBar具有flexibleSpace属性,可以接受渐变,但是CupertinoSliverAppBar仅具有backgroundColor属性。

或者,如果可以将flexibleSpace中的标题向左移动,我可以这样做。但是我也无法弄清楚。

我读了这些:

此问题在Flutter存储库上打开:https://github.com/flutter/flutter/issues/25144

@rmtmckenzie可以解决问题!值得注意的是,这也适用于CupertinoSliverNavigationBar。此外,除了将看到backgroundColor属性被动画化的背景之外,所有过渡动画都将保留。您可以使用渐变的一种颜色作为backgroundColor作弊,但这并不完美。渐变确实呈现在内容下方。见下文:

enter image description here

2 个答案:

答案 0 :(得分:1)

这实际上有点困难-正如您提到的CupertinoSliverAppBar不支持'flexibleSpace'或类似的东西一样,因此您不得不尝试使用backgroundColor,它也不能满足您的需要。

我建议在Flutter存储库上打开一个问题,指出这是不可能的,以及为什么要这样做。他们可能不会立即对此采取行动,但是如果他们知道人们愿意这样做,则可能会发生。

虽然并非所有希望都立刻消失,但我们可以作弊! (尽管我希望您在编写版本时希望使用一个不太可怕的渐变色

screenshot showing cupertinoappbar with gradient screenshot showing cupertionoappbar collapsed with gradient

我所做的是将子类划分为Border,然后覆盖它绘制的内容,以便它绘制您在绘制实际边框之前传入的渐变。之所以可行,是因为它具有一个覆盖整个应用程序栏的绘制上下文,并且在应用程序栏的背景上绘制但在其内容下方(希望-至少似乎在标题下方,因此我认为它也位于其他所有内容之下)。背景颜色仍会在应用栏下方绘制,因此,如果您的渐变有些透明,则可能需要将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(),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

答案 1 :(得分:0)

您可以尝试

flexibleSpace: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.centerLeft,
                end: Alignment.centerRight,
                colors: [
                  Colors.red,
                  Colors.blue
                ],
              ),
            ),
          ),