gesture_recorder 0.2.0 copy "gesture_recorder: ^0.2.0" to clipboard
gesture_recorder: ^0.2.0 copied to clipboard

gesture_recorder enables you to record and replay gesture events

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:gesture_recorder/gesture_recorder.dart';
import 'shared_preferences.dart' as persistence;

void main() {
  runApp(GestureRecorder(child: const MyApp()));

  // for more detailed example
  // runApp(GestureRecorder(child: const DrawingCanvasExample()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  RecordedGestureData? _recordedData;

  Future<void> _toggleRecordState(RecordState recordState) async {
    switch (recordState) {
      case RecordState.none:
        if (_recordedData != null) {
          await GestureRecorder.replay(context, _recordedData!);
        } else {
          GestureRecorder.start(context);
        }
      case RecordState.recording:
        final data = await GestureRecorder.stop(context);
        setState(() {
          _recordedData = data;
        });
      case RecordState.playing:
        // do nothing
        break;
    }
  }

  Future<void> _saveData() async {
    if (_recordedData == null) return;
    final success = await persistence.saveRecordedData(_recordedData!);
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content:
              Text(success ? 'Data saved successfully' : 'Failed to save data'),
          duration: const Duration(seconds: 2),
        ),
      );
    }
  }

  Future<void> _restoreData() async {
    final data = await persistence.fetchRecordedData();
    if (mounted) {
      if (data != null) {
        setState(() {
          _recordedData = data;
        });
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('No saved data found'),
            duration: Duration(seconds: 2),
          ),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final recordState = GestureRecorder.stateOf(context);
    final hasHistory = _recordedData != null;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 48),
            Text(
              recordState.recordStatusText(hasHistory),
              style: Theme.of(context).textTheme.titleMedium?.copyWith(
                    color: recordState.recordColor(hasHistory),
                    fontWeight: FontWeight.bold,
                  ),
            ),
            const SizedBox(height: 16),
            ElevatedButton.icon(
              onPressed: recordState == RecordState.playing
                  ? null
                  : () => _toggleRecordState(recordState),
              icon: Icon(recordState.recordIcon(hasHistory)),
              label: Text(
                recordState == RecordState.recording
                    ? 'Stop Recording'
                    : hasHistory
                        ? 'Replay'
                        : 'Start Recording',
              ),
              style: ElevatedButton.styleFrom(
                backgroundColor: recordState.recordColor(hasHistory),
                foregroundColor: Colors.white,
                padding: const EdgeInsets.symmetric(
                  horizontal: 24,
                  vertical: 12,
                ),
              ),
            ),
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton.icon(
                  onPressed: (hasHistory &&
                          recordState != RecordState.recording &&
                          recordState != RecordState.playing)
                      ? _saveData
                      : null,
                  icon: const Icon(Icons.save),
                  label: const Text('Save'),
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(
                      horizontal: 24,
                      vertical: 12,
                    ),
                  ),
                ),
                const SizedBox(width: 16),
                ElevatedButton.icon(
                  onPressed: (recordState != RecordState.recording &&
                          recordState != RecordState.playing)
                      ? _restoreData
                      : null,
                  icon: const Icon(Icons.restore),
                  label: const Text('Restore'),
                  style: ElevatedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(
                      horizontal: 24,
                      vertical: 12,
                    ),
                  ),
                ),
              ],
            ),
            if (hasHistory) ...[
              const SizedBox(height: 16),
              Text(
                'Events: ${_recordedData!.events.length}',
                style: Theme.of(context).textTheme.bodySmall,
              ),
              Text(
                'Screen size: ${_recordedData!.screenSize.width.toStringAsFixed(0)} x ${_recordedData!.screenSize.height.toStringAsFixed(0)}',
                style: Theme.of(context).textTheme.bodySmall,
              ),
            ],
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _counter++),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

extension on RecordState {
  IconData recordIcon(bool hasHistory) => switch (this) {
        RecordState.none =>
          hasHistory ? Icons.play_arrow : Icons.fiber_manual_record,
        RecordState.recording => Icons.stop,
        RecordState.playing => Icons.play_arrow,
      };

  Color recordColor(bool hasHistory) => switch (this) {
        RecordState.none => hasHistory ? Colors.green : Colors.red,
        RecordState.recording => Colors.grey,
        RecordState.playing => Colors.blue,
      };

  String recordStatusText(bool hasHistory) => switch (this) {
        RecordState.none => hasHistory ? 'Ready to replay' : 'Ready to record',
        RecordState.recording => 'Recording...',
        RecordState.playing => 'Playing...',
      };
}
18
likes
160
points
41
downloads

Publisher

unverified uploader

Weekly Downloads

gesture_recorder enables you to record and replay gesture events

Repository (GitHub)
View/report issues

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on gesture_recorder