【问题标题】:How to disable default Widget splash effect in Flutter?如何在 Flutter 中禁用默认的 Widget 飞溅效果?
【发布时间】:2018-10-05 19:51:15
【问题描述】:

如何禁用 Widget 上的默认飞溅/波纹/墨迹效果?有时效果是不需要的,例如在以下 TextField 情况下:

【问题讨论】:

    标签: widget flutter


    【解决方案1】:

    根据上面@hunter 的建议,我发现通过将我的主题中的highlightColorsplashColor 都设置为Colors.transparent 消除了涟漪。

    我确实担心设置highlightColor 可能会产生一些连锁反应,但我还没有注意到。

    编辑:虽然我最初的答案有很多赞成票,但我学到的越多,我就越意识到这确实不是正确的方法。正如下面几个人所指出的,更好的解决方案是使用splashFactory。例如,下面的代码显示它是直接通过样式设置的,或者您也可以在主题中设置它:

    ElevatedButton(
      onPressed: onPressed,
      style: ElevatedButton.styleFrom(
        splashFactory: NoSplash.splashFactory,
      ),
      child: child,
    );
    

    【讨论】:

    • 这也消除了 InkWell 和 InkResponse 等小部件的涟漪效应
    • highlightColor 设置为透明使得使用Theme.of(context).highlightColor 毫无意义
    【解决方案2】:

    您可以将组件包装到Theme 中,并将splashColorhighlightColor 的属性设置为ThemeData 上的透明

    Theme(
      data: ThemeData(
        splashColor: Colors.transparent,
        highlightColor: Colors.transparent,
      ),
      child: YourWidget(),
    );
    

    【讨论】:

    • 最佳答案在这里,不改变整个应用程序的主题!你甚至可以使用Theme.of(context).copyWith 而不是ThemeData,因为它将保留已经定义的主题数据而不是flutter的默认数据:)
    【解决方案3】:

    您可以将主题的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 上回答。

    【讨论】:

    • 你也可以只定义一个透明的 splashColor;即:ThemeData(splashColor: Colors.transparent)
    • @override 注解应该被移除,因为InteractiveInkFeatureFactory 是最新版本的flutter中的一个抽象类。
    • 现在已经合并到flutter中了!使用splashFactory: NoSplash.splashFactory
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

      使用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'),
      )
      

      【讨论】:

        【解决方案6】:

        我试过上面的答案没有成功(splashColor: Colors.transparent, highlightColor: Colors.transparent,)。

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

        【讨论】:

        • 实际上,为了消除 InkWell 上的每个高光、悬停、飞溅效果,我还必须同时设置 splashColor、highlightColor 和 hoverColor,但它通过设置墨水池本身来起作用,我没有需要使用主题包装器
        【解决方案7】:

        当我正在寻找一种从列表过度滚动中删除斜线的方法时,没有一个与 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 中禁用滚动发光效果”这样的新问题并自己回答可能是个好主意。可能会使搜索该内容的人更容易找到。
        • 是的,我花了一些时间才意识到,然后我在 SO 的其他地方找到了其中的一部分,所以这就是我在这里发布它的原因。如果有人像我一样误解了自己的需求,我的意思是:)
        猜你喜欢
        • 2018-09-03
        • 2018-08-12
        • 2023-01-28
        • 2021-06-27
        • 2020-03-19
        • 2020-05-19
        • 2021-07-18
        • 1970-01-01
        • 2020-10-21
        相关资源
        最近更新 更多