# 优化短信验证码逻辑
# 禁止获取验证码事件误触
主要优化counter_button.dart
的逻辑:
class _CounterButtonState extends State<CounterButton> {
String _msg = '获取验证码';
NumberCount _numberCount = NumberCount();
Widget build(BuildContext context) {
return StreamBuilder(
stream: _numberCount.stream,
builder: (context, snapshot) {
// ...
return ElevatedButton(
// ...
onPressed: () {
// 优化点击事件,当按钮不可点击时,把onPressed事件进行屏蔽
if (!(widget.active && _numberCount.avaliable)) {
return;
}
_numberCount.start();
widget.onPressed!();
},
);
});
}
}
# 键盘相关
# 模拟键盘
在mac上模拟键盘的弹出:
在顶部的菜单点选I/O->Keyboard->Connect Hardware Keyboard
取消掉,就可以弹出模拟键盘了:
# 键盘高度溢出
除了键盘可能会溢出,页面上的元素也可能会导致溢出(空间不够),或者叠在一起了,提示xxx OVERFLOWED BY xx PIXELS
。知道了原因之后,具体问题具体分析:
键盘溢出,是由于首页整个内容不能滚动。
解决方案:
// 使用SingleChildScrollView
class _HomePageState extends State<HomePage> {
Widget build(BuildContext context) {
return SafeArea(
// 1.Column -> logo + form
// 2.如何引用图片 -> 图片圆角
child: SingleChildScrollView(
child: Column(
children: [
// ...
// 这个是封装的登录组件
LoginForm(),
],
),
),
);
}
}
# 键盘颜色背景
# 方案一
通过设置TextField
:
TextField(
focusNode: currentFocusNode,
controller: controller,
// 设置 keyboardAppearance, light为浅色,默认为 dark 深色
// keyboardAppearance: Brightness.light,
decoration: InputDecoration(
counterText: "",
prefixIcon: Icon(
MyIcons.person,
color: Colors.black54,
size: 26,
),
),
// ...
缺点:
针对于所有的键盘都需要设置,比较麻烦。
# 方案二
一劳永逸的作法,在main.dart
中设置主题:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
// CuperinoApp
return MaterialApp(
theme: ThemeData(
brightness: Brightness.light,
primaryColorBrightness: Brightness.light,
),
home: Scaffold(
appBar: AppBar(),
// 2. SafeArea
body: HomePage(),
),
);
// return MaterialApp(
// home: Scaffold(
// appBar: AppBar(),
// body: Container(
// child: Text(
// 'toimc社区',
// textDirection: TextDirection.ltr,
// ),
// ),
// ),
// );
}
}
# 如何自动聚焦输入框
需要借助到FocusNode
,修改login/login_form.dart
文件中的LoginFormState
:
// 新建两个FocusNode,用于控制聚焦
FocusNode currentFocusNode = FocusNode();
FocusNode focusNode = FocusNode();
// 调整手机号 + 验证码部分的输入的Textfield
TextField(
focusNode: currentFocusNode,
// ...
),
TextField(
focusNode: focusNode,
// ...
),
自动聚焦如何实现:
// 定义私有方法
_changeFocus(FocusNode focusNodeNext) {
// 判断一下,current是否被聚焦,取消聚焦 -> 聚焦新的输入框
FocusNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
focusNodeNext.requestFocus();
}
输入手机号之后,点击获取验证码:
// Positioned
// 1.页面按钮状态 -> 有状态组件如何设置页面状态
// 2.倒计时逻辑 -> stream
Positioned(
right: 10.0,
child: CounterButton(
active: _active,
onPressed: () async {
_changeFocus(focusNode);
userService.sendCode(controller.text);
},
),
)
# 其他技巧
如何设置键盘的类型?
可以设置TextField中的
keyboardType
,比如keyboardType: TextInputType.number
,这样键盘弹出后就只能输入数字类型的数据了。如何删除Input输入框后面的文字计数?
可以在
decoration
部分设置InputDecoration
中的counterText
为空字符串。