2

SliverGrid我正在构建一个带有颤动的应用程序,并且在使用inside构建项目网格时卡住了CustomScrollView,我无法在其背景中添加边框半径。请注意,我可以为单个网格项添加半径。

这是我尝试过的

Scaffold(
  backgroundColor: Colors.orange,
  body: CustomScrollView(
    slivers: <Widget>[
      SliverAppBar(
        pinned: true,
        floating: true,
        expandedHeight: 250.0,
        flexibleSpace: FlexibleSpaceBar(
            background: Image.asset(
              'assets/images/000.png',
              fit: BoxFit.cover,
            ),
            title: Text('Hello there')),
      ),
      SliverGrid(
        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 200.0,
          mainAxisSpacing: 10.0,
          crossAxisSpacing: 10.0,
          childAspectRatio: 4.0,
        ),
        delegate: SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            return Container(
              margin: EdgeInsets.symmetric(
                horizontal: 15,
                vertical: 15,
              ),
              alignment: Alignment.center,
              color: Colors.teal[100 * (index % 9)],
              child: Text('grid item $index'),
            );
          },
          childCount: 30,
        ),
      ),
    ],
  ),
);

下面的这张图片是我用上面的代码得到的。 我现在需要的是在橙色部分的 topLeft 和 topRight 中添加一个圆形边框半径。

在此处输入图像描述

4

2 回答 2

4

您可以向 sliverAppBar 添加一个形状

return Scaffold(
      backgroundColor: Colors.orange,
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            floating: true,
            expandedHeight: 250.0,
            shape: RoundedRectangleBorder(
                borderRadius:
                   BorderRadius.vertical(bottom: Radius.circular(16))), //like this
            flexibleSpace: FlexibleSpaceBar(
                background: Container(color: Colors.blueAccent), //changed it because I dont have the image asset
                title: Text('Hello there')),
          ),
          SliverGrid(
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 200.0,
              mainAxisSpacing: 10.0,
              crossAxisSpacing: 10.0,
              childAspectRatio: 4.0,
            ),
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  margin: EdgeInsets.symmetric(
                    horizontal: 15,
                    vertical: 15,
                  ),
                  alignment: Alignment.center,
                  color: Colors.teal[100 * (index % 9)],
                  child: Text('grid item $index'),
                );
              },
              childCount: 100,
            ),
          ),
        ],
      ),
    );
  }

在此处输入图像描述

如果你想要它的另一种方式,也许你应该创建一个自定义 ShapeBorder 并覆盖 getOuterPath 以超出形状并使其看起来像橙色的一侧是带有形状的一侧。让我知道您是否希望以这种方式尝试更新答案

更新

我相信你正在寻找这样的东西 在此处输入图像描述

    class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.orange,
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            floating: true,
            expandedHeight: 250.0,
            shape: _CustomShape(), //like this
            flexibleSpace: FlexibleSpaceBar(
              background: Image.network(
                "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                fit: BoxFit.cover,
              ),
              title: Text('Hello there'),
            ),

          ),
          SliverGrid(
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 200.0,
              mainAxisSpacing: 10.0,
              crossAxisSpacing: 10.0,
              childAspectRatio: 4.0,
            ),
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  margin: EdgeInsets.symmetric(
                    horizontal: 15,
                    vertical: 15,
                  ),
                  alignment: Alignment.center,
                  color: Colors.teal[100 * (index % 9)],
                  child: Text('grid item $index'),
                );
              },
              childCount: 100,
            ),
          ),
        ],
      ),
    );
  }
}

class _CustomShape extends ShapeBorder {
  const _CustomShape({
    this.side = BorderSide.none,
    this.borderRadius = BorderRadius.zero,
  }) : assert(side != null),
       assert(borderRadius != null);

  final BorderRadiusGeometry borderRadius;

  /// The style of this border.
  final BorderSide side;

   @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.all(side.width);

  @override
  ShapeBorder scale(double t) {
    return _CustomShape(
      side: side.scale(t),
      borderRadius: borderRadius * t,
    );
  }

  @override
  ShapeBorder lerpFrom(ShapeBorder a, double t) {
    assert(t != null);
    if (a is ContinuousRectangleBorder) {
      return ContinuousRectangleBorder(
        side: BorderSide.lerp(a.side, side, t),
        borderRadius: BorderRadiusGeometry.lerp(a.borderRadius, borderRadius, t),
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  ShapeBorder lerpTo(ShapeBorder b, double t) {
    assert(t != null);
    if (b is ContinuousRectangleBorder) {
      return ContinuousRectangleBorder(
        side: BorderSide.lerp(side, b.side, t),
        borderRadius: BorderRadiusGeometry.lerp(borderRadius, b.borderRadius, t),
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  Path getInnerPath(Rect rect, { TextDirection textDirection }) {
    double length = 16;
    return Path()
      ..lineTo(0, rect.height - length)
      ..lineTo(rect.width, rect.height - length)
      ..lineTo(rect.width, 0)
      ..close();
  }

  @override
  Path getOuterPath(rect, {TextDirection textDirection}) {
    double length = 16; //its just a random number I came up with to test the border
    return Path()
      ..lineTo(0, rect.height)
      ..quadraticBezierTo(length / 4, rect.height - length, length, rect.height - length)
      ..lineTo(rect.width - length, rect.height - length)
      ..quadraticBezierTo(rect.width - (length / 4), rect.height - length, rect.width, rect.height)
      ..lineTo(rect.width, 0)
      ..close();
  }

  @override
  void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
    if (rect.isEmpty)
      return;
    switch (side.style) {
      case BorderStyle.none:
        break;
      case BorderStyle.solid:
        final Path path = getOuterPath(rect, textDirection: textDirection);
        final Paint paint = side.toPaint();
        canvas.drawPath(path, paint);
        break;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is ContinuousRectangleBorder
        && other.side == side
        && other.borderRadius == borderRadius;
  }

  @override
  int get hashCode => hashValues(side, borderRadius);

}

我所做的是创建一个基于 ContinuousRectangleBorder 的自定义 ShapeBorder 但将 getOuterPath 和 getInnerPath 更改为一个常量值以使其看起来像这样(例如,如果您想要一个可以在多种情况下使用的自定义类可能会改变构造函数中的一些其他值)。

我仍然在 SliverAppBar 中使用,因为那是允许我使用 shape 属性更改形状的小部件,但是使用 getOuterPath 我绘制了从小部件的最大高度到 maxHeight - 16 的曲线(我想出了一个随机数,就像我添加时的前一个示例BorderRadius.vertical(bottom: Radius.circular(16)))。如果您没有 Sliver AppBar 而不是 Scaffold 中的 AppBar,您可以将 CustomScrollView 包装在没有边距和形状的 Card 中RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)))以获得类似的效果

更新包

添加flutter_group_sliver: ^0.0.2到您的 pubspec.yaml 依赖项

dependencies:
  flutter:
    sdk: flutter
  flutter_group_sliver: ^0.0.2

将其导入您的项目并在 CustomScrollView 中使用新类 SliverGroupBuilder(),它基本上是一个制成 Sliver 的容器,因此您可以在 Sliver 中使用边距、装饰、填充选项

import 'package:flutter_group_sliver/flutter_group_sliver.dart';
Scaffold(
      backgroundColor: Colors.pink[100],
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            floating: true,
            expandedHeight: 250.0,
            elevation: 0.0,
            forceElevated: false,
            flexibleSpace: FlexibleSpaceBar(
              background: Image.network(
                "https://happypixelmedia.com/wp-content/uploads/2019/10/Web-design-ideas-to-look-forward-to-in-2020-cover-1.jpg",
                fit: BoxFit.cover,
              ),
              title: Text('Hello there'),
            ),
          ),
          SliverGroupBuilder(
            margin: EdgeInsets.zero,
            decoration: BoxDecoration(
              color: Colors.orange,
              borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
            ),
            child: SliverGrid(
              gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
                childAspectRatio: 4.0,
              ),
              delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  return Container(
                    margin: EdgeInsets.symmetric(
                      horizontal: 15,
                      vertical: 15,
                    ),
                    alignment: Alignment.center,
                    color: Colors.teal[100 * (index % 9)],
                    child: Text('grid item $index'),
                  );
                },
                childCount: 100,
              ),
            ),
          )
        ],
      ),
    )

Scaffold 背景为粉红色,SliverGroupBuilder 为橙色,带有BorderRadius.vertical(top: Radius.circular(16)),

在此处输入图像描述

关闭的 SliverAppBar

在此处输入图像描述

这种方法可以满足您的需求,但您必须注意脚手架背景的颜色以使其不同,以便您可以看到边界半径

检查https://pub.dev/packages/flutter_group_sliver#-readme-tab-以获取该软件包的更多信息

于 2020-05-20T20:28:49.147 回答
1

这是我的方法

 SliverAppBar(
              elevation: 0,//remove elevetion
              backgroundColor: Colors.white, // match the color of sliver grid/list
              leading: SizedBox(), // // hide arrow icon
              leadingWidth: 0.0, // hide arrow icon
              expandedHeight: 200,
              stretch: true, 
              flexibleSpace: FlexibleSpaceBar(
                collapseMode: CollapseMode.pin, // to make radius remain if scrolled
                title: _myTitle,
                titlePadding: EdgeInsets.all(30),
                centerTitle: true,
                stretchModes: [
                  StretchMode.zoomBackground, // zoom effect
                  StretchMode.fadeTitle, // fade effect
                ],
                background: Container(
                  color: Colors.white,
                  child: Stack(
                    fit: StackFit.expand, // expand stack
                    children: [
                      ColorFiltered(
                        colorFilter: ColorFilter.mode(
                          Colors.black.withOpacity(0.5),
                          BlendMode.srcOver,
                        ),
                        child: Container(
                          child: Image.network(
                            "$imageLink",
                            fit: BoxFit.cover,
                          ),
                        ),
                      ),
                      Positioned(
                        child: Container(
                          height: 30,
                          clipBehavior: Clip.antiAlias,
                          decoration: BoxDecoration(
                              color: Colors.white,
                              borderRadius: BorderRadius.vertical(
                                top: Radius.circular(50),
                              ),
                              border: Border.all(
                                color: Colors.white,
                                width: 0,
                              )),
                        ),
                        bottom: -1,
                        left: 0,
                        right: 0,
                      ),
                      Positioned(
                        bottom: 0, // to bottom
                        right: 45, // to right 45
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(120),
                          child: Container(
                            color: darkBlue,
                            width: 60,
                            height: 60,
                            child: Icon(
                              LineIcons.store,
                              size: 26,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            )
    )

在此处输入图像描述

在此处输入图像描述

于 2021-04-25T06:04:36.427 回答