惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
L
LangChain Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗
小众软件
小众软件
博客园 - Franky
D
Docker
Google DeepMind News
Google DeepMind News
Microsoft Azure Blog
Microsoft Azure Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
宝玉的分享
宝玉的分享
C
Check Point Blog
B
Blog
V
V2EX
博客园 - 三生石上(FineUI控件)
MyScale Blog
MyScale Blog
The Cloudflare Blog
博客园 - 聂微东
博客园_首页
Engineering at Meta
Engineering at Meta

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How I Built VoxCalc — An AI-Inspired Next-Gen Calculator ...
Md Rounaq Ali · 2026-06-01 · via DEV Community

TL;DR: I built a cross-platform scientific calculator in Flutter that lets you speak math equations out loud, point your camera at handwritten formulas, and watch them get solved instantly. Here's exactly how I did it.


🎯 Why I Built This

As a B.Tech CSE student, I was tired of building the same CRUD apps for my portfolio.

Everyone has a to-do list. Everyone has a weather app. I wanted to build something that genuinely impressed technical interviewers and showed I could work with AI APIs, device hardware, and complex state management — all at once.

So I built VoxCalc — a mathematical computational suite that combines:

  • 🎙️ Voice-to-Math: Speak "what is 15 percent of 340" and get the answer
  • 📸 Camera OCR: Point at a handwritten equation → it solves it
  • 📈 2D Graph Plotter: Visualize any algebraic function with multi-touch zoom
  • 💱 Currency Converter: Live exchange rates via REST API

Here's what I learned building it from scratch.


🛠️ The Tech Stack

Framework:     Flutter 3.x (Dart)
Architecture:  Clean Architecture (Feature-First)
AI / ML:       Google ML Kit (Text Recognition v2)
Voice:         speech_to_text package (NLP)
State Mgmt:    Provider / Riverpod
APIs:          Open Exchange Rates REST API
Storage:       flutter_secure_storage
Build:         Gradle with R8/Proguard minification


🏗️ Architecture: Why Feature-First Clean Architecture?

Most Flutter tutorials show you lib/screens/ and lib/widgets/. That works for demos. It breaks for real apps.

I used Feature-First Clean Architecture, which separates every feature into its own isolated module:

lib/
├── core/
│   ├── theme/
│   ├── utils/
│   └── constants/
├── features/
│   ├── calculator/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   ├── voice_input/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   ├── ocr_scanner/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   ├── graph_plotter/
│   └── currency_converter/
└── main.dart

Why this matters: Each feature can be developed, tested, and deployed independently. When I added the currency converter 2 weeks after the core calculator, I didn't touch a single existing file.


🎙️ Feature 1: Voice-to-Math NLP Engine

This was the most exciting feature to build. The goal: convert natural spoken language into a solvable math expression.

The Challenge

speech_to_text gives you raw text like:

"what is fifteen percent of three hundred and forty"

That's useless to a math parser. You need:

340 * 0.15

My Solution: A Custom NLP Preprocessor

I wrote a Dart utility class that maps English phrases to mathematical operators:

class MathNLPParser {
  static const Map<String, String> _wordMap = {
    'plus': '+',
    'minus': '-',
    'times': '*',
    'multiplied by': '*',
    'divided by': '/',
    'percent of': '* 0.01 *',
    'squared': '^ 2',
    'square root of': 'sqrt(',
  };

  static String parse(String spokenText) {
    String expression = spokenText.toLowerCase();

    // Replace word numbers with digits
    expression = _replaceWordNumbers(expression);

    // Replace operator phrases
    _wordMap.forEach((word, operator) {
      expression = expression.replaceAll(word, operator);
    });

    // Clean up and validate
    expression = expression.replaceAll(RegExp(r'[^0-9+\-*/.()^\s]'), '').trim();

    return expression;
  }
}

Then I pass this cleaned expression to a math evaluation engine to get the result.

The UX Touch

While the user is speaking, I render a live audio waveform animation using a custom painter that reads microphone amplitude values in real time. This makes the feature feel futuristic and gives users confidence the app is listening.


📸 Feature 2: Camera OCR Scanner (On-Device, 100% Offline)

Using Google ML Kit Text Recognition v2, I built a live camera scanner that detects handwritten or printed mathematical expressions and solves them instantly.

Setup

# pubspec.yaml
dependencies:
  google_mlkit_text_recognition: ^0.11.0
  camera: ^0.10.5

The Core Scanner Logic

class OcrScannerService {
  final textRecognizer = TextRecognizer(
    script: TextRecognitionScript.latin,
  );

  Future<String?> recognizeFromImage(InputImage image) async {
    try {
      final RecognizedText result = await textRecognizer.processImage(image);

      // Extract only math-relevant characters
      String raw = result.text;
      String cleaned = _extractMathExpression(raw);

      return cleaned.isNotEmpty ? cleaned : null;
    } catch (e) {
      debugPrint('OCR Error: $e');
      return null;
    }
  }

  String _extractMathExpression(String raw) {
    // Keep only digits, operators, and math symbols
    return raw
      .replaceAll('×', '*')
      .replaceAll('÷', '/')
      .replaceAll(RegExp(r'[^0-9+\-*/().=\s]'), '')
      .trim();
  }
}

Why On-Device Processing Matters

I specifically chose ML Kit over cloud OCR APIs (like Google Vision API) because:

  1. Zero latency — no network round trip
  2. Privacy — user's handwriting never leaves their device
  3. Works offline — functions in airplane mode
  4. Free — no API billing ever

📈 Feature 3: Real-Time 2D Algebraic Graph Plotter

This was the most technically complex feature. I built a custom CustomPainter that renders mathematical functions as smooth curves on a coordinate grid.

class GraphPainter extends CustomPainter {
  final String expression;
  final double scale;
  final Offset offset;

  GraphPainter({
    required this.expression,
    required this.scale,
    required this.offset,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2 + offset.dx, 
                          size.height / 2 + offset.dy);

    // Draw coordinate axes
    _drawAxes(canvas, size, center);

    // Plot the function
    _plotFunction(canvas, size, center);
  }

  void _plotFunction(Canvas canvas, Size size, Offset center) {
    final paint = Paint()
      ..color = const Color(0xFF00E5FF)  // Neon cyan
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;

    final path = Path();
    bool firstPoint = true;

    // Sample function at every pixel along x-axis
    for (double px = 0; px < size.width; px++) {
      double x = (px - center.dx) / scale;
      double? y = _evaluateAt(expression, x);

      if (y == null || y.isNaN || y.isInfinite) {
        firstPoint = true;
        continue;
      }

      double py = center.dy - (y * scale);

      if (firstPoint) {
        path.moveTo(px, py);
        firstPoint = false;
      } else {
        path.lineTo(px, py);
      }
    }

    canvas.drawPath(path, paint);
  }
}

I also implemented multi-touch pinch-to-zoom and pan gestures using GestureDetector to give users a native-feeling interactive graph experience.


🔒 Security & Build Optimization

Secure Storage

For saving user preferences and API keys, I used flutter_secure_storage which encrypts data using platform-native keystore (Android Keystore / iOS Keychain):

final storage = const FlutterSecureStorage();

// Write
await storage.write(key: 'api_key', value: userApiKey);

// Read
String? key = await storage.read(key: 'api_key');

R8/Proguard Minification

In android/app/build.gradle, I enabled R8 code shrinking for the release build:

buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                      'proguard-rules.pro'
    }
}

This reduced the APK size by ~40% and made reverse engineering significantly harder.


🎨 UI Design Philosophy

I went with a dark glassmorphism theme with neon cyan highlights (#00E5FF). The design principle was: "make it feel like something from 2030".

Key UI decisions:

  • 120 FPS micro-animations on button press using AnimatedScale
  • Custom slide-out drawer for feature navigation (instead of a boring tab bar)
  • Tactile haptic feedback on every key press using HapticFeedback.lightImpact()
  • Futuristic monospace font (JetBrains Mono) for the result display

🚀 What I Learned

  1. Clean Architecture pays off immediately — when I added the currency converter, it took 4 hours, not 4 days
  2. On-device ML is the future — no latency, no cost, better privacy
  3. Custom painters are powerful — Flutter's canvas API can render anything you imagine
  4. NLP is hard but solvable — even simple regex + word maps get you 80% of the way there
  5. Security is not optional — even a calculator app handles user data that deserves encryption

📦 Check It Out


💬 What's Next?

I'm currently exploring adding:

  • LaTeX rendering for displaying complex mathematical notation
  • Step-by-step equation solver showing all working steps
  • Wolfram Alpha API integration for symbolic math

If you found this useful, drop a ❤️ or share it! I'm a B.Tech CSE student from Hyderabad actively looking for Flutter internship opportunities — feel free to connect on LinkedIn!