在其他小部件上颤动阴影
Posted
技术标签:
【中文标题】在其他小部件上颤动阴影【英文标题】:Flutter shadow over other widgets 【发布时间】:2020-01-15 18:34:43 【问题描述】:我的基本小部件是一个列。第一个元素是具有 BoxShadow 的 Container。第二个元素是一个 ListView,它根据上下文构建多个 Card。如果滚动为 0,则显示阴影。然而,当开始滚动时,卡片会“越过”阴影(较高的 z-index)并隐藏它。
未滚动
滚动
阴影应始终位于卡片上方。这是怎么做到的?
【问题讨论】:
你能分享一些代码吗?以及一些预期的用户界面?屏幕截图看起来很白,无法从细节中理解很多。对不起朋友! 【参考方案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】:编辑
如果您不希望容器阴影在滚动时消失,请删除 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'),
),
),
),
],
),
),
);
【讨论】:
【参考方案3】:根据您的问题,这是这里出了什么问题的概念。
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`来完成。它们包含上部空格,这就是为什么我们只能看到第一次。
在 Ui 上渲染优先级从底部到顶部。
如何解决这个问题:
我们可以在容器底部提供空间或分配margin
(不是填充),或者在container
之后使用SizedBox
,提供与shadow
相同的高度。
-
在容器上提供底部
margin
。
添加具有阴影高度的 SizedBox。
用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,
)
],
),
);
【讨论】:
【参考方案4】:将上面的框包裹在Material
小部件中并提供一个高度。
【讨论】:
高程实际上不是 z-index material.io/design/environment/elevation.html 高程与 z-index 无关。它被称为高程,但只提供阴影以上是关于在其他小部件上颤动阴影的主要内容,如果未能解决你的问题,请参考以下文章