Hi Guys, Welcome to Proto Coders Point, In this flutter article we will implement button in flutter to show a progress or loading indication, useful when a form is been submitted.
- Loading Spinner Indicator on Button – Flutter:
Useful, when user is submittiing a form & has to wait until form submittion is successful. In that case, we can show a Circular Progress Indicator like showing a loading spinner on a button until form is submitted.
- Animated Loading Button State – Flutter
Here we will create 3 state of a button Indication.
1. ButtonState.init: initial state of a button (before submitting).

2. ButtonState.submitting: A state to indicate user that the form is getting submitting to the server & user need to wait. This state is loading/progress just to show circular Progress.

3. ButtonState.completed: A state to indicate that the from is submitted successfuly.

Note: This Article source code is just the UI to create a loading button in flutter ( this is not a real time form submission example)
Example 1: Flutter Code – Loading Circular Spinner Button
Code – main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
//loading spinner on button
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isLoading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
height: 70,
width: MediaQuery.of(context).size.width,
alignment: Alignment.center,
child: ElevatedButton(
style: ElevatedButton.styleFrom(shape: StadiumBorder()),
onPressed: () async {
setState(() {
isLoading = true;
});
await Future.delayed(const Duration(seconds: 5));
setState(() {
isLoading = false;
});
},
child: (isLoading)
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 1.5,
))
: const Text('Submit'),
),
),
),
);
}
}
Output of above code

Example 2: Flutter Code – Animated Loading Circular Button State
Code – main.dart
Read the comment in below code for understanding the code flow:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ButtonStates(),
);
}
}
bool isAnimating = true;
//enum to declare 3 state of button
enum ButtonState { init, submitting, completed }
class ButtonStates extends StatefulWidget {
const ButtonStates({Key? key}) : super(key: key);
@override
_ButtonStatesState createState() => _ButtonStatesState();
}
class _ButtonStatesState extends State<ButtonStates> {
ButtonState state = ButtonState.init;
@override
Widget build(BuildContext context) {
final buttonWidth = MediaQuery.of(context).size.width;
// update the UI depending on below variable values
final isInit = isAnimating || state == ButtonState.init;
final isDone = state == ButtonState.completed;
return Scaffold(
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(40),
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
onEnd: () => setState(() {
isAnimating = !isAnimating;
}),
width: state == ButtonState.init ? buttonWidth : 70,
height: 60,
// If Button State is Submiting or Completed show 'buttonCircular' widget as below
child: isInit ? buildButton() : circularContainer(isDone)),
),
);
}
// If Button State is init : show Normal submit button
Widget buildButton() => ElevatedButton(
style: ElevatedButton.styleFrom(shape: const StadiumBorder()),
onPressed: () async {
// here when button is pressed
// we are changing the state
// therefore depending on state our button UI changed.
setState(() {
state = ButtonState.submitting;
});
//await 2 sec // you need to implement your server response here.
await Future.delayed(Duration(seconds: 2));
setState(() {
state = ButtonState.completed;
});
await Future.delayed(Duration(seconds: 2));
setState(() {
state = ButtonState.init;
});
},
child: const Text('SUBMIT'),
);
// this is custom Widget to show rounded container
// here is state is submitting, we are showing loading indicator on container then.
// if it completed then showing a Icon.
Widget circularContainer(bool done) {
final color = done ? Colors.green : Colors.blue;
return Container(
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
child: Center(
child: done
? const Icon(Icons.done, size: 50, color: Colors.white)
: const CircularProgressIndicator(
color: Colors.white,
),
),
);
}
}
Output of above code






