Кто-нибудь знает, как добавить градиентный фон в CupertinoSliverAppBar? - PullRequest
2 голосов
/ 09 мая 2019

Я пытаюсь добавить градиентный фон к CupertinoSliverAppBar в приложении Flutter, но не могу понять, как это сделать.У SliverAppBar есть свойство flexibleSpace, которое принимает градиент, но у CupertinoSliverAppBar есть только свойство backgroundColor.

В качестве альтернативы, если бы можно было переместить заголовок в flexibleSpace moreслева я мог бы пойти с этим.Но я не могу понять это тоже.

Я прочитал это:

И эта проблема открылась в репозитории Flutter: https://github.com/flutter/flutter/issues/25144

@ rmtmckenzie делает свое дело!Стоит отметить, что это также работает с CupertinoSliverNavigationBar.Кроме того, сохраняются все анимации перехода, кроме фоновой, для которой вы увидите анимированное свойство backgroundColor.Вы можете обмануть, используя один из цветов градиента как backgroundColor, но он не идеален.Градиент действительно отображается ниже содержимого.См. Ниже:

enter image description here

Ответы [ 2 ]

1 голос
/ 09 мая 2019

Это на самом деле немного сложно - как вы упомянули, CupertinoSliverAppBar не поддерживает «FlexibleSpace» или что-то подобное, поэтому вы застряли на попытке использовать backgroundColor, который тоже не делает то, что вам нужно.

Я бы порекомендовал открыть вопрос о репозитории Flutter, заявив, что это невозможно и почему вы хотите это сделать. Вероятно, они не сразу примут меры, но если они знают, что люди хотели бы сделать это, это может произойти.

Не вся надежда потеряна для немедленного исправления, хотя мы можем обмануть! (хотя я надеюсь, что вы будете использовать менее уродливый градиент при написании своей версии)

screenshot showing cupertinoappbar with gradientscreenshot 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(),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
0 голосов
/ 14 мая 2019

вы можете попробовать это

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