How can I disable the default splash/ripple/ink effect on a Widget? Sometimes the effect is unwanted, such as in the following TextField case:
Per @hunter's suggestion above, I found that by setting both highlightColor
and splashColor
in my theme to Colors.transparent
removed the ripple.
I do hold some concerns that setting highlightColor
might have some knock-on effects, but I haven't noticed any yet.
Edit: While my original answer has loads of up-votes, the more I learn, the more I've realised that it really isn't the right way to do it. As several people have pointed out below, a better solution is to use the splashFactory
. For example, the code below shows it being set directly via the style, or you can set it in your theme too:
ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
splashFactory: NoSplash.splashFactory,
),
child: child,
);
highlightColor
to transparent makes using Theme.of(context).highlightColor
pointless –
Rone TextButton.styleFrom(splashFactory: NoSplash.splashFactory);
I can't see why. –
Galiot You can wrap the component into Theme
and set the properties splashColor
and highlightColor
to transparent on ThemeData
Theme(
data: ThemeData(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
child: YourWidget(),
);
Theme.of(context).copyWith
instead of ThemeData
as it will keep already defined theme data instead of having flutter's default ones :) –
Dragrope Use NoSplash.splashFactory
Set to a theme
final yourTheme = ThemeData.light();
...
Theme(
data: yourTheme.copyWith(
splashFactory: NoSplash.splashFactory,
),
...
)
Set to a material widget
ElevatedButton(
style: ElevatedButton.styleFrom(
splashFactory: NoSplash.splashFactory,
),
onPressed: () { },
child: Text('No Splash'),
)
You can replace the Theme's splashFactory
with one that doesn't paint anything:
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) {}
}
And wrap your widget with it:
child: new Theme(
data: new ThemeData(splashFactory: const NoSplashFactory()),
child: new TextField(...),
),
Originally answered by HansMuller on a GitHub PR.
ThemeData(splashColor: Colors.transparent)
–
Alienism @override
annotation should be removed as InteractiveInkFeatureFactory
is an abstract class in latest version of flutter. –
Mitis splashFactory: NoSplash.splashFactory
–
Hellion I'll modify Camilo's approach just to be sure we don't override other properties of the parent theme.
var color = Colors.transparent;
Theme(
data: Theme.of(context).copyWith(
highlightColor: color,
splashColor: color,
hoverColor: color,
),
child: YourWidget(),
)
I have tried the above answer without success(splashColor: Colors.transparent, highlightColor: Colors.transparent,
).
My solution was to only set hoverColor:Colors.transparent
Set highlightColor
,splashColor
to transparent and splashFactory
to NoSplash as shown below in your material apptheme.
MaterialApp(
theme: ThemeData(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
splashFactory: NoSplash.splashFactory,,
)
)
If a widget has splashColor
and highColor
like IconButton
set it to transparant.
IconButton(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
color: HexColor.fromHex(AppColors.navigationIconColor),
icon: SvgPicture.asset(
Platform.isAndroid
? "assets/back_button_android.svg"
: "assets/back_button.svg",
fit: BoxFit.cover,
),
onPressed: onPress,
);
As I was looking for a way to remove the slash from list overscroll, none of the ThemeData related solutions worked for me. I thought that this question was the same as the one I had, so for any users facing the same misunderstanding, the following solution proved to work, and is pretty neat when put into a stateless widget as you can see below:
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);
}
}
The way to use this is to simply wrap your widget with NoSplash(child: )
Hope someone finds this useful!
I found this question while looking for a solution to disable splash on ElevatedButton
. all solutions presented here did not work for my problem, even though Theme(data: ThemeData(... NoSplash..))
was working but for some reason did not work. I set overlayColor:..
in ButtonStyle()
to transparent like this: overlayColor: MaterialStateProperty.all(Colors.transparent),
and worked. hope this will help someone
for ElevatedButton. (Flutter 2.20+)
class NoSplashState extends MaterialStatesController{
@override
void update(MaterialState state, bool add) {
}
}
ElevatedButton(
statesController: NoSplashState(),
...
)
@override
Widget build(BuildContext context){
// You can use your custom theme like AppTheme.of(context).materialThemeData
final yourTheme = Theme.of(context) ;
return Theme(
data: yourTheme.copyWith(
// removes splash effect
splashFactory: NoSplash.splashFactory,
// removes color when holding the button
highlightColor: Colors.transparent,
),
child: yourChild
);
}
For radio button you can do like this:
Theme(
data: Theme.of(context).copyWith(
radioTheme: const RadioThemeData(splashRadius: 0),
),
child: Radio<T>(
value: e,
groupValue: widget.value,
onChanged: (value) {
widget.onChanged(value);
state.didChange(value);
},
),
),
© 2022 - 2024 — McMap. All rights reserved.