U Avalos
U Avalos

Reputation: 6798

Why Flutter IconButton Animation Shows Under the Row

In my app, I setup a IconButton to render over a Row with a color background. Unfortunately, the ripple animation on button press renders under the Row (as shown in the screencast). How do i make the ripple show over the Row?

class Card extends StatelessWidget {
final Issue issue;
Color _bgColor;

Card({this.issue}) {
  _bgColor = colorSwatch[issue.hashCode % colorSwatch.length];
}

@override
Widget build(BuildContext context) {
  return Container(
    margin: EdgeInsets.only(top: 12, left: 18, right: 18),
    padding: EdgeInsets.only(top: 8, bottom: 8),
    decoration: new BoxDecoration(
      color: _bgColor,
      border: new Border.all(color: _bgColor),
      borderRadius: BorderRadius.all(
          Radius.circular(10.0) 
          ),
    ),
    child: Row(children: [
      IconButton(
        padding: EdgeInsets.only(right: 16),
        icon: Icon(Icons.play_arrow, color: Colors.white, size: 48),
        tooltip: 'Start ${issue.issueName}',
        onPressed: () {},
      ),
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              padding: const EdgeInsets.only(bottom: 8),
              child: Text(
                issue.title,
                style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
                softWrap: true,
              ),
            ),
            Text(
              issue.issueName,
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
    ]));
  }
}

screencast

Upvotes: 17

Views: 9626

Answers (4)

Michael Yuwono
Michael Yuwono

Reputation: 2617

The ripple is part of the Material effect. Wrap your IconButton with Material:

Material(
  color: _bgColor,
  child: IconButton(
    padding: EdgeInsets.only(right: 16),
    icon: Icon(Icons.play_arrow, color: Colors.white, size: 48),
    tooltip: 'Start ${issue.issueName}',
    onPressed: () {},
  ),
),

UPDATE

To be more specific to your goal, you can replace your Container with Material.

return Material(
  color: _bgColor,
  borderRadius: BorderRadius.all(Radius.circular(10.0)),
  child: Container(
     margin: EdgeInsets.only(top: 12, left: 18, right: 18),
     padding: EdgeInsets.only(top: 8, bottom: 8),
     backgroundBlendMode: BlendMode.multiply,
     child: Row(
     ...
  ),
);

Upvotes: 20

Alexander Kwint
Alexander Kwint

Reputation: 136

It looks like a bug in the Flutter Framework. This occurs only with IconButton, no problem with FlatButton.

Possible workaround is to set BlendMode to multiply BlendMode.multiply.
try this:

Container(
          decoration: BoxDecoration(
              color: Colors.greenAccent[400],
              backgroundBlendMode: BlendMode.multiply),
          child: ListTile(
            leading: IconButton(icon: Icon(Icons.play_arrow), onPressed: () {}),
            title: Text("issue title"),
            subtitle: Text("description"),
          ),
        ),

Update
issue on github

Upvotes: 2

nick.tdr
nick.tdr

Reputation: 4933

Ripple always takes on top of the material widgets. So if there is anything on top of the material widget you will see ripples under your widget.

Just wrap your IconButton with a Material widget with the material set to use the "transparency" type and it should work.

You can use the below generic widget for adding ripples to your widgets.

class AddRipple extends StatelessWidget {
  final Widget child;
  final Function onTap;

  AddRipple({@required this.child, @required this.onTap});

 @override
 Widget build(BuildContext context) {
 return Stack(
     children: <Widget>[
     child,
      Positioned.fill(
        child: new Material(
            color: Colors.transparent,
            child: new InkWell(
              onTap: onTap,
            ))),
      ],
    );
  }
}

You can also take in a color in the constructor and user 'splashColor' property of the InkWell widget to set the splash color.

Upvotes: 0

Tinus Jackson
Tinus Jackson

Reputation: 3653

You can wrap your Row inside a InkWell, this will give you the touch ripples.

I have removed the background color of the container, had issues with it showing the ripple, as well as changed the text color to black.

enter image description here

    @override
  Widget build(BuildContext context) {
    return Container(
        height: 100,
        margin: EdgeInsets.only(top: 12, left: 18, right: 18),
        padding: EdgeInsets.only(top: 8, bottom: 8),
        decoration: new BoxDecoration(
          color: Colors.transparent,
          border: new Border.all(color: Colors.orange),
          borderRadius: BorderRadius.all(Radius.circular(10.0)),
        ),
        child: InkWell(
          // added here
          onTap: () {},
          child: Row(children: [
            IconButton(
              padding: EdgeInsets.only(right: 16),
              icon: Icon(Icons.play_arrow, color: Colors.black, size: 48),
              tooltip: 'Start issue',
              onPressed: () {},
            ),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Container(
                    padding: const EdgeInsets.only(bottom: 8),
                    child: Text(
                      'issue.title',
                      style: TextStyle(
                        color: Colors.black,
                        fontWeight: FontWeight.bold,
                      ),
                      softWrap: true,
                    ),
                  ),
                  Text(
                    'issue.issueName',
                    style: TextStyle(
                      color: Colors.black,
                    ),
                  ),
                ],
              ),
            ),
          ]),
        ));
  }

References

Add ripples

Upvotes: 0

Related Questions