如何将阴影框扩展到容器之外
How to expand a shadow box beyond the container
我正在创建一个带有投射阴影的卡片的水平卷轴。
我不明白为什么如果我有 3 张卡片阴影会被“剪裁”,但如果我有 2 张卡片则不会。
它应该是这样的:
这是当我有 3 个或更多元素时的样子(我怀疑元素比适合屏幕的元素多)。
如何避免这种行为?
我在 SingleChildScrollView 中有一个列。在该列中,有带有卡片行的 SingleChildScrollViews。
这是脚手架里面的代码:
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SectionTitlePadded("Dependency"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Location), buttonText: "Location", explanation: "A specific location is required", image: Image.asset("assets/images/location.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Collaborator), buttonText: "Collaborator", explanation: "Somebody else is required", image: Image.asset("assets/images/friends.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.TaskDependency), buttonText: "Task", explanation: "Another task must be completed", image: Image.asset("assets/images/list.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SectionTitlePadded("Time"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.LackOfTime), buttonText: "Not enough", explanation: "There is not enough time right now", image: Image.asset("assets/images/hourglass.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Schedule), buttonText: "Not now", explanation: "Right now is not the proper time", image: Image.asset("assets/images/schedule.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SectionTitlePadded("Task Properties"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Priority), buttonText: "Priority", explanation: "The task is not as high a priority", image: Image.asset("assets/images/bring.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Delete), buttonText: "Delete", explanation: "This task is no longer required", image: Image.asset("assets/images/delete.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SizedBox(
height: CustomTheme.standardSeparation,
),
Align(
alignment: Alignment.center,
child: TextButton(
onPressed: () {},
child: const Text("Other"),
),
),
const SizedBox(
height: CustomTheme.standardSeparation * 2,
),
],
),
)
这是卡片的代码(发出阴影的东西):
class CardCustom extends StatelessWidget {
Widget? child;
EdgeInsetsGeometry? innerPadding;
EdgeInsetsGeometry? outerPadding;
CardCustom({Key? key, this.child, this.innerPadding, this.outerPadding}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: outerPadding ?? EdgeInsets.fromLTRB(CustomTheme.standardHorizontalPadding.left, 0, CustomTheme.standardHorizontalPadding.right, CustomTheme.standardSeparation),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: CustomTheme.borderRadius,
boxShadow: [BoxShadow(
color: const Color(0xFF887AA6).withAlpha(25),
spreadRadius: 0,
blurRadius: 40,
offset: const Offset(0, 4),
)],
),
child: Padding(
padding: innerPadding ?? EdgeInsets.fromLTRB(CustomTheme.standardHorizontalPadding.left, CustomTheme.standardSeparation, CustomTheme.standardHorizontalPadding.right, CustomTheme.standardSeparation),
child: child,
),
),
);
}
}
发生这种情况是因为对于 2 个元素,SingleChildScrollView 被视为一行,因为不需要滚动。仅当将第 3 个元素添加到列表使其溢出时,该小部件才可滚动。
解决方法之一是在 SingleChildScrollView 的填充参数中添加 EdgeInsets.symmetric(vertical: value)。
另一种解决方法是删除 Outer Padding Widget 并在 CardCustom 的 Container 的边距参数中添加 EdgeInsets.symmetric(vertical: value)。
我最终使用 clipBehavior: Clip.none
从这个 post 解决了它:How to fix cropped shadow in a Horizontal List View in Flutter
我正在创建一个带有投射阴影的卡片的水平卷轴。
我不明白为什么如果我有 3 张卡片阴影会被“剪裁”,但如果我有 2 张卡片则不会。
它应该是这样的:
这是当我有 3 个或更多元素时的样子(我怀疑元素比适合屏幕的元素多)。
如何避免这种行为?
我在 SingleChildScrollView 中有一个列。在该列中,有带有卡片行的 SingleChildScrollViews。
这是脚手架里面的代码:
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SectionTitlePadded("Dependency"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Location), buttonText: "Location", explanation: "A specific location is required", image: Image.asset("assets/images/location.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Collaborator), buttonText: "Collaborator", explanation: "Somebody else is required", image: Image.asset("assets/images/friends.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.TaskDependency), buttonText: "Task", explanation: "Another task must be completed", image: Image.asset("assets/images/list.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SectionTitlePadded("Time"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.LackOfTime), buttonText: "Not enough", explanation: "There is not enough time right now", image: Image.asset("assets/images/hourglass.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Schedule), buttonText: "Not now", explanation: "Right now is not the proper time", image: Image.asset("assets/images/schedule.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SectionTitlePadded("Task Properties"),
SingleChildScrollView(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Row(children: [
SizedBox(width: CustomTheme.standardHorizontalPadding.left * 0.7),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Priority), buttonText: "Priority", explanation: "The task is not as high a priority", image: Image.asset("assets/images/bring.png")),
TaskRejectionReasonCard(onButtonPressed: () => rejectWithReason(Reason.Delete), buttonText: "Delete", explanation: "This task is no longer required", image: Image.asset("assets/images/delete.png")),
SizedBox(width: CustomTheme.standardHorizontalPadding.right * 0.7),
]),
),
const SizedBox(
height: CustomTheme.standardSeparation,
),
Align(
alignment: Alignment.center,
child: TextButton(
onPressed: () {},
child: const Text("Other"),
),
),
const SizedBox(
height: CustomTheme.standardSeparation * 2,
),
],
),
)
这是卡片的代码(发出阴影的东西):
class CardCustom extends StatelessWidget {
Widget? child;
EdgeInsetsGeometry? innerPadding;
EdgeInsetsGeometry? outerPadding;
CardCustom({Key? key, this.child, this.innerPadding, this.outerPadding}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: outerPadding ?? EdgeInsets.fromLTRB(CustomTheme.standardHorizontalPadding.left, 0, CustomTheme.standardHorizontalPadding.right, CustomTheme.standardSeparation),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: CustomTheme.borderRadius,
boxShadow: [BoxShadow(
color: const Color(0xFF887AA6).withAlpha(25),
spreadRadius: 0,
blurRadius: 40,
offset: const Offset(0, 4),
)],
),
child: Padding(
padding: innerPadding ?? EdgeInsets.fromLTRB(CustomTheme.standardHorizontalPadding.left, CustomTheme.standardSeparation, CustomTheme.standardHorizontalPadding.right, CustomTheme.standardSeparation),
child: child,
),
),
);
}
}
发生这种情况是因为对于 2 个元素,SingleChildScrollView 被视为一行,因为不需要滚动。仅当将第 3 个元素添加到列表使其溢出时,该小部件才可滚动。
解决方法之一是在 SingleChildScrollView 的填充参数中添加 EdgeInsets.symmetric(vertical: value)。
另一种解决方法是删除 Outer Padding Widget 并在 CardCustom 的 Container 的边距参数中添加 EdgeInsets.symmetric(vertical: value)。
我最终使用 clipBehavior: Clip.none
从这个 post 解决了它:How to fix cropped shadow in a Horizontal List View in Flutter