开发微醺坊时,发现一些交互存并不友好,记录下自己最终选定的优化方案。
FloatingActionButton 遮挡内容
输入时,随着键盘弹出,FloatingActionButton(后称FAB)会随着上浮,遮挡需要展示的内容。
搜了一圈资料,多是设置FAB不再随着键盘上浮之类的,但是这容易造成用户误会,最终考虑将FAB设置透明度。
import 'package:flutter/material.dart';
class KeyboardAwareFAB extends StatelessWidget {
const KeyboardAwareFAB({
super.key,
required this.onPressed,
this.icon = Icons.check,
this.duration = const Duration(milliseconds: 188),
this.opacityWhenKeyboardOpen = 0.3, // 可自定义半透明程度
});
final VoidCallback onPressed;
final IconData icon;
final Duration duration;
final double opacityWhenKeyboardOpen;
@override
Widget build(BuildContext context) {
// 检测键盘是否弹出
final bool isKeyboardOpen = MediaQuery.of(context).viewInsets.bottom > 0;
// 根据键盘状态决定透明度
final double targetOpacity = isKeyboardOpen ? opacityWhenKeyboardOpen : 1.0;
// 过平滑改变透明度实现“半透明”效果,动画自然且性能好
return AnimatedOpacity(
opacity: targetOpacity,
duration: duration,
curve: Curves.easeInOut,
child: FloatingActionButton(
// 保持 key 稳定,避免重建时动画异常
key: const ValueKey('keyboard_aware_fab'),
onPressed: onPressed,
// 可选:键盘弹出时也可以禁用按钮(如果不想让用户点击)
// onPressed: isKeyboardOpen ? null : onPressed,
child: Icon(icon),
),
);
}
}
TextField 多行输入时,iOS 和 Android 自带输入法键盘不会自动收起
在 Flutter App 中,尤其是使用 showDialog(如 AlertDialog)显示多行输入的 TextField 时,iPhone(iOS)自带输入法键盘不会自动收起。
多行输入 (keyboardType: TextInputType.multiline 或 maxLines > 1 / null)时,键盘右下角的“返回”键是用于换行,而不是“Done”(完成并收起键盘)。
再加上 iOS 系统不像 Android 有导航栏的返回按钮,也没有自动在键盘上提供“收起”功能按钮。这点国产输入法就做的很人性化,每次输入完成后,键盘右上角会出现“收起”功能按钮。
搜了一圈资料,基本都是手动在输入组件中增加“完成”按钮,或者通过第三方包(keyboard_actions)添加键盘工具栏。前者影响设计,后者实现复杂。
最终选择使用点击对话框空白区域,令输入组件失去焦点,实现收起键盘。本准备使用GestureDetector实现该逻辑,恰好搜索到官方资料,Flutter 3.7+ 起,TextField 支持 onTapOutside。
DartTextField(
...,
onTapOutside: (event) {
// 用户点击 TextField 外的对话框空白区域,即可收起键盘。
FocusManager.instance.primaryFocus?.unfocus();
},
)