face_gesture_detector 0.1.0-dev copy "face_gesture_detector: ^0.1.0-dev" to clipboard
face_gesture_detector: ^0.1.0-dev copied to clipboard

A Flutter widget that translates camera frames and facial landmarks into high-level semantic callbacks, analogous to how GestureDetector translates pointer events into touch gestures.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:face_gesture_detector/face_gesture_detector.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Face Gesture Detector Demo',
      theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
      home: const FaceDetectorDemo(),
    );
  }
}

class FaceDetectorDemo extends StatefulWidget {
  const FaceDetectorDemo({super.key});

  @override
  State<FaceDetectorDemo> createState() => _FaceDetectorDemoState();
}

class _FaceDetectorDemoState extends State<FaceDetectorDemo> {
  final _controller = FaceGestureDetectorController();
  final _events = <String>[];

  bool _hasFace = false;
  bool _isPaused = false;

  void _addEvent(String event) {
    setState(() {
      _events.insert(
        0,
        '${DateTime.now().toIso8601String().substring(11, 19)} $event',
      );
      if (_events.length > 50) _events.removeLast();
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Face Gesture Detector'),
        actions: [
          IconButton(
            icon: Icon(_isPaused ? Icons.play_arrow : Icons.pause),
            onPressed: () {
              setState(() {
                _isPaused = !_isPaused;
                _isPaused ? _controller.pause() : _controller.resume();
              });
            },
          ),
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () {
              _controller.reset();
              setState(() => _events.clear());
            },
          ),
        ],
      ),
      body: Column(
        children: [
          // Camera preview placeholder — replace with actual CameraPreview
          // once native layer (M3) is integrated.
          Expanded(
            flex: 2,
            child: FaceGestureDetector(
              configuration: FaceGestureConfiguration(),
              controller: _controller,
              onFaceDetected: (details) {
                _hasFace = true;
                _addEvent(
                  'Face detected (${(details.confidence * 100).toInt()}%)',
                );
              },
              onFaceLost: () {
                _hasFace = false;
                _addEvent('Face lost');
              },
              onBlinkDetected: (details) => _addEvent(
                'Blink (${details.blinkDuration.inMilliseconds}ms)',
              ),
              onSmileDetected: (details) => _addEvent(
                'Smile (intensity: ${details.intensity.toStringAsFixed(2)})',
              ),
              onHeadTurnDetected: (details) =>
                  _addEvent('Head turn ${details.direction.name}'),
              onHeadNodDetected: (details) =>
                  _addEvent('Head nod ${details.direction.name}'),
              onBrowRaised: (details) => _addEvent(
                'Brow raised (${details.intensity.toStringAsFixed(2)})',
              ),
              onMouthOpened: (details) => _addEvent(
                'Mouth open (${details.openness.toStringAsFixed(2)})',
              ),
              onPoseChanged: (details) =>
                  _addEvent('Pose: frontal=${details.isFrontal}'),
              onDistanceChanged: (details) =>
                  _addEvent('Distance: ${details.category.name}'),
              child: Container(
                color: _hasFace ? Colors.green.shade50 : Colors.grey.shade200,
                child: Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(
                        _hasFace ? Icons.face : Icons.face_retouching_off,
                        size: 64,
                        color: _hasFace ? Colors.green : Colors.grey,
                      ),
                      const SizedBox(height: 8),
                      Text(
                        _hasFace ? 'Face Detected' : 'No Face',
                        style: Theme.of(context).textTheme.headlineSmall,
                      ),
                      const SizedBox(height: 4),
                      Text(
                        'Camera preview will appear here\nonce native layer is integrated',
                        textAlign: TextAlign.center,
                        style: Theme.of(context).textTheme.bodySmall,
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
          // Event log
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.grey.shade100,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(8),
                    child: Text(
                      'Event Log',
                      style: Theme.of(context).textTheme.titleSmall,
                    ),
                  ),
                  const Divider(height: 1),
                  Expanded(
                    child: _events.isEmpty
                        ? const Center(child: Text('Waiting for events...'))
                        : ListView.builder(
                            padding: const EdgeInsets.symmetric(horizontal: 8),
                            itemCount: _events.length,
                            itemBuilder: (context, index) => Padding(
                              padding: const EdgeInsets.symmetric(vertical: 2),
                              child: Text(
                                _events[index],
                                style: const TextStyle(
                                  fontFamily: 'monospace',
                                  fontSize: 12,
                                ),
                              ),
                            ),
                          ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
0
points
0
downloads

Publisher

verified publisherccisne.dev

Weekly Downloads

A Flutter widget that translates camera frames and facial landmarks into high-level semantic callbacks, analogous to how GestureDetector translates pointer events into touch gestures.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on face_gesture_detector

Packages that implement face_gesture_detector