Adam Griffiths
Adam Griffiths

Reputation: 782

Control on tap ripple effect on Flutter ElevatedButton

Question

How can I change the duration and colour of the on tap ripple effect on an ElevatedButton? See the dart pad link for a working example of this ripple effect.

Code for working ElevatedButton

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: MyStatelessWidget(),
      ),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () {},
        child: const Text('Elevated Button', style: TextStyle(fontSize: 20)),
      ),
    );
  }
}

DartPad Link

https://dartpad.dev/369b01f31b06c18d4f47076319aa4da4

Upvotes: 23

Views: 22487

Answers (3)

Heshan Sandeepa
Heshan Sandeepa

Reputation: 3687

With Flutter 2.0, try this

ElevatedButton(
    style: ButtonStyle(
      overlayColor: MaterialStateProperty.all<Color>(Colors.black12)),
    onPressed: () {},
    child: Text('Ripple'))

Upvotes: 7

Mohamed Slama
Mohamed Slama

Reputation: 197

You can use animationDuration for duration and onPrimary to change splash color.

return ElevatedButton(
      onPressed: action,
      child:
          Text(text, style: Theme.of(context).textTheme.subtitle1),
      style: ElevatedButton.styleFrom(
        onPrimary: Colors.black,
        animationDuration: Duration(milliseconds: 1000),
        primary: Colors.red,
        shadowColor: Colors.redAccent,
        elevation: 10,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(15),
        ),
      ),
    );

Upvotes: 0

Wilson Wilson
Wilson Wilson

Reputation: 3757

It's pretty simple. Just make sure you return your desired overlay color when the current MaterialState is pressed.

    Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {},
            style: ButtonStyle(
              overlayColor: MaterialStateProperty.resolveWith(
                (states) {
                  return states.contains(MaterialState.pressed)
                      ? Colors.red
                      : null;
                },
              ),
            ),
            child: const Text(
              'Elevated Button',
              style: TextStyle(fontSize: 20),
            ),
          ),
        ),
      ),

Better still, you can use this as your buttonStyle:

ElevatedButton.styleFrom(
    onPrimary: Colors.yellow,
 ),

The only problem with this is that it affects your foreground color, but that's not too bad.

So your button with a custom splash should look like this:

      ElevatedButton(
            onPressed: () {},
            style: ElevatedButton.styleFrom(
              onPrimary: Colors.yellow,
            ),
            child: const Text(
              'Elevated Button',
              style: TextStyle(fontSize: 20, color: Colors.white),
            ),
          ),

Changing the duration of the splash, however, is NOT possible, because, from the source code, the button's splash factory is hardcoded, and not open for modification.

...
splashFactory: InkRipple.splashFactory,

And as this answer shows, you need to modify the splash factory to change the duration.

If you really need that functionality, the quickest way to get that done would be to copy the code from the source and re-implement it yourself. But I wouldn't recommend that.

The more appropriate way you could do this would be to create your own custom button using a Material and an InkWell, but that wouldn't be an elevated button

Upvotes: 40

Related Questions