阴影在其他小部件上

时间:2019-09-13 22:52:55

标签: android ios flutter flutter-layout

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

Shadow is visible when not scrolling enter image description here

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

4 个答案:

答案 0 :(得分:3)

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

尽量使用 Stack 而不是 Column,因为 Column 占据了整个屏幕空间。因此它重叠了阴影。 Stack 将帮助您在 Container 上方显示 ListView。也使用 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
        )
     ),
    ),
  ]
)

答案 1 :(得分:1)

编辑

如果您不希望容器阴影在滚动时消失,请删除 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'),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

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` 来完成。它们包含上部空格,这就是为什么我们只能看到第 1 次。

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

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

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

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

enter image description here

演示代码:

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,
          )
        ],
      ),
    );
  }
}