Open In App

Flutter – Neumorphic Button

Last Updated : 04 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Flutter contains various in-built button types like ElevatedButton, TextButton, etc. But with the help of GestureDetector, we can make any widget perform a set of actions on certain gestures. In this article, we are going to use AnimatedContainer to make a 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.

Demo Video:

Step by Step Implementation

Step 1: Create a new Flutter Application

Create a new Flutter application using the command Prompt. To create a new app, write the following command and run it.

flutter create app_name

To know more about it refer this article: Creating a Simple Application in Flutter.

Step 2: Working with main.dart:

Add the boilerplate code below in main.dart to initialize the Firebase in the main function and create a basic structure with an MaterialApp and call NeumorphismPage().

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: Working with NeumorphismPage Class

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

  @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: Create a Neumorphic button

The following will be the code to create the Neumorphic button. 

Example:

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,
            ),
          ),
        ),
      ),
    );
  }
}


Complete Source Code:

main.dart:

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(),
    );
  }
}

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.circle,
              // 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: 




Next Article
Article Tags :

Similar Reads