【问题标题】:How to Give BorderRadius to SliverList如何将 BorderRadius 赋予 SliverList
【发布时间】:2023-04-03 02:08:01
【问题描述】:

我在我的项目中使用SliverAppBarSliverListView

我需要BorderRadius 到我的SliverList,这是我的SliverAppBar 的底部。

这是我需要的截图:

这是我的代码:

Scaffold(
    body: CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
            backgroundColor: Colors.transparent,
            brightness: Brightness.dark,
            actions: <Widget>[
              IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
              IconButton(icon: Icon(Icons.share), onPressed: () {})
            ],
            floating: false,
            pinned: false,
            //title: Text("Flexible space title"),
            expandedHeight: getHeight(context) - MediaQuery.of(context).padding.top,
            flexibleSpace: Container(
              height: double.infinity,
              width: double.infinity,
              decoration: BoxDecoration(
                image: DecorationImage(
                  fit: BoxFit.cover,
                  image: AssetImage("assets/images/Rectangle-image.png")
                )
              ),
            ),
            bottom: _bottomWidget(context),
          ),
           SliverList(
            delegate: SliverChildListDelegate(listview),
          ),
      ],
    ),
  )

所以,有了这段代码,用户界面就变成了这样......

可以建议我可以采取的任何其他方法来实现这种设计...

【问题讨论】:

  • 目前似乎不可能。我刚刚在 GitHub 上发布了一个问题:github.com/flutter/flutter/issues/62781在此期间您是否能够找到任何解决方法?
  • 为了解决问题,我删除了与条子相关的所有内容,并添加了滚动控制器以实现自定义滚动效果。不像条子那样光滑,但现在可以使用。

标签: flutter dart flutter-layout flutter-sliver


【解决方案1】:

我使用SliverToBoxAdapter 我这样的代码实现了这个设计。

final sliver = CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(),
    SliverToBoxAdapter(
      child: Container(
        color: Color(0xff5c63f1),
        height: 20,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Container(
              height: 20,
              decoration: BoxDecoration(
                color: Colors.white,
                  borderRadius: BorderRadius.only(
                    topLeft: const Radius.circular(20.0),
                    topRight: const Radius.circular(20.0),
                  ),
              ),
            ),
          ],
        ),
      ),
    ),
    SliverList(),
  ],
);

我在 SliverToBoxAdapter 中使用了 2 个容器。

SliverToBoxAdapter 位于 Sliver Appbar 和 Sliver List 之间。

  1. 首先我为角边缘创建一个蓝色(应该是 Appbar 颜色)容器。
  2. 然后我在蓝色容器内创建具有边框半径的相同高度的白色容器以用于列表视图。

Preview on dartpad

【讨论】:

  • 更多关于 2 Container 的描述可以更好地帮助我。
  • @black-hacker 我添加了我使用的确切代码,并更新了解释。
  • 如果您有图像,这将不起作用......它正在使用,因为您的颜色与应用程序颜色匹配,但如果您有图像,则图像将从条子列表中分离出来, ,您需要在条子列表后面设置图像 false。
【解决方案2】:

解决方案

在撰写本文时,还没有支持此功能的小部件。方法是使用Stack 小部件和您自己的SliveWidget

之前:

这是您的默认代码:


 import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flexible space title',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
              backgroundColor: Colors.transparent,
              brightness: Brightness.dark,
              actions: <Widget>[IconButton(icon: Icon(Icons.favorite), onPressed: () {}), IconButton(icon: Icon(Icons.share), onPressed: () {})],
              floating: false,
              pinned: false,
              expandedHeight: 250 - MediaQuery.of(context).padding.top,
              flexibleSpace: Container(
                height: 550,
                width: double.infinity,
                decoration: BoxDecoration(
                    image: DecorationImage(
                        fit: BoxFit.cover,
                        image: NetworkImage(
                            'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
              ),
              //bottom: _bottomWidget(context),
            ),
            SliverList(
              delegate: SliverChildListDelegate(_listview(50)),
            ),
          ],
        ),
      ),
    );
  }
}

List _listview(int count) {
  List<Widget> listItems = List();

  listItems.add(Container(
    color: Colors.black,
    height: 50,
    child: TabBar(
      tabs: [FlutterLogo(), FlutterLogo()],
    ),
  ));

  for (int i = 0; i < count; i++) {
    listItems.add(new Padding(padding: new EdgeInsets.all(20.0), child: new Text('Item ${i.toString()}', style: new TextStyle(fontSize: 25.0))));
  }

  return listItems;
}

之后

这是您使用 StackSliveWidget 小部件完成的代码:

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flexible space title',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        body: Stack(
          children: [
            Container(
              height: 550,
              width: double.infinity,
              decoration: BoxDecoration(
                  image: DecorationImage(
                      fit: BoxFit.cover,
                      image: NetworkImage(
                          'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
            ),
            CustomScrollView(
              anchor: 0.4,
              slivers: <Widget>[
                SliverWidget(
                  child: Container(
                    width: double.infinity,
                    height: 100,
                    decoration: BoxDecoration(
                        color: Colors.yellow, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))),
                    child: TabBar(
                      tabs: [FlutterLogo(), FlutterLogo()],
                    ),
                  ),
                ),
                SliverList(
                  delegate: SliverChildListDelegate(_listview(50)),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

List _listview(int count) {
  List<Widget> listItems = List();

  for (int i = 0; i < count; i++) {
    listItems.add(
      Container( //NOTE: workaround to prevent antialiasing according to: https://github.com/flutter/flutter/issues/25009
        decoration: BoxDecoration(
            color: Colors.white, //the color of the main container
            border: Border.all(
                //apply border to only that side where the line is appearing i.e. top | bottom | right | left.
                width: 2.0, //depends on the width of the unintended line
                color: Colors.white)),
        child: Container(
          padding: EdgeInsets.all(20),
          color: Colors.white,
          child: new Text(
            'Item ${i.toString()}',
            style: new TextStyle(fontSize: 25.0),
          ),
        ),
      ),
    );
  }

  return listItems;
}

class SliverWidget extends SingleChildRenderObjectWidget {
  SliverWidget({Widget child, Key key}) : super(child: child, key: key);
  @override
  RenderObject createRenderObject(BuildContext context) {
    // TODO: implement createRenderObject
    return RenderSliverWidget();
  }
}

class RenderSliverWidget extends RenderSliverToBoxAdapter {
  RenderSliverWidget({
    RenderBox child,
  }) : super(child: child);

  @override
  void performResize() {}

  @override
  void performLayout() {
    if (child == null) {
      geometry = SliverGeometry.zero;
      return;
    }
    final SliverConstraints constraints = this.constraints;
    child.layout(constraints.asBoxConstraints(/* crossAxisExtent: double.infinity */), parentUsesSize: true);
    double childExtent;
    switch (constraints.axis) {
      case Axis.horizontal:
        childExtent = child.size.width;
        break;
      case Axis.vertical:
        childExtent = child.size.height;
        break;
    }
    assert(childExtent != null);
    final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
    final double cacheExtent = calculateCacheOffset(constraints, from: 0.0, to: childExtent);

    assert(paintedChildSize.isFinite);
    assert(paintedChildSize >= 0.0);
    geometry = SliverGeometry(
      scrollExtent: childExtent,
      paintExtent: 100,
      paintOrigin: constraints.scrollOffset,
      cacheExtent: cacheExtent,
      maxPaintExtent: childExtent,
      hitTestExtent: paintedChildSize,
    );
    setChildParentData(child, constraints, geometry);
  }
}

【讨论】:

  • 实际上还有更好的答案,因为我的代码会产生错误,因此会降低帧速率。查看@Kherel 的解决方案——非常完美!您还可以在此处阅读有关错误和更好答案的更多信息:stackoverflow.com/questions/63265729/…
【解决方案3】:

为我工作!

     SliverAppBar(
            pinned: true,
            floating: false,
            centerTitle: true,
            title: TextWidget(detail.title,
              weight: FontWeight.bold
            ),
            expandedHeight: MediaQuery.of(context).size.height/2.5,
            flexibleSpace: FlexibleSpaceBar(
              centerTitle: true,
              collapseMode: CollapseMode.parallax,
              background: Stack(
                children: [
                 // Carousel images
                  Swiper(
                      itemWidth: MediaQuery.of(context).size.width,
                      itemHeight: MediaQuery.of(context).size.height /3.5,
                      itemCount: 2,
                      pagination:  SwiperPagination.dots,
                      loop: detail.banners.length > 1,
                      itemBuilder: (BuildContext context, int index) {
                        return Image.network(
                            'https://image.com?image=123.png',
                            fit: BoxFit.cover
                        );
                      }
                  ),
                  //Border radius 
                  Align(
                    alignment: Alignment.bottomCenter,
                    child: Container(
                      color: Colors.transparent,
                      height: 20,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: <Widget>[
                          Container(
                            height: 10,
                            decoration: BoxDecoration(
                              color: Colors.white,
                              borderRadius: BorderRadius.only(
                                topLeft: const Radius.circular(10),
                                topRight: const Radius.circular(10),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  )
                ],
              ),
            ),
          )

【讨论】:

    【解决方案4】:

    这个想法不错,但在某些情况下看起来很奇怪。

    您可以为列表中的第一个元素提供borderRadius

    Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.only(
          topRight: Radius.circular(index == 0 ? 15 : 0),
          topLeft: Radius.circular(index == 0 ? 15 : 0),
        ),
      ),
    )
    

    希望这对某人有所帮助

    【讨论】:

      【解决方案5】:

      试试这个,这是一个简单的解决方案

      import 'package:flutter/material.dart';
      
      class SliveR extends StatelessWidget {
        const SliveR({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            body: Stack(
              children: [
                SizedBox(
                  width: double.infinity,
                  child: Image.network(
                    'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
                    fit: BoxFit.cover,
                    height: MediaQuery.of(context).size.height * 0.35,
                  ),
                ),
                Align(
                  alignment: Alignment.topCenter,
                  child: Container(
                    decoration: const BoxDecoration(
                      borderRadius: BorderRadius.all(Radius.circular(30)),
                    ),
                    child: ClipRRect(
                      borderRadius: const BorderRadius.all(Radius.circular(30)),
                      child: CustomScrollView(
                        anchor: 0.3,
                        slivers: [
                          SliverToBoxAdapter(
                            child: Container(
                              height: 900,
                              decoration: const BoxDecoration(
                                color: Colors.white,
                                borderRadius: BorderRadius.only(
                                  topLeft: Radius.circular(40.0),
                                  topRight: Radius.circular(40.0),
                                ),
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.grey,
                                    offset: Offset(0.0, 1.0), //(x,y)
                                    blurRadius: 16.0,
                                  ),
                                ],
                              ),
                              child: const Center(
                                child: Text(
                                  'Hello',
                                  style: TextStyle(color: Colors.grey),
                                ),
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          );
        }
      }
      

      【讨论】:

      • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多