如何在Flutter中禁用默认小部件的闪烁效果?

67

如何在小部件上禁用默认的溅泼/波纹/墨水效果?有时候这个效果是不需要的,比如下面的TextField案例:

12个回答

142
根据@hunter上面的建议,我发现通过将我的主题中的highlightColorsplashColor都设置为Colors.transparent可以去除涟漪效果。
我确实担心设置highlightColor可能会有一些连锁反应,但我还没有注意到任何影响。
编辑:虽然我的原始答案得到了很多赞,但我学到的越多,就越意识到这并不是正确的方法。正如下面几个人指出的那样,更好的解决方案是使用splashFactory。例如,下面的代码显示直接通过样式设置它,或者您也可以在主题中设置它:
ElevatedButton(
  onPressed: onPressed,
  style: ElevatedButton.styleFrom(
    splashFactory: NoSplash.splashFactory,
  ),
  child: child,
);

1
这也会从像InkWell和InkResponse这样的小部件中移除涟漪效果。 - Oleg Khalidov
1
highlightColor设置为透明会使得使用Theme.of(context).highlightColor毫无意义。 - Andrey Gordeev
TextButton无法工作。TextButton.styleFrom(splashFactory: NoSplash.splashFactory); 我不知道为什么。 - undefined

77
您可以将组件包装在 Theme 中,并在 ThemeData 上将属性 splashColorhighlightColor 设置为透明。
Theme(
  data: ThemeData(
    splashColor: Colors.transparent,
    highlightColor: Colors.transparent,
  ),
  child: YourWidget(),
);

4
最佳答案在这里,不改变整个应用程序的主题!您甚至可以使用 Theme.of(context).copyWith 而不是 ThemeData,因为它将保留已定义的主题数据,而不是使用 Flutter 的默认数据 :) - Hugo H

27

使用NoSplash.splashFactory

设置为主题

final yourTheme = ThemeData.light();
...
Theme(
  data: yourTheme.copyWith(
    splashFactory: NoSplash.splashFactory,
  ),
  ...
)

设置为材料小部件

ElevatedButton(
  style: ElevatedButton.styleFrom(
    splashFactory: NoSplash.splashFactory,
  ),
  onPressed: () { },
  child: Text('No Splash'),
)

22
你可以用不绘制任何内容的 splashFactory 替换主题的原始 splashFactory
class NoSplashFactory extends InteractiveInkFeatureFactory {
  const NoSplashFactory();

  @override
  InteractiveInkFeature create({
    MaterialInkController controller,
    RenderBox referenceBox,
    Offset position,
    Color color,
    TextDirection textDirection,
    bool containedInkWell = false,
    Rect Function() rectCallback,
    BorderRadius borderRadius,
    ShapeBorder customBorder,
    double radius,
    VoidCallback onRemoved,
  }) {
    return NoSplash(
      controller: controller,
      referenceBox: referenceBox,
    );
  }
}

class NoSplash extends InteractiveInkFeature {
  NoSplash({
    @required MaterialInkController controller,
    @required RenderBox referenceBox,
  })  : assert(controller != null),
        assert(referenceBox != null),
        super(
          controller: controller,
          referenceBox: referenceBox,
        );

  @override
  void paintFeature(Canvas canvas, Matrix4 transform) {}
}

将您的小部件用它包装起来:

child: new Theme(
  data: new ThemeData(splashFactory: const NoSplashFactory()),
  child: new TextField(...),
),

最初由HansMuller在GitHub PR上回答。


8
你可以定义一个透明的splashColor,例如:ThemeData(splashColor: Colors.transparent) - hunter
1
在最新版本的Flutter中,InteractiveInkFeatureFactory是一个抽象类,因此应该删除@override注释。 - Evan
3
现在它已经合并到Flutter中了!使用 splashFactory: NoSplash.splashFactory - Pavel

15

我会修改Camilo的方法,以确保我们不会覆盖父主题的其他属性。

var color = Colors.transparent;
Theme(
  data: Theme.of(context).copyWith(
    highlightColor: color,
    splashColor: color,
    hoverColor: color,
  ),
  child: YourWidget(),
)

7

我尝试了上述回答,但没有成功(splashColor: Colors.transparent, highlightColor: Colors.transparent,)。

我的解决方案是只设置hoverColor:Colors.transparent


1
实际上,为了消除InkWell上的每个高亮、悬停、溅泼效果,我不得不同时设置splashColor、highlightColor和hoverColor,但是通过在InkWell本身上设置,它可以正常工作,我不需要使用Theme包装器。 - Daniel Leiszen

5

在您的Material AppTheme中,如下所示,将highlightColorsplashColor设置为透明,并将splashFactory设置为NoSplash

MaterialApp(
   theme: ThemeData(
      highlightColor: Colors.transparent,
      splashColor: Colors.transparent,
      splashFactory: NoSplash.splashFactory,,
    )
 )

2

在寻找解决ElevatedButton闪屏问题的方法时,我发现了这个问题。尽管这里提出的所有解决方案都无法解决我的问题,但Theme(data: ThemeData(... NoSplash..))却可以工作,但由于某些原因它没有起作用。我在ButtonStyle()中将overlayColor:..设置为透明,如下所示:overlayColor: MaterialStateProperty.all(Colors.transparent),并且它起作用了。希望这能帮助到某些人。


2

当我在寻找一种方法来移除列表overscroll中的斜杠时,与ThemeData相关的解决方案都不适用于我。我认为这个问题和我遇到的问题是一样的,因此对于任何面临同样误解的用户,以下解决方案被证明是有效的,并且当放入无状态小部件中时非常整洁,如下所示:

class NoSplash extends StatelessWidget {
  NoSplash({this.child});

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return NotificationListener<OverscrollIndicatorNotification>(
        onNotification: (OverscrollIndicatorNotification overscroll) {
          overscroll.disallowGlow();
          return true;
        },
        child: child);
  }
}

使用方法很简单,只需将您的小部件包装在 NoSplash(child: ) 中即可。
希望有人会觉得这很有用!

看起来很整洁。虽然这个问题通常与点击效果有关,但我觉得如果你提出一个新问题,比如“如何在Flutter中禁用滚动发光效果”,并自己回答,可能会是个好主意。这样做可能会更容易为那些寻找答案的人找到。 - xip
1
是的,我花了一些时间才意识到,后来我在 Stack Overflow 上找到了一部分,所以这就是为什么我在这里发布它。以防有人像我一样误解了自己的需求 :) - Rami Awar

1

用于ElevatedButton。(Flutter 2.20+)

class NoSplashState extends MaterialStatesController{
  @override
  void update(MaterialState state, bool add) {
  }
}


ElevatedButton(
   statesController: NoSplashState(),
   ...
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接