flutter_screen_lock 9.1.0 copy "flutter_screen_lock: ^9.1.0" to clipboard
flutter_screen_lock: ^9.1.0 copied to clipboard

Provides the ability to lock the screen on ios and android. Biometric authentication can be used in addition to passcode.

example/lib/main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screen_lock/flutter_screen_lock.dart';
import 'package:local_auth/local_auth.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    Future<void> localAuth(BuildContext context) async {
      final localAuth = LocalAuthentication();
      final didAuthenticate = await localAuth.authenticate(
        localizedReason: 'Please authenticate',
        options: const AuthenticationOptions(biometricOnly: true),
      );

      if (didAuthenticate && context.mounted) {
        Navigator.pop(context);
      }
    }

    return Scaffold(
        appBar: AppBar(
          title: const Text('Next Screen Lock'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16),
          child: Center(
            child: ConstrainedBox(
              constraints: const BoxConstraints(
                maxWidth: 700,
              ),
              child: Wrap(
                spacing: 16,
                runSpacing: 16,
                alignment: WrapAlignment.start,
                children: [
                  ElevatedButton(
                    onPressed: () => showDialog<void>(
                      context: context,
                      builder: (context) {
                        return ScreenLock(
                          correctString: '1234',
                          onCancelled: Navigator.of(context).pop,
                          onUnlocked: Navigator.of(context).pop,
                        );
                      },
                    ),
                    child: const Text('Manually open'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      canCancel: false,
                    ),
                    child: const Text('Not cancelable'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      // Define it to control the confirmation state with its own events.
                      final controller = InputController();
                      screenLockCreate(
                        context: context,
                        inputController: controller,
                        onConfirmed: (matchedText) =>
                            Navigator.of(context).pop(),
                        footer: TextButton(
                          onPressed: () {
                            // Release the confirmation state and return to the initial input state.
                            controller.unsetConfirmed();
                          },
                          child: const Text('Reset input'),
                        ),
                      );
                    },
                    child: const Text('Confirm mode'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      customizedButtonChild: const Icon(
                        Icons.fingerprint,
                      ),
                      customizedButtonTap: () async => await localAuth(context),
                      onOpened: () async => await localAuth(context),
                    ),
                    child: const Text(
                      'use local_auth \n(Show local_auth when opened)',
                      textAlign: TextAlign.center,
                    ),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '123456',
                      canCancel: false,
                      footer: Container(
                        width: 68,
                        height: 68,
                        padding: const EdgeInsets.only(top: 10),
                        child: OutlinedButton(
                          onPressed: () => Navigator.pop(context),
                          style: OutlinedButton.styleFrom(
                            backgroundColor: Colors.transparent,
                          ),
                          child: const Padding(
                            padding: EdgeInsets.all(10),
                            child: Text('Cancel'),
                          ),
                        ),
                      ),
                    ),
                    child: const Text('Using footer'),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      screenLockCreate(
                        context: context,
                        title: const Text('change title'),
                        confirmTitle: const Text('change confirm title'),
                        onConfirmed: (value) => Navigator.of(context).pop(),
                        config: const ScreenLockConfig(
                          backgroundColor: Colors.deepOrange,
                          titleTextStyle: TextStyle(fontSize: 24),
                        ),
                        secretsConfig: SecretsConfig(
                          spacing: 15, // or spacingRatio
                          padding: const EdgeInsets.all(40),
                          secretConfig: SecretConfig(
                            borderColor: Colors.amber,
                            borderSize: 2.0,
                            disabledColor: Colors.black,
                            enabledColor: Colors.amber,
                            size: 15,
                            builder: (context, config, enabled) => Container(
                              decoration: BoxDecoration(
                                shape: BoxShape.rectangle,
                                color: enabled
                                    ? config.enabledColor
                                    : config.disabledColor,
                                border: Border.all(
                                  width: config.borderSize,
                                  color: config.borderColor,
                                ),
                              ),
                              padding: const EdgeInsets.all(10),
                              width: config.size,
                              height: config.size,
                            ),
                          ),
                        ),
                        keyPadConfig: KeyPadConfig(
                          buttonConfig: KeyPadButtonConfig(
                            buttonStyle: OutlinedButton.styleFrom(
                              textStyle: const TextStyle(
                                color: Colors.orange,
                                fontWeight: FontWeight.bold,
                              ),
                              shape: const RoundedRectangleBorder(),
                              backgroundColor: Colors.deepOrange,
                            ),
                          ),
                          displayStrings: [
                            '零',
                            '壱',
                            '弐',
                            '参',
                            '肆',
                            '伍',
                            '陸',
                            '質',
                            '捌',
                            '玖',
                          ],
                        ),
                        cancelButton: const Icon(Icons.close),
                        deleteButton: const Icon(Icons.delete),
                      );
                    },
                    child: const Text('Customize styles'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      onUnlocked: () {
                        Navigator.pop(context);
                        NextPage.show(context);
                      },
                    ),
                    child: const Text('Next page with unlock'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      useBlur: false,
                      config: const ScreenLockConfig(
                        /// If you don't want it to be transparent, override the config
                        backgroundColor: Colors.black,
                        titleTextStyle: TextStyle(fontSize: 24),
                      ),
                    ),
                    child: const Text('Not blur'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      maxRetries: 2,
                      retryDelay: const Duration(seconds: 3),
                      delayBuilder: (context, delay) => Text(
                        'Cannot be entered for ${(delay.inMilliseconds / 1000).ceil()} seconds.',
                      ),
                    ),
                    child: const Text('Delay next retry'),
                  ),
                  ElevatedButton(
                    onPressed: () => showDialog<void>(
                      context: context,
                      builder: (context) => ScreenLock(
                        correctString: '1234',
                        keyPadConfig: const KeyPadConfig(
                          clearOnLongPressed: true,
                        ),
                        onUnlocked: Navigator.of(context).pop,
                      ),
                    ),
                    child: const Text('Delete long pressed to clear input'),
                  ),
                  ElevatedButton(
                    onPressed: () => showDialog<void>(
                      context: context,
                      builder: (context) => ScreenLock(
                        correctString: '1234',
                        secretsBuilder: (
                          context,
                          config,
                          length,
                          input,
                          verifyStream,
                        ) =>
                            SecretsWithCustomAnimation(
                          verifyStream: verifyStream,
                          config: config,
                          input: input,
                          length: length,
                        ),
                        onUnlocked: Navigator.of(context).pop,
                      ),
                    ),
                    child: const Text('Secrets custom animation widget'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: '1234',
                      useLandscape: false,
                    ),
                    child: const Text('Disable landscape mode'),
                  ),
                  ElevatedButton(
                    onPressed: () => screenLock(
                      context: context,
                      correctString: 'x' * 4,
                      onValidate: (value) async => await Future<bool>.delayed(
                        const Duration(milliseconds: 500),
                        () => value == '1234',
                      ),
                    ),
                    child: const Text('Callback validation'),
                  ),
                ],
              ),
            ),
          ),
        ));
  }
}

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

  static show(BuildContext context) {
    Navigator.of(context)
        .push(MaterialPageRoute(builder: (context) => const NextPage()));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Next Page'),
      ),
    );
  }
}

class SecretsWithCustomAnimation extends StatefulWidget {
  const SecretsWithCustomAnimation({
    super.key,
    required this.config,
    required this.length,
    required this.input,
    required this.verifyStream,
  });

  final SecretsConfig config;
  final int length;
  final ValueListenable<String> input;
  final Stream<bool> verifyStream;

  @override
  State<SecretsWithCustomAnimation> createState() =>
      _SecretsWithCustomAnimationState();
}

class _SecretsWithCustomAnimationState extends State<SecretsWithCustomAnimation>
    with SingleTickerProviderStateMixin {
  late Animation<double> _animation;
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();

    widget.verifyStream.listen((valid) {
      if (!valid) {
        // scale animation.
        _animationController.forward();
      }
    });

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 80),
    );

    _animation = Tween<double>(begin: 1, end: 2).animate(_animationController)
      ..addStatusListener(
        (status) {
          if (status == AnimationStatus.completed) {
            _animationController.reverse();
          }
        },
      );
  }

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

  @override
  Widget build(BuildContext context) {
    return ScaleTransition(
      scale: _animation,
      child: Secrets(
        input: widget.input,
        length: widget.length,
        config: widget.config,
      ),
    );
  }
}
265
likes
160
pub points
97%
popularity

Publisher

verified publisherincrementleaf.net

Provides the ability to lock the screen on ios and android. Biometric authentication can be used in addition to passcode.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_screen_lock