I would like to draw a user's attention to a submit button anytime a radio button is selected and I would like to know if there's anyway to implement this in flutter. I have looked at the RaisedButton docs but there doesn't seem to be any property that flashes or shakes the button. The code below for instance initially has no radio button selected so the button is grayed out, once a choice is made amongst multiple radio buttons, the submit RaisedButton onPressed property value is no longer null but replaced with the action required; however I also want a situation where if a different radio button is selected, there is some way to add some motion (flashing/shaking button) to the submit button but not change the onPressed property

new Radio<int>(
value: 1, 
groupValue: 0, 
onChanged: handleRadioValue
)

new RaisedButton(
child: const Text('SUBMIT')
onPressed: selected
)

handleRadioValue(){
selected = groupValue == 0 ? null : submitButton();
//change Raised button to attract attention}


Solution 1: Collin Jackson

You can attract attention by animating the color of the RaisedButton. This example draws attention to the RaisedButton when the radio button selection changes by changing its color to the current theme's disabledColor and back.

screenshot

import 'dart:math';
import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'Flutter Demo',
        home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  AnimationController _controller;
  int _radioValue;

  @override initState() {
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 100),
    )..addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed)
        _controller.reverse();
    });
    super.initState();
  }

  void _handleRadioValue(int value) {
    // Don't animate the first time that the radio value is set
    if (_radioValue != null)
      _controller.forward();
    setState(() {
      _radioValue = value;
    });
  }

  @override
  Widget build(BuildContext context) {
    ThemeData theme = Theme.of(context);
    return new Scaffold(
      body: new Center(
        child: new Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            new Radio<int>(
              value: 0,
              groupValue: _radioValue,
              onChanged: _handleRadioValue
            ),
            new Radio<int>(
              value: 1,
              groupValue: _radioValue,
              onChanged: _handleRadioValue
            ),
            new AnimatedBuilder(
              child: const Text('SUBMIT'),
              animation: _controller,
              builder: (BuildContext context, Widget child) {
                return new RaisedButton(
                  color: new ColorTween(
                    begin: theme.primaryColor,
                    end: theme.disabledColor,
                  ).animate(_controller).value,
                  colorBrightness: Brightness.dark,
                  child: child,
                  onPressed: _radioValue == null ?
                             null :
                             () => print('submit')
                );
              }
            )
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}