Open In App

Flutter – Neumorphic Button

Last Updated : 11 Apr, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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.

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 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.

Dart




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.

Dart




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.

Dart




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:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads