首页 > 解决方案 > ShaderMask LinearGradient 停止奇怪的行为

问题描述

我想淡化内容的两侧(边缘)。

我使用 aShaderMask和 a LinearGradient,它工作得很好,除了我不明白为什么我stops没有正确居中,我使用stops: [0.0, 0.05, 0.95, 1.0]它应该0.05在每一侧褪色,但我得到以下(我添加了一个Container具有相同配置的渐变比较):

Container vs ShaderMask 停止

使用调试绘画模式:

Container vs ShaderMask 停止并启用调试绘制

Container我对和使用完全相同的停靠点,ShaderMask但得到不同的结果。

当然,我可以尝试不同stops的渐变值,ShaderMask直到它居中,但这似乎是一个 hack。

有人可以解释一下吗?

如果有人想尝试一下,这是代码:

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,
              )
            ],
          ),
        ),
      )
    ],
  ),
);

我使用FractionalOffset代替Alignment.centerRightand得到了相同的结果Alignment.centerRight

标签: flutterdartflutter-layout

解决方案


shaderCallbackShader为给定的创建一个Rect,并且Rect坐标相对于给定的原点

着色器回调以子项的当前大小调用,以便它可以将着色器自定义为子项的大小和位置

这意味着我们必须根据没有偏移的子部件的大小来创建着色器Rect(基本上传递给的边界shaderCallback在全局坐标中,同时createShader等待一个局部的Rect)。

所以一个简单的解决方案是创建一个Rect具有正确原点(偏移量)和边界的新的:createShader(Rect.fromLTRB(0, 0, bounds.width, bounds.height))

或者更性感的速记: 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);
},

归功于 pskink !


推荐阅读