问题
I want to fade both side (edges) of a content.
I use a ShaderMask
along with a LinearGradient
, it works great except that I don't understand why my stops
are not centered correctly, I use stops: [0.0, 0.05, 0.95, 1.0]
so that it should be faded 0.05
on each side, but I get the following (I added a Container
gradient with same configuration for comparison):
With debug paint mode :
I use exactly the same stops for the Container
and for the ShaderMask
but get different results.
Of course I can try different stops
values for the ShaderMask
gradient until I got it centered but it seems like a hack.
Someone can explain ?
Here's the code if anyone want to give it a try :
return Container(
height: 200,
child: Column(
children: <Widget>[
Expanded(
child: ShaderMask(
blendMode: BlendMode.modulate,
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: <Color>[Colors.transparent, Colors.white, Colors.white, Colors.transparent],
stops: [0.0, 0.05, 0.95, 1.0],
tileMode: TileMode.clamp,
).createShader(bounds);
},
child: Container(
color: Colors.blue,
child: ListView(
children: <Widget>[
Text(
"I'm a ShaderMask and I don't understand why my gradient don't behave like container's gradient. I'm a ShaderMask and I don't understand why my gradient don't behave like container's gradient.",
textAlign: TextAlign.justify,
)
],
),
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Colors.transparent, Colors.blue, Colors.blue, Colors.transparent],
stops: [0.0, 0.05, 0.95, 1.0],
tileMode: TileMode.clamp,
),
),
child: ListView(
children: <Widget>[
Text(
"I'm a Container and I don't understand why ShaderMask's gradient don't behave like mine. I'm a Container and I don't understand why ShaderMask's gradient don't behave like mine.",
textAlign: TextAlign.justify,
)
],
),
),
)
],
),
);
I got the same result using FractionalOffset
instead of Alignment.centerRight
and Alignment.centerRight
.
回答1:
shaderCallback
creates a Shader
for a given Rect
, and the Rect
coordinates are relative to a given origin.
The shader callback is called with the current size of the child so that it can customize the shader to the size and location of the child.
It means we have to create the shader with a Rect
based on the size of the child widget with no offset (basically the bounds passed to shaderCallback
are in global coordinates while createShader
is waiting for a local Rect
).
So a simple solution is to create a new Rect
with the right origin (offset) and bounds : createShader(Rect.fromLTRB(0, 0, bounds.width, bounds.height))
.
Or a more sexy shorthand : createShader(Offset.zero & bounds.size)
:
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: <Color>[Colors.transparent, Colors.blue, Colors.blue, Colors.transparent],
stops: [0.0, 0.04, 0.96, 1.0],
tileMode: TileMode.clamp,
).createShader(Offset.zero & bounds.size);
},
Credits to pskink !
来源:https://stackoverflow.com/questions/59705860/shadermask-lineargradients-stops-strange-behavior