Posts: 0
Threads: 0
Joined: Jan 2017
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
According to the [github issue]( [To see links please register here] ) there is no inset attribute in ShadowBox yet. Is there any workaround how to emulate inner shadow right now in flutter.
I like to achieve inner shadow effects like you can see on the following images
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[1]:
[2]:
|
Posts: 0
Threads: 0
Joined: Feb 2017
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
james's answer did not do the trick for me.
So I simply made it out by placing an inner **Gradient** layer above my container/image, thus, I had the kind of inner shadow I wanted (only from the bottom in my case).
```dart
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],
),
),
)
],
)
```
|
Posts: 0
Threads: 0
Joined: Oct 2016
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
Here is what I do:
```dart
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();
}
}
```
then just use it somewhere:
```dart
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,
),
)
```
The result:
![result]( )
|
Posts: 0
Threads: 0
Joined: Nov 2022
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
James's answer creates a shadow outside which warps the shape. Mohammed's answer is a gradient and not proper shadow but Alexandr's solution works perfectly for me with a small fix! rectInner has to be updated.
final Rect rectInner = Rect.fromLTWH(
offset.dx,
offset.dy,
size.width,
size.height,
);
|
Posts: 0
Threads: 0
Joined: Apr 2018
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
decoration: BoxDecoration(
boxShadow: [
const BoxShadow(
color: your_shadow_color,
),
const BoxShadow(
color: your_bg_color,
spreadRadius: -12.0,
blurRadius: 12.0,
),
],
),
|
Posts: 0
Threads: 0
Joined: Sep 2021
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
I've taken the answer by @AlexandrPriezzhev and improved it to use the standard `Shadow` class (including the semantics of its `offset` field), added support for multiple shadows, and shaved off a `saveLayer()` call which should make it a bit more efficient:
```dart
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();
}
}
```
|
Posts: 0
Threads: 0
Joined: Jan 2021
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
You can use do it using multiple BoxShadow, where the first one (below) is darker, and a lighter one on top, and top it off with the a border with greyish color to make the container pops.
Code:
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),
),
result:
![]( )
|
Posts: 0
Threads: 0
Joined: Aug 2018
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
If you are comfortable with just using a package I found this one works quite well.
[To see links please register here]
|
Posts: 0
Threads: 0
Joined: Mar 2023
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
Found this package: [To see links please register here]
Works perfect for me:
```
InnerShadow(
blur: 3,
offset: const Offset(2, 2),
child: Image.asset('path'),
),
```
without inner shadow
[![enter image description here][1]][1]
with inner shadow
[![enter image description here][2]][2]
[1]:
[2]:
|
Posts: 0
Threads: 0
Joined: Oct 2017
Reputation:
0
Level: inf []
Total Points: inf
Rank nan / 1
100% to upload Level
Activity inf / 1
99% to upload your Rank
Experience nan
100% to upload Experience
Points: 50
|
Alternatively, you can solve this problem by using normal box shadow and two containers - the outer one acting as a background and inner one providing the shadow.
Code:
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"),
),
)))),
Produces:
[![Screen shot][1]][1]
[1]:
|
|