我的基本窗口小部件是列。第一个元素是一个具有BoxShadow的Container。第二个元素是ListView,它根据上下文构建多个Card。如果滚动条为0,则显示阴影。但是,当开始滚动时,卡片会“遮盖”阴影(较高的z-index)并将其隐藏。
阴影应始终位于卡片上方。怎么做?
答案 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)
编辑
如果您不希望容器阴影在滚动时消失,请删除 ScrollNotification
和 NotificationListener
有一个小部件?
您可以将 ScrollNotification
与 NotificationListener
一起使用。试试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 shadow
。 Shadow
在定义的大小之外呈现。如果您在此 Container
之后不提供任何空格,我们将无法看到阴影。这个空间可以通过 Container margin
、SizedBox
或 wrapping 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
相同的高度。
margin
。Padding
包装我们的列表并提供 top:
。在这张图片中,
我们的shadow: white
,background: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,
)
],
),
);
}
}