decoration: BoxDecoration(
boxShadow: [
const BoxShadow(
color: your_shadow_color,
),
const BoxShadow(
color: your_bg_color,
spreadRadius: -12.0,
blurRadius: 12.0,
),
],
),
这就是我所做的:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class InnerShadow extends SingleChildRenderObjectWidget {
const InnerShadow({
Key key,
this.blur = 10,
this.color = Colors.black38,
this.offset = const Offset(10, 10),
Widget child,
}) : super(key: key, child: child);
final double blur;
final Color color;
final Offset offset;
@override
RenderObject createRenderObject(BuildContext context) {
final _RenderInnerShadow renderObject = _RenderInnerShadow();
updateRenderObject(context, renderObject);
return renderObject;
}
@override
void updateRenderObject(
BuildContext context, _RenderInnerShadow renderObject) {
renderObject
..color = color
..blur = blur
..dx = offset.dx
..dy = offset.dy;
}
}
class _RenderInnerShadow extends RenderProxyBox {
double blur;
Color color;
double dx;
double dy;
@override
void paint(PaintingContext context, Offset offset) {
if (child == null) return;
final Rect rectOuter = offset & size;
final Rect rectInner = Rect.fromLTWH(
offset.dx,
offset.dy,
size.width - dx,
size.height - dy,
);
final Canvas canvas = context.canvas..saveLayer(rectOuter, Paint());
context.paintChild(child, offset);
final Paint shadowPaint = Paint()
..blendMode = BlendMode.srcATop
..imageFilter = ImageFilter.blur(sigmaX: blur, sigmaY: blur)
..colorFilter = ColorFilter.mode(color, BlendMode.srcOut);
canvas
..saveLayer(rectOuter, shadowPaint)
..saveLayer(rectInner, Paint())
..translate(dx, dy);
context.paintChild(child, offset);
context.canvas..restore()..restore()..restore();
}
}
然后在某个地方使用它:
InnerShadow(
blur: 5,
color: const Color(0xFF477C70),
offset: const Offset(5, 5),
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8)),
color: Color(0xFFE9EFEC),
),
height: 100,
),
)
结果:
我已经接受了@AlexandrPriezzhev的答案,并将其改进为使用标准
Shadow
类(包括其 offset
字段的语义),添加了对多个阴影的支持,并删除了 saveLayer()
调用,该调用应该使它更有效率一点:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class InnerShadow extends SingleChildRenderObjectWidget {
const InnerShadow({
Key? key,
this.shadows = const <Shadow>[],
Widget? child,
}) : super(key: key, child: child);
final List<Shadow> shadows;
@override
RenderObject createRenderObject(BuildContext context) {
final renderObject = _RenderInnerShadow();
updateRenderObject(context, renderObject);
return renderObject;
}
@override
void updateRenderObject(
BuildContext context, _RenderInnerShadow renderObject) {
renderObject.shadows = shadows;
}
}
class _RenderInnerShadow extends RenderProxyBox {
late List<Shadow> shadows;
@override
void paint(PaintingContext context, Offset offset) {
if (child == null) return;
final bounds = offset & size;
context.canvas.saveLayer(bounds, Paint());
context.paintChild(child!, offset);
for (final shadow in shadows) {
final shadowRect = bounds.inflate(shadow.blurSigma);
final shadowPaint = Paint()
..blendMode = BlendMode.srcATop
..colorFilter = ColorFilter.mode(shadow.color, BlendMode.srcOut)
..imageFilter = ImageFilter.blur(
sigmaX: shadow.blurSigma, sigmaY: shadow.blurSigma);
context.canvas
..saveLayer(shadowRect, shadowPaint)
..translate(shadow.offset.dx, shadow.offset.dy);
context.paintChild(child!, offset);
context.canvas.restore();
}
context.canvas.restore();
}
}
詹姆斯的答案在外部产生了一个阴影,使形状扭曲。穆罕默德的答案是渐变而不是正确的阴影,但亚历山大的解决方案非常适合我,只需一个小修复! rectInner 必须更新。
final Rect rectInner = Rect.fromLTWH(
offset.dx,
offset.dy,
size.width,
size.height,
);
您可以使用多个 BoxShadow 来完成此操作,其中第一个(下面)较暗,顶部较亮,并在其顶部加上灰色边框以使容器弹出。
代码:
Container(
width: 100,
height: 100,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.fromBorderSide(
BorderSide(color: Colors.black12),
),
shape: BoxShape.circle,
boxShadow: [
BoxShadow(color: Colors.black, blurRadius: 1, spreadRadius: 0),
BoxShadow(color: Colors.white, blurRadius: 10, spreadRadius: 5),
]),
child: Icon(Icons.pause, size: 70, color: Colors.black54),
),
结果:
或者,您可以通过使用普通的盒子阴影和两个容器来解决此问题 - 外部容器充当背景,内部容器提供阴影。
代码:
Container(
padding: EdgeInsets.only(top: 30, left: 10, right: 10),
child: Container(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(12))),
padding: EdgeInsets.all(10),
child: Container(
padding: EdgeInsets.zero,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(8)),
boxShadow: [
BoxShadow(
color: Colors.white,
blurRadius: 10,
spreadRadius: 10)
]),
width: double.infinity,
height: 272,
child: Center(
child: Text("Content goes here"),
),
)))),
詹姆斯的回答对我来说没有效果。
所以我只是通过在容器/图像上方放置一个内部Gradient层来实现它,因此,我有了我想要的内部阴影(仅从我的情况的底部)。
Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage('images/bg.jpg') /*NetworkImage(imageUrl)*/,
),
),
height: 350.0,
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomCenter,
colors: [
Colors.grey.withOpacity(0.0),
Colors.black54,
],
stops: [0.95, 1.0],
),
),
)
],
)
如果您对只使用一个软件包感到满意,我发现这个软件包效果很好。
找到这个包:https://pub.dev/packages/inner_shadow_widget
非常适合我:
InnerShadow(
blur: 3,
offset: const Offset(2, 2),
child: Image.asset('path'),
),
无内阴影
有内阴影
更新:https://pub.dev/packages/flutter_inner_shadow
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 100,
width: 100,
child: InnerShadow(
shadows: [
Shadow(
color: Colors.black.withOpacity(0.25),
blurRadius: 10,
offset: Offset(2, 5))
],
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.red,
),
),
),
),
),
);
}