【问题标题】:Flutter shadow over other widgets在其他小部件上颤动阴影
【发布时间】:2020-01-15 18:34:43
【问题描述】:

我的基本小部件是一个列。第一个元素是具有 BoxShadow 的 Container。第二个元素是一个 ListView,它根据上下文构建多个 Card。如果滚动为 0,则显示阴影。然而,当开始滚动时,卡片会“越过”阴影(较高的 z-index)并隐藏它。

未滚动

滚动

阴影应始终位于卡片上方。这是怎么做到的?

【问题讨论】:

  • 你能分享一些代码吗?以及一些预期的用户界面?屏幕截图看起来很白,无法从细节中理解很多。对不起朋友!

标签: android ios flutter flutter-layout


【解决方案1】:

代码对解决这个问题很有帮助。但我知道您面临什么问题以及如何解决。

尝试使用Stack 而不是Column,因为Column 占据了整个屏幕空间。因此它与阴影重叠。 Stack 将帮助您在您的ListView 上方显示Container。也使用Positioned。您的ListView 需要从顶部ListItem 偏移,否则它将被Container 覆盖并且无法再触摸。

Stack(
  children: <Widget>[
    Padding(
      //padding
      child: //Listview (can also be wrapped in "Positioned")
    ),
    Positioned(
      top: 0.0, //Container at the top, ListView needs an additional offset from top, otherwise it will be covered by Container
      left: 0.0,
      right: 0.0,
      child: Container(
        decoration: BoxDecoration(
          color: //put some color
          boxShadow: [
            BoxShadow(
              color: //put some color
              offset: Offset(0, 10), //offset
              // also can do some blur etc.
          )]
        ),
        child: ListTile(
          title: //choose your title
        )
     ),
    ),
  ]
)

【讨论】:

    【解决方案2】:

    编辑

    如果您不希望容器阴影在滚动时消失,请删除 ScrollNotificationNotificationListener

    有一个小部件 ?

    您可以将ScrollNotificationNotificationListener 一起使用。试试this;

    编码愉快! ?

    class TestPage extends StatefulWidget {
      const TestPage({Key key}) : super(key: key);
    
      @override
      _TestPageState createState() => _TestPageState();
    }
    
    class _TestPageState extends State<TestPage> {
      double blurRadius = 10.0;
      double spreadRadius = 1.0;
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.blueGrey,
            title: Text('Title'),
          ),
          body: Container(
            width: Get.width,
            height: Get.height,
            child: Stack(
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0).copyWith(
                    top: 62.0,
                  ),
                  child: NotificationListener<ScrollNotification>(
                    // ignore: missing_return
                    onNotification: (scrollNotification) {
                      if (scrollNotification is ScrollStartNotification) {
                        setState(() {
                          blurRadius = 0.0;
                          spreadRadius = 0.0;
                        });
                      } else if (scrollNotification is ScrollEndNotification) {
                        setState(() {
                          blurRadius = 10.0;
                          spreadRadius = 1.0;
                        });
                      }
                    },
                    child: ListView.builder(
                      // controller: _controller,
                      itemCount: 10,
                      itemBuilder: (context, index) {
                        return Card(
                          child: Container(
                              width: Get.width * .8,
                              height: 100.0,
                              child: Center(
                                child: Text('child @ index : $index'),
                              )),
                        );
                      },
                    ),
                  ),
                ),
                Positioned(
                  top: 0,
                  left: 0,
                  right: 0,
                  child: Container(
                    width: Get.width,
                    height: 60.0,
                    margin: EdgeInsets.only(),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.only(
                        bottomLeft: Radius.circular(20.0),
                        bottomRight: Radius.circular(20.0),
                      ),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey,
                          blurRadius: blurRadius,
                          spreadRadius: spreadRadius,
                        ),
                      ],
                    ),
                    child: Center(
                      child: Text('TOP CONTAINER'),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案3】:

      根据您的问题,这是这里出了什么问题的概念。

      Column 的第一个孩子是 Container with shadowShadow 呈现超出定义的大小。如果您在此Container 之后不提供任何空格,我们将无法看到阴影。这个空间可以通过Container marginSizedBoxwrapping our list with Padding. But now our main question is how we get shadow while index=0. I believe it is coming from ListChildren`来完成。它们包含上部空格,这就是为什么我们只能看到第一次。

      在 Ui 上渲染优先级从底部到顶部。

      如何解决这个问题: 我们可以在容器底部提供空间或分配margin(不是填充),或者在container 之后使用SizedBox,提供与shadow 相同的高度。

      1. 在容器上提供底部margin
      2. 添加具有阴影高度的 SizedBox。
      3. Padding 包装我们的列表并提供top:

      在这张图片中, 我们的shadow: whitebackground:amber

      演示代码:

      import 'package:flutter/material.dart';
      
      class ColumnWithContainerShadow extends StatelessWidget {
        const ColumnWithContainerShadow({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            backgroundColor: Colors.amber,
            body: Column(
              children: [
                Container(
                  height: 50,
                  width: double.infinity,
                  ////* we dont need margin if we have padding on ListView
                  // margin: EdgeInsets.only(bottom: 12),
                  decoration: BoxDecoration(
                    color: Colors.green,
                    boxShadow: [
                      BoxShadow(
                        offset: Offset(0, 12),
                        color: Colors.white,
                      )
                    ],
                  ),
                  child: Center(child: Text("Container A")),
                ),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.only(top: 12),
                    child: ListView(
                      children: [
                        ...List.generate(
                          333,
                          (index) => Container(
                            /// enable this margine and remove other spaces to see 1st child shadow.(shadow depend on children position)
                            // margin: EdgeInsets.only(top: 12),
                            height: 60,
                            color: Colors.deepPurple,
                            child: Text("$index"),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
                Container(
                  height: 50,
                  width: double.infinity,
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    color: Colors.green,
                    boxShadow: [
                      BoxShadow(
                        offset: Offset(0, 12),
                        color: Colors.white,
                      )
                    ],
                  ),
                  child: Text("Bottom Container"),
                ),
                // Comment to close shadow
                SizedBox(
                  height: 20,
                )
              ],
            ),
          );
        }
      }
      
      

      【讨论】:

        【解决方案4】:

        将上面的框包裹在Material 小部件中并提供一个高度。

        【讨论】:

        猜你喜欢
        • 2019-02-13
        • 2020-06-24
        • 2021-09-28
        • 2019-11-06
        • 2020-11-21
        • 2022-01-27
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        相关资源
        最近更新 更多