Modern Calculator App Built in Flutter πŸ”’ | FuzzuTech

 Demo :


Click Video πŸ‘‡πŸ‘‡πŸ‘‡






















🌟 Features:

  • Embed YouTube Short video

  • Include Flutter code snippet (formatted in code block)

  • Add tags as Blogger “labels”

  • CTA: “Subscribe to FuzzuTech on YouTube for daily tech projects!”


Code :


import 'package:flutter/material.dart';


void main() {

  runApp(CalculatorApp());

}


class CalculatorApp extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'Modern Calculator',

      theme: ThemeData.dark().copyWith(

        scaffoldBackgroundColor: Colors.black,

        colorScheme: ColorScheme.dark(

          primary: Colors.blue,

          secondary: Colors.blueAccent,

        ),

      ),

      home: CalculatorScreen(),

      debugShowCheckedModeBanner: false,

    );

  }

}


class CalculatorScreen extends StatefulWidget {

  @override

  _CalculatorScreenState createState() => _CalculatorScreenState();

}


class _CalculatorScreenState extends State<CalculatorScreen> {

  // Current expression being built

  String _expression = '';

  

  // Result of the calculation

  String _result = '0';

  

  // Track if we're starting a new expression

  bool _newExpression = true;


  // Button layout organized in rows

  final List<List<String>> _buttonRows = [

    ['C', '⌫', '%', '÷'],

    ['7', '8', '9', '×'],

    ['4', '5', '6', '-'],

    ['1', '2', '3', '+'],

    ['+/-', '0', '.', '='],

  ];


  // Check if a character is an operator

  bool _isOperator(String char) {

    return ['+', '-', '×', '÷'].contains(char);

  }


  // Handle button presses

  void _onButtonPressed(String button) {

    setState(() {

      switch (button) {

        case 'C':

          _clear();

          break;

        case '⌫':

          _backspace();

          break;

        case '=':

          _calculate();

          break;

        case '+/-':

          _toggleSign();

          break;

        case '%':

          _percentage();

          break;

        case '.':

          _addDecimal();

          break;

        default:

          if (_isOperator(button)) {

            _addOperator(button);

          } else {

            _addDigit(button);

          }

      }

    });

  }


  // Clear everything

  void _clear() {

    _expression = '';

    _result = '0';

    _newExpression = true;

  }


  // Remove last character

  void _backspace() {

    if (_expression.isNotEmpty) {

      _expression = _expression.substring(0, _expression.length - 1);

    }

    if (_expression.isEmpty) {

      _result = '0';

      _newExpression = true;

    }

  }


  // Add digit to expression

  void _addDigit(String digit) {

    if (_newExpression) {

      _expression = digit;

      _newExpression = false;

    } else {

      _expression += digit;

    }

    _result = _expression;

  }


  // Add operator to expression

  void _addOperator(String operator) {

    if (_expression.isEmpty) return;

    

    // Replace last operator if needed

    final lastChar = _expression[_expression.length - 1];

    if (_isOperator(lastChar)) {

      _expression = _expression.substring(0, _expression.length - 1);

    }

    

    _expression += operator;

    _newExpression = false;

    _result = _expression;

  }


  // Add decimal point

  void _addDecimal() {

    if (_newExpression) {

      _expression = '0.';

      _newExpression = false;

    } else {

      // Check if current number already has a decimal

      final parts = _expression.split(RegExp(r'[+\-×÷]'));

      final currentNumber = parts.last;

      if (!currentNumber.contains('.')) {

        _expression += '.';

      }

    }

    _result = _expression;

  }


  // Toggle positive/negative sign

  void _toggleSign() {

    if (_expression.isEmpty) return;

    

    try {

      // Evaluate current expression and toggle sign

      final currentValue = _evaluateExpression(_expression);

      final toggledValue = -currentValue;

      _expression = toggledValue.toString();

      _result = _expression;

      _newExpression = false;

    } catch (e) {

      _result = 'Error';

    }

  }


  // Convert to percentage

  void _percentage() {

    if (_expression.isEmpty) return;

    

    try {

      final currentValue = _evaluateExpression(_expression);

      final percentageValue = currentValue / 100;

      _expression = percentageValue.toString();

      _result = _expression;

      _newExpression = false;

    } catch (e) {

      _result = 'Error';

    }

  }


  // Convert infix expression to Reverse Polish Notation using shunting-yard algorithm

  List<String> _shuntingYard(List<String> tokens) {

    final output = <String>[];

    final operators = <String>[];

    

    final precedence = {'+': 1, '-': 1, '×': 2, '÷': 2};

    

    for (final token in tokens) {

      if (double.tryParse(token) != null) {

        // Number - add to output

        output.add(token);

      } else if (_isOperator(token)) {

        // Operator - handle precedence

        while (operators.isNotEmpty && 

               precedence[operators.last]! >= precedence[token]!) {

          output.add(operators.removeLast());

        }

        operators.add(token);

      }

    }

    

    // Add remaining operators

    while (operators.isNotEmpty) {

      output.add(operators.removeLast());

    }

    

    return output;

  }


  // Evaluate RPN expression

  double _evaluateRPN(List<String> rpn) {

    final stack = <double>[];

    

    for (final token in rpn) {

      if (double.tryParse(token) != null) {

        stack.add(double.parse(token));

      } else {

        final b = stack.removeLast();

        final a = stack.removeLast();

        

        switch (token) {

          case '+':

            stack.add(a + b);

            break;

          case '-':

            stack.add(a - b);

            break;

          case '×':

            stack.add(a * b);

            break;

          case '÷':

            if (b == 0) throw Exception('Division by zero');

            stack.add(a / b);

            break;

        }

      }

    }

    

    return stack.last;

  }


  // Tokenize expression string

  List<String> _tokenize(String expression) {

    final tokens = <String>[];

    final buffer = StringBuffer();

    

    for (int i = 0; i < expression.length; i++) {

      final char = expression[i];

      

      if (_isOperator(char)) {

        if (buffer.isNotEmpty) {

          tokens.add(buffer.toString());

          buffer.clear();

        }

        tokens.add(char);

      } else {

        buffer.write(char);

      }

    }

    

    if (buffer.isNotEmpty) {

      tokens.add(buffer.toString());

    }

    

    return tokens;

  }


  // Main evaluation function

  double _evaluateExpression(String expression) {

    if (expression.isEmpty) return 0;

    

    try {

      final tokens = _tokenize(expression);

      final rpn = _shuntingYard(tokens);

      return _evaluateRPN(rpn);

    } catch (e) {

      throw Exception('Invalid expression');

    }

  }


  // Perform calculation

  void _calculate() {

    if (_expression.isEmpty) return;

    

    try {

      final result = _evaluateExpression(_expression);

      _result = result.toString();

      

      // Format result to avoid unnecessary decimal places

      if (result % 1 == 0) {

        _result = result.toInt().toString();

      } else {

        _result = result.toStringAsFixed(6).replaceAll(RegExp(r'0+$'), '').replaceAll(RegExp(r'\.$'), '');

      }

      

      _expression = _result;

      _newExpression = true;

    } catch (e) {

      _result = 'Error';

      _newExpression = true;

    }

  }


  // Get button background color based on type

  Color _getButtonColor(String button) {

    if (button == '=') {

      return Colors.blue;

    } else if (_isOperator(button) || button == '%') {

      return Colors.grey[800]!;

    } else if (button == 'C' || button == '⌫') {

      return Colors.grey[700]!;

    } else {

      return Colors.grey[900]!;

    }

  }


  // Get button text color

  Color _getTextColor(String button) {

    if (button == 'C' || button == '⌫') {

      return Colors.redAccent;

    }

    return Colors.white;

  }


  @override

  Widget build(BuildContext context) {

    return Scaffold(

      body: SafeArea(

        child: Column(

          children: [

            // Display area

            Expanded(

              flex: 1,

              child: Padding(

                padding: const EdgeInsets.all(20.0),

                child: Column(

                  mainAxisAlignment: MainAxisAlignment.end,

                  crossAxisAlignment: CrossAxisAlignment.stretch,

                  children: [

                    // Expression display

                    SingleChildScrollView(

                      scrollDirection: Axis.horizontal,

                      reverse: true,

                      child: Text(

                        _expression.isEmpty ? '0' : _expression,

                        style: TextStyle(

                          fontSize: 24,

                          color: Colors.grey[400],

                        ),

                        textAlign: TextAlign.end,

                      ),

                    ),

                    const SizedBox(height: 10),

                    // Result display

                    SingleChildScrollView(

                      scrollDirection: Axis.horizontal,

                      reverse: true,

                      child: Text(

                        _result,

                        style: const TextStyle(

                          fontSize: 48,

                          fontWeight: FontWeight.bold,

                          color: Colors.white,

                        ),

                        textAlign: TextAlign.end,

                      ),

                    ),

                  ],

                ),

              ),

            ),

            

            // Button grid

            Expanded(

              flex: 2,

              child: Padding(

                padding: const EdgeInsets.all(16.0),

                child: Column(

                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,

                  children: _buttonRows.map((row) {

                    return Expanded(

                      child: Row(

                        crossAxisAlignment: CrossAxisAlignment.stretch,

                        children: row.map((button) {

                          return Expanded(

                            child: Padding(

                              padding: const EdgeInsets.all(4.0),

                              child: ElevatedButton(

                                onPressed: () => _onButtonPressed(button),

                                style: ElevatedButton.styleFrom(

                                  backgroundColor: _getButtonColor(button),

                                  foregroundColor: _getTextColor(button),

                                  shape: RoundedRectangleBorder(

                                    borderRadius: BorderRadius.circular(16),

                                  ),

                                  elevation: 2,

                                  shadowColor: Colors.black38,

                                ),

                                child: Text(

                                  button,

                                  style: TextStyle(

                                    fontSize: 24,

                                    fontWeight: FontWeight.w500,

                                  ),

                                ),

                              ),

                            ),

                          );

                        }).toList(),

                      ),

                    );

                  }).toList(),

                ),

              ),

            ),

          ],

        ),

      ),

    );

  }

}

Comments

Popular posts from this blog

Is This News Real or Fake? πŸ€– AI Exposes the Truth | FuzzuTech Python App Demo

🚨 Python Intrusion Detection System (IDS) – Real-Time ML + Tkinter GUI Project | FuzzuTech

Educational File Encryptor GUI (Python AES Project) | FuzzuTech