100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Flutter仿微信 支付宝密码输入框+自定义键盘

Flutter仿微信 支付宝密码输入框+自定义键盘

时间:2022-08-06 21:35:13

相关推荐

Flutter仿微信 支付宝密码输入框+自定义键盘

大家好,我又来了。

刚用Flutter做完一个金融项目,当中使用到了类似于微信,和支付宝的那种密码输入框,然后为了安全一点也自己实现了自定义的键盘,今天跟大家分享一波

效果如下图所示:

Flutter自定义密码——键盘.jpg

当中的布局形式,大家可根据自己的具体需求来调整就好了,我这里写的demo是这样的布局,这个调整起来很简单(本来想弄成gif的,然而不会。。。)。

我们分析下这个东东,首先我们需要自定义好这个密码输入框,当我们在输入一个密码的时候,密码输入框就填充一位 ,这个过程其实我们自己把它绘制出来就好:

先绘制六个密码框接受调用者传过来的密码,根据密码长度来绘制密码框的填充个数

/// 自定义 密码输入框 第一步 —— 使用画笔画出单个的框class CustomJPasswordField extends StatelessWidget {/// 传入当前密码String data;CustomJPasswordField(this.data);@overrideWidget build(BuildContext context) {return CustomPaint(painter: MyCustom(data),);}}/// 继承CustomPainter ,来实现自定义图形绘制class MyCustom extends CustomPainter {/// 传入的密码,通过其长度来绘制圆点String pwdLength;MyCustom(this.pwdLength);/// 此处Sizes是指使用该类的父布局大小@overridevoid paint(Canvas canvas, Size size) {// 密码画笔Paint mPwdPaint;Paint mRectPaint;// 初始化密码画笔 mPwdPaint = new Paint();mPwdPaint..color = Colors.black;// mPwdPaint.setAntiAlias(true);// 初始化密码框 mRectPaint = new Paint();mRectPaint..color = Color(0xff707070);/// 圆角矩形的绘制RRect r = new RRect.fromLTRBR(0.0, 0.0, size.width, size.height, new Radius.circular(size.height / 12));/// 画笔的风格mRectPaint.style = PaintingStyle.stroke;canvas.drawRRect(r, mRectPaint);/// 将其分成六个 格子(六位支付密码)var per = size.width / 6.0;var offsetX = per;while (offsetX < size.width) {canvas.drawLine(new Offset(offsetX, 0.0), new Offset(offsetX, size.height), mRectPaint);offsetX += per;}/// 画实心圆var half = per/2;var radio = per/8;mPwdPaint.style = PaintingStyle.fill;/// 当前有几位密码,画几个实心圆for(int i =0; i< pwdLength.length && i< 6; i++){canvas.drawArc(new Rect.fromLTRB(i*per+half-radio, size.height/2-radio, i*per+half+radio, size.height/2+radio), 0.0, 2*pi, true, mPwdPaint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}}

到这里为止,我们就写完了我们第一个重头,自定义的密码输入框,然后第二步,实现自定义密码键盘,密码键盘也可以通过完全自定义绘制出来,但是我这里用的一种比较简单的实现方式,直接使用多个按钮组装成一个键盘,

自定义键盘.png

这个键盘其实就是12个相同样式的按钮组成,只是各自的文字内容不同,因此我们首先可以定义好一个公共的按钮样式,然后我们在其中通过回调的方式来将点击事件抛给调用者定义,

import 'package:flutter/material.dart';/// 自定义 键盘 按钮class CustomKbBtn extends StatefulWidget {/// 按钮显示的文本内容String text;CustomKbBtn({Key key, this.text, this.callback}) : super(key: key);/// 按钮 点击事件的回调函数final callback;@overrideState<StatefulWidget> createState() {return ButtonState();}}class ButtonState extends State<CustomKbBtn> {///回调函数执行体var backMethod;void back() {widget.callback('$backMethod');}@overrideWidget build(BuildContext context) {/// 获取当前屏幕的总宽度,从而得出单个按钮的宽度MediaQueryData mediaQuery = MediaQuery.of(context);var _screenWidth = mediaQuery.size.width;return new Container(height:50.0,width: _screenWidth / 3,child: new OutlineButton(// 直角shape: new RoundedRectangleBorder(borderRadius: new BorderRadius.circular(0.0)),// 边框颜色borderSide: new BorderSide(color: Color(0x10333333)),child: new Text(widget.text,style: new TextStyle(color: Color(0xff333333), fontSize: 20.0),),// 按钮点击事件onPressed: back,));}}

有了按钮之后,我们就将它拼装成一个完整的键盘:

/// 自定义密码 键盘class MyKeyboard extends StatefulWidget {final callback;MyKeyboard(this.callback);@overrideState<StatefulWidget> createState() {return new MyKeyboardStat();}}class MyKeyboardStat extends State<MyKeyboard> {final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();/// 定义 确定 按钮 接口 暴露给调用方///回调函数执行体var backMethod;void onCommitChange() {widget.callback(new KeyEvent("commit"));}void onOneChange(BuildContext cont) {widget.callback(new KeyEvent("1"));}void onTwoChange(BuildContext cont) {widget.callback(new KeyEvent("2"));}void onThreeChange(BuildContext cont) {widget.callback(new KeyEvent("3"));}void onFourChange(BuildContext cont) {widget.callback(new KeyEvent("4"));}void onFiveChange(BuildContext cont) {widget.callback(new KeyEvent("5"));}void onSixChange(BuildContext cont) {widget.callback(new KeyEvent("6"));}void onSevenChange(BuildContext cont) {widget.callback(new KeyEvent("7"));}void onEightChange(BuildContext cont) {widget.callback(new KeyEvent("8"));}void onNineChange(BuildContext cont) {widget.callback(new KeyEvent("9"));}void onZeroChange(BuildContext cont) {widget.callback(new KeyEvent("0"));}/// 点击删除void onDeleteChange() {widget.callback(new KeyEvent("del"));}@overrideWidget build(BuildContext context) {return new Container(key: _scaffoldKey,width: double.infinity,height: 250.0,color: Colors.white,child: new Column(children: <Widget>[new Container(height:30.0,color: Colors.white,alignment: Alignment.center,child: new Text('下滑隐藏',style: new TextStyle(fontSize: 12.0, color: Color(0xff999999)),),),/// 键盘主体new Column(children: <Widget>[/// 第一行new Row(children: <Widget>[CustomKbBtn(text: '1', callback: (val) => onOneChange(context)),CustomKbBtn(text: '2', callback: (val) => onTwoChange(context)),CustomKbBtn(text: '3', callback: (val) => onThreeChange(context)),],),/// 第二行new Row(children: <Widget>[CustomKbBtn(text: '4', callback: (val) => onFourChange(context)),CustomKbBtn(text: '5', callback: (val) => onFiveChange(context)),CustomKbBtn(text: '6', callback: (val) => onSixChange(context)),],),/// 第三行new Row(children: <Widget>[CustomKbBtn(text: '7', callback: (val) => onSevenChange(context)),CustomKbBtn(text: '8', callback: (val) => onEightChange(context)),CustomKbBtn(text: '9', callback: (val) => onNineChange(context)),],),/// 第四行new Row(children: <Widget>[CustomKbBtn(text: '删除', callback: (val) => onDeleteChange()),CustomKbBtn(text: '0', callback: (val) => onZeroChange(context)),CustomKbBtn(text: '确定', callback: (val) => onCommitChange()),],),],)],),);}}

这里的回调函数,其实是将所有的按钮事件处理交给调用者自己去处理,

这里就引出了代码中的KeyEvent()这个类,我们看看这个类的实现

/// 支符密码 用于 密码输入框和键盘之间进行通信class KeyEvent {/// 当前点击的按钮所代表的值String key;KeyEvent(this.key);bool isDelete() => this.key == "del";bool isCommit() => this.key == "commit";}

这个类实际上只是拿到了按钮最终代表的实际内容,然后调用者可以根据这个key的值来判断当前点击的是 数字按钮 还是说是 删除按钮 或者是 确定按钮,以此来进行密码的修改,。

到这里为止,所有的内容基本都准备好了,接下来就是使用了:

这里得注意一个点,密码键盘是从屏幕的最下方弹出来的,这里我使用到了Flutter的showBottomSheet,这个是一个官方的widget,通过这个来实现键盘的弹出。

直接上代码吧

/// 支付密码 + 自定义键盘class main_keyboard extends StatefulWidget {static final String sName = "enter";@overrideState<StatefulWidget> createState() {return new keyboardState();}}class keyboardState extends State<main_keyboard> {/// 用户输入的密码String pwdData = '';/*GlobalKey:整个应用程序中唯一的键ScaffoldState:Scaffold框架的状态解释:_scaffoldKey的值是Scaffold框架状态的唯一键*/final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();// VoidCallback:没有参数并且不返回数据的回调VoidCallback _showBottomSheetCallback;@overridevoid initState() {_showBottomSheetCallback = _showBottomSheet;}@overrideWidget build(BuildContext context) {return new Scaffold(key: _scaffoldKey,body: _buildContent(context),);}Widget _buildContent(BuildContext c) {return new Container(width: double.maxFinite,height: 300.0,color: Color(0xffffffff),child: new Column(children: <Widget>[new Padding(padding: const EdgeInsets.only(top: 50.0),child: new Text('请在此输入新支付密码',style: new TextStyle(fontSize: 18.0, color: Color(0xff333333)),),),///密码框new Padding(padding: const EdgeInsets.only(top: 15.0),child: _buildPwd(pwdData),),],),);}/// 密码键盘 确认按钮 事件void onAffirmButton() {}/// 密码键盘的整体回调,根据不同的按钮事件来进行相应的逻辑实现void _onKeyDown(KeyEvent data){// 如果点击了删除按钮,则将密码进行修改if (data.isDelete()) {if (pwdData.length > 0) {pwdData = pwdData.substring(0, pwdData.length - 1);setState(() {});}} // 点击了确定按钮时else if (data.isCommit()) {if (pwdData.length != 6) {// Fluttertoast.showToast(msg: "密码不足6位,请重试", gravity: ToastGravity.CENTER);return;}onAffirmButton();} //点击了数字按钮时 将密码进行完整的拼接else {if (pwdData.length < 6) {pwdData += data.key;}setState(() {});}}/// 底部弹出 自定义键盘 下滑消失void _showBottomSheet() {setState(() {// disable the button // 禁用按钮_showBottomSheetCallback = null;});/*currentState:获取具有此全局键的树中的控件状态showBottomSheet:显示持久性的质感设计底部面板解释:联系上文,_scaffoldKey是Scaffold框架状态的唯一键,因此代码大意为,在Scaffold框架中显示持久性的质感设计底部面板*/_scaffoldKey.currentState.showBottomSheet<void>((BuildContext context) {/// 将自定义的密码键盘作为其child 这里将回调函数传入return new MyKeyboard(_onKeyDown);}).closed.whenComplete(() {if (mounted) {setState(() {// re-enable the button // 重新启用按钮_showBottomSheetCallback = _showBottomSheet;});}});}/// 构建 密码输入框 定义了其宽度和高度Widget _buildPwd(var pwd) {return new GestureDetector(child: new Container(width: 250.0,height:40.0,//color: Colors.white, 自定义密码输入框的使用child: new CustomJPasswordField(pwd),),// 用户点击输入框的时候,弹出自定义的键盘onTap: () {_showBottomSheetCallback();},);}}

大功告成,这个时候我们就实现了想要的效果啦。

回想了下我写的博客,基本都是代码偏多,我把该有的说明都在代码中写成注释了,我觉得这样更加的直观,希望各位喜欢这种方式,如果本文帮助到了你,希望你能点点喜欢,给我一点点鼓励,每次看到有人评论和点了喜欢,都会很开心,哈哈。要是能点点关注就更好了。

有啥问题欢迎及时联系我,我们下次再见啦!

代码来啦Github传送门

作者:Yinll

链接:/p/675bff7a0d4a

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。