Flutter 密码锁定屏幕

共 22643字,需浏览 46分钟

 ·

2021-05-12 10:20


Flutter 让我对高效构建令人愉悦的UI很感兴趣,而且它允许您同时为两个平台创建。直到最近一年,我一直使用touchID和FaceID作为身份验证工具。在任何情况下,如最新的Andriod先决条件所指出的那样,您需要在生物识别认证被破坏或受损的偶然机会上提供选择性的认证策略。

在在本文中,我们将探讨「Flutter中」「密码锁定屏幕」。我们将看到如何在flutter应用程序中使用「passcode_screen」软件包来实现演示程序密码锁定屏幕。

pub 地址:https://pub.dev/packages/passcode_screen

密码锁定屏幕

一个与阶段无关的Flutter软件包,用于显示密码输入屏幕,例如Native iOS。屏幕可适应颜色,大小,文本样式等。它将显示在flutter应用程序中使用密码屏幕时如何解锁屏幕。

该演示视频演示了如何在Flutter中创建密码锁定屏幕。它显示了如何在flutter应用程序中使用「passcode_screen」软件包来运行密码锁定屏幕。它显示密码输入屏幕以解锁屏幕。它会显示在您的设备上。

使用

  1. 添加依赖

    passcode_screen: ^1.2.2+1
  2. 引入

    import 'package:passcode_screen/passcode_screen.dart';
  3. 运行命令:「flutter packages get」

  4. 启用「AndriodX」

    org.gradle.jvmargs=-Xmx1536M
    android.enableR8=true
    android.useAndroidX=true
    android.enableJetifier=true

在libs目录下创建 「demo_page.dart」 文件

Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Text('You are ${isAuthenticated ? '' : 'not'}'
          ' authenticated',style: TextStyle(fontSize: 16),),
      SizedBox(height: 10,),
      _lockScreenButton(context),
    ],
  ),
),

在主屏幕上,我们将添加文本“You are not authenticated”,这意味着用户可以解锁密码屏幕,然后更改身份验证文本。否则,您的设备上将显示未通过身份验证。我们将添加一个**_lockScreenButton(context)。**

_lockScreenButton(BuildContext context) => MaterialButton(
  padding: EdgeInsets.only(left: 50,right: 50),
  color: Theme.of(context).primaryColor,
  child: Text('Lock Screen',style: TextStyle(color: Colors.white,
      fontWeight: FontWeight.bold,fontSize: 17),),
  onPressed: () {
    _showLockScreen(
      context,
      opaque: false,
      cancelButton: Text(
        'Cancel',
        style: const TextStyle(fontSize: 16, color: Colors.white,),
        semanticsLabel: 'Cancel',
      ),
    );
  },
);

在**_lockScreenButton()中**,我们将使用按钮。我们将在按钮内添加填充,颜色,文本和onPressed方法,并在此方法上添加**_showLockScreen()**小部件。当我们运行应用程序时,我们应该获得屏幕的输出,如屏幕下方的截图所示。

img

定义**_showLockScreen()**

_showLockScreen(BuildContext context,
    {bool opaque,
      CircleUIConfig circleUIConfig,
      KeyboardUIConfig keyboardUIConfig,
      Widget cancelButton,
      List<String> digits}) {
  Navigator.push(
      context,
      PageRouteBuilder(
        opaque: opaque,
        pageBuilder: (context, animation, secondaryAnimation) => PasscodeScreen(
          title: Text(
            'Enter Passcode',
            textAlign: TextAlign.center,
            style: TextStyle(color: Colors.white, fontSize: 28),
          ),
          circleUIConfig: circleUIConfig,
          keyboardUIConfig: keyboardUIConfig,
          passwordEnteredCallback: _passcodeEntered,
          cancelButton: cancelButton,
          deleteButton: Text(
            'Delete',
            style: const TextStyle(fontSize: 16, color: Colors.white),
            semanticsLabel: 'Delete',
          ),
          shouldTriggerVerification: _verificationNotifier.stream,
          backgroundColor: Colors.black.withOpacity(0.8),
          cancelCallback: _passcodeCancelled,
          digits: digits,
          passwordDigits: 6,
          bottomWidget: _passcodeRestoreButton(),
        ),
      ));
}

在此小部件中,我们将添加「PasscodeScreen()。「在屏幕内部,我们将添加标题,内置的圆圈配置和键盘。我们将添加一个」passwordEnteredCallback」方法。在此方法中,添加_passcodeEntered小部件,我们将在下面进行定义。添加一个cancelButton,deleteButton,shouldTriggerVerification,cancelCallback,密码数字和bottomWidget。

final StreamController<bool> _verificationNotifier = StreamController<bool>.broadcast();
_passcodeEntered(String enteredPasscode) {
  bool isValid = storedPasscode == enteredPasscode;
  _verificationNotifier.add(isValid);
  if (isValid) {
    setState(() {
      this.isAuthenticated = isValid;
    });
  }
}

密码输入完成回调,并在密码正确与否时通知密码屏幕。用户可以添加任何storedPasscodelike 654321等。如果密码有效,则对屏幕进行身份验证。当我们运行应用程序时,我们应该获得屏幕的输出,如屏幕下方的截图所示。

img

不要忘记关闭流。用户可以处理它。

@override 
void dispose(){_ 
  verificationNotifier.close(); 
  super.dispose(); 
}

定义**_passcodeRestoreButton()**

Align(
  alignment: Alignment.bottomCenter,
  child: Container(
    margin: const EdgeInsets.only(bottom: 10.0, top: 20.0),
    child: FlatButton(
      child: Text(
        "Reset passcode",
        textAlign: TextAlign.center,
        style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w300),
      ),
      splashColor: Colors.white.withOpacity(0.4),
      highlightColor: Colors.white.withOpacity(0.2),
      onPressed: _resetApplicationPassword,
    ),
  ),
);

在此小部件中,如果结果等于结果,则导航pop。否则,使用**_restoreDialog()**小部件,然后弹出。

_restoreDialog(VoidCallback onAccepted) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        backgroundColor: Colors.teal[50],
        title: Text(
          "Reset passcode",
          style: const TextStyle(color: Colors.black87),
        ),
        content: Text(
          "Passcode reset is a non-secure operation!\nAre you sure want to reset?",
          style: const TextStyle(color: Colors.black87),
        ),
        actions: <Widget>[
          // usually buttons at the bottom of the dialog
          FlatButton(
            child: Text(
              "Cancel",
              style: const TextStyle(fontSize: 18),
            ),
            onPressed: () {
              Navigator.maybePop(context);
            },
          ),
          FlatButton(
            child: Text(
              "I proceed",
              style: const TextStyle(fontSize: 18),
            ),
            onPressed: onAccepted,
          ),
        ],
      );
    },
  );
}

完整代码:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_passcode_lock_screen/constant.dart';
import 'package:passcode_screen/circle.dart';
import 'package:passcode_screen/keyboard.dart';
import 'package:passcode_screen/passcode_screen.dart';

class DemoPage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage{
  final StreamController<bool> _verificationNotifier = StreamController<bool>.broadcast();
  bool isAuthenticated = false;

  @override
  void dispose() {
    _verificationNotifier.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blueGrey[100],
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title: Text('Passcode Lock Screen Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You are ${isAuthenticated ? '' : 'not'}'
                ' authenticated',style: TextStyle(fontSize: 16),),
            SizedBox(height: 10,),
            _lockScreenButton(context),
          ],
        ),
      ),
    );
  }

  _lockScreenButton(BuildContext context) => MaterialButton(
    padding: EdgeInsets.only(left: 50,right: 50),
    color: Theme.of(context).primaryColor,
    child: Text('Lock Screen',style: TextStyle(color: Colors.white,
        fontWeight: FontWeight.bold,fontSize: 17),),
    onPressed: () {
      _showLockScreen(
        context,
        opaque: false,
        cancelButton: Text(
          'Cancel',
          style: const TextStyle(fontSize: 16, color: Colors.white,),
          semanticsLabel: 'Cancel',
        ),
      );
    },
  );


  _showLockScreen(BuildContext context,
      {bool opaque,
        CircleUIConfig circleUIConfig,
        KeyboardUIConfig keyboardUIConfig,
        Widget cancelButton,
        List<String> digits}) {
    Navigator.push(
        context,
        PageRouteBuilder(
          opaque: opaque,
          pageBuilder: (context, animation, secondaryAnimation) => PasscodeScreen(
            title: Text(
              'Enter Passcode',
              textAlign: TextAlign.center,
              style: TextStyle(color: Colors.white, fontSize: 28),
            ),
            circleUIConfig: circleUIConfig,
            keyboardUIConfig: keyboardUIConfig,
            passwordEnteredCallback: _passcodeEntered,
            cancelButton: cancelButton,
            deleteButton: Text(
              'Delete',
              style: const TextStyle(fontSize: 16, color: Colors.white),
              semanticsLabel: 'Delete',
            ),
            shouldTriggerVerification: _verificationNotifier.stream,
            backgroundColor: Colors.black.withOpacity(0.8),
            cancelCallback: _passcodeCancelled,
            digits: digits,
            passwordDigits: 6,
            bottomWidget: _passcodeRestoreButton(),
          ),
        ));
  }

  _passcodeEntered(String enteredPasscode) {
    bool isValid = storedPasscode == enteredPasscode;
    _verificationNotifier.add(isValid);
    if (isValid) {
      setState(() {
        this.isAuthenticated = isValid;
      });
    }
  }

  _passcodeCancelled() {
    Navigator.maybePop(context);
  }

  _passcodeRestoreButton() => Align(
    alignment: Alignment.bottomCenter,
    child: Container(
      margin: const EdgeInsets.only(bottom: 10.0, top: 20.0),
      child: FlatButton(
        child: Text(
          "Reset passcode",
          textAlign: TextAlign.center,
          style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w300),
        ),
        splashColor: Colors.white.withOpacity(0.4),
        highlightColor: Colors.white.withOpacity(0.2),
        onPressed: _resetApplicationPassword,
      ),
    ),
  );

  _resetApplicationPassword() {
    Navigator.maybePop(context).then((result) {
      if (!result) {
        return;
      }
      _restoreDialog(() {
        Navigator.maybePop(context);
      });
    });
  }

  _restoreDialog(VoidCallback onAccepted) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          backgroundColor: Colors.teal[50],
          title: Text(
            "Reset passcode",
            style: const TextStyle(color: Colors.black87),
          ),
          content: Text(
            "Passcode reset is a non-secure operation!\nAre you sure want to reset?",
            style: const TextStyle(color: Colors.black87),
          ),
          actions: <Widget>[
            // usually buttons at the bottom of the dialog
            FlatButton(
              child: Text(
                "Cancel",
                style: const TextStyle(fontSize: 18),
              ),
              onPressed: () {
                Navigator.maybePop(context);
              },
            ),
            FlatButton(
              child: Text(
                "I proceed",
                style: const TextStyle(fontSize: 18),
              ),
              onPressed: onAccepted,
            ),
          ],
        );
      },
    );
  }

}


浏览 93
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报