Flutter contains various in-built button types like RaisedButton, FlatButton, etc. But with the help of GestureDetector, we can make any widget to perform a set of actions on certain gestures. In this article, we are going to use AnimatedContainer to make Neumorphic Button in Flutter. The traditional way of creating a button includes the use of drop shadows, but it makes it feel like the button is hovering over the background. But in Neumorphism we use two types of shading- light on one side and dark on the other which makes it feel like the button is attached to the background and not hovering above it. We will be using VS code to develop our Flutter application.
Step by Step Implementation
Step 1: Creating a new Flutter application.
- Open VS code, and by using “Ctrl+Shift+P” select “Flutter: New Project”.
- Select the folder in which you want to create your application.
- Then give a name to your application.
- After pressing “Enter” Flutter SDK will create a new project for you.
Step 2: After creating the project open the “main.dart” file and paste the below code into it.
import 'package:flutter/material.dart' ;
void main() {
runApp( const MyApp());
} class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is root
// of your application
@override
Widget build(BuildContext context) {
return MaterialApp(
// By using this line,
// you can hide Debug banner
debugShowCheckedModeBanner: false ,
title: 'Flutter Demo' ,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const NeumorphismPage(),
);
}
} |
Step 3: Create a stateful widget below the MyApp widget and name it as NeumorphismPage. In VS Code you can try typing “stl” and in autocomplete select stateful widget or paste the below code. This is the code for the “main.dart” file.
import 'package:flutter/material.dart' ;
void main() {
runApp( const MyApp());
} class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false ,
title: 'Flutter Demo' ,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const NeumorphismPage(),
);
}
} // Widget that will be shown // at the start of application. class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State<NeumorphismPage> createState() => _NeumorphismPageState();
} class _NeumorphismPageState extends State<NeumorphismPage> {
bool _isElevated = false ;
@override
Widget build(BuildContext context) {
// Create your widget here.
return Scaffold();
}
} |
Note: You can create a separate dart file for each widget and then import it but as it is only a single widget we will only create one file.
Step 4: Following will be the code to create the Neumorphic button.
Example 1
In this example, after pressing the button it will become flat.
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State<NeumorphismPage> createState() => _NeumorphismPageState();
} class _NeumorphismPageState extends State<NeumorphismPage> {
// Boolean to check whether the
// button is elevated or not.
bool _isElevated = false ;
@override
Widget build(BuildContext context) {
return Scaffold(
// Providing background
// color to our Scaffold
backgroundColor: Colors.grey[300],
body: Center(
// Gesture Detector to detect taps
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Image.asset(
"assets/gfg.png" ,
scale: 3,
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circular,
// If widget is not elevated, elevate it.
boxShadow: _isElevated
?
// Elevation Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
),
]
: null,
),
),
),
),
);
}
} |
Output:
Example 2
In this widget, after pressing the button it will create inset shadows. Before that, we need to add a package.
flutter pub add flutter_inset_box_shadow
Then imports at the start of the file should be changed as follows:
import 'package:flutter/material.dart' hide BoxDecoration, BoxShadow; import 'package:flutter_inset_box_shadow/flutter_inset_box_shadow.dart'; // As both packages contains BoxDecoration and BoxShadow, so hiding them in from one of the package to avoid Diamond Problem
After the imports, we will create inset shadows using the code below.
class NeumorphismPage extends StatefulWidget {
const NeumorphismPage({Key? key}) : super(key: key);
@override
State<NeumorphismPage> createState() => _NeumorphismPageState();
} class _NeumorphismPageState extends State<NeumorphismPage> {
bool _isElevated = false ;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: GestureDetector(
onTap: () {
setState(() {
_isElevated = !_isElevated;
});
},
child: AnimatedContainer(
child: Icon(
Icons.power_settings_new,
size: 80,
// Changing icon color on
// the basis of it's elevation
color:
_isElevated ? Colors.grey : Color.fromARGB(255, 83, 220, 230),
),
// Providing duration parameter
// to create animation
duration: const Duration(
milliseconds: 200,
),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
// when _isElevated is false, value
// of inset parameter will be true
// that will create depth effect.
boxShadow: _isElevated
?
// Elevated Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: false ,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: false ,
),
]
:
// Depth Effect
[
const BoxShadow(
color: Color(0xFFBEBEBE),
// Shadow for bottom right corner
offset: Offset(10, 10),
blurRadius: 30,
spreadRadius: 1,
inset: true ,
),
const BoxShadow(
color: Colors.white,
// Shadow for top left corner
offset: Offset(-10, -10),
blurRadius: 30,
spreadRadius: 1,
inset: true ,
),
],
),
),
),
),
);
}
} |
Output: