用了两年的flutter,有了一些心得,从今天开始陆续更新一些案例,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢~(原创不易,转发请标注来源和作者)

注意:无特殊说明,flutter版本为3.0+

此文大部分代码内容来自 GitHub - Im-Kevin/cool_ui: 用flutter实现一些我认为好看的UI控件,有Popover,仿Weui的Toast,自定义键盘,感谢大神指路,喜欢的可以去看源码,当然也有区别于原作者的实现,敬请关注。


为什么需要自定义键盘?自定义键盘可以说在客户端原生开发中有很多地方需要用到,比如做一个数字键盘支持支付业务,特殊内容的输入,或者响应其他特殊需求。作者在开发中也遇到自定义键盘的需求,当时是初学,在github和pub.flutter-io.cn中查了大量的插件,觉得cool_ui中的自定义键盘能满足,再次感谢作者。此文从cool_ui的自定义键盘出发,细说一下解决思路,希望给初学者在自定组件和理解Flutter运行原理提供帮助。

自定义键盘一定是一个Widget组件,那么它至少要实现类似系统键盘的以下功能:

  • 当TextField 聚焦时候弹出键盘组件,将主视图推到键盘上,不至于遮挡
  • 实现内容发送到TextField,也要有“搜索”,“确定”,“下一个”,“收起键盘”等常用键盘指令
当然还有一些细节,比如TextField 失去焦点的时候的时候收起键盘等。
本文先解决如何推起键盘的问题。

一。KeyboardRootWidget

        首先我们要定义一个组件包裹要使用自定义键盘的组件,这个组件可以进行键盘的初始化工作,并定义设置键盘,清楚键盘等功能

1.定义一个StatefulWidget,里面有两个参数的基础设置

class KeyboardRootWidget extends StatefulWidget {
        final Widget child;
        final TextDirection textDirection;  //文字输入的方向,有从右到左,也有从左到右
...

2.键盘初始化KeyboardMediaQuery,下一个章节具体解释

@override
Widget build(BuildContext context) {
// TODO: implement build
return KeyboardMediaQuery(child: Builder(builder: (context) {
CoolKeyboard.init(this, context);

List<Widget> children = [widget.child];
if (_keyboardBuilder != null) {
children.add(Builder(
builder: _keyboardBuilder!,
));
}

...
}

3.设置键盘和清除键盘的方法

setKeyboard 和clearKeyboard ,这两个方法用来设置和清除WidgetBuilder

完整代码如下:

class KeyboardRootState extends State<KeyboardRootWidget> {
WidgetBuilder? _keyboardBuilder;

bool get hasKeyboard => _keyboardBuilder != null;

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

@override
Widget build(BuildContext context) {
// TODO: implement build
return KeyboardMediaQuery(child: Builder(builder: (context) {
CoolKeyboard.init(this, context);

List<Widget> children = [widget.child];
if (_keyboardBuilder != null) {
children.add(Builder(
builder: _keyboardBuilder!,
));
}
return Directionality(
textDirection: widget.textDirection,
child: Stack(
children: children,
));
}));
}

setKeyboard(WidgetBuilder _keyboardBuilder) {
_keyboardBuilder = _keyboardBuilder;
Future.delayed(const Duration(milliseconds: 50)).then((e) {
setState(() {});
});
}

clearKeyboard() {
if (_keyboardBuilder != null) {
_keyboardBuilder = null;
setState(() {});
}
}
}

二。KeybordMediaQuery

我们再回顾一下什么是MediaQuery(如果需要详细了解,可以在我的专栏中搜索此文章),MediaQuery媒体查询会返回MediaQueryData,其中有个一重要数据就是viewInsets,这个是键盘遮挡UI的部分,那我们的思路很清晰,就是在我们自己的键盘弹出的时候更新当前视图的viewInsets值

1.定义一个键盘高度的监听

ValueNotifier<double> keyboardHeightNotifier = CoolKeyboard.getKeyboardHeightNotifier();

@override
void initState(){
super.initState();
CoolKeyboard.getKeyboardHeightNotifier().addListener(onUpdateHeight);
}

2.当键盘高度设置时候,覆盖系统的viewInsets值,就实现了类似系统键盘的弹出功能了。

var data = MediaQuery.maybeOf(context);
data ??= MediaQueryData.fromWindow(WidgetsBinding.instance.window);
var bottom = CoolKeyboard.getKeyboardHeightNotifier().value != 0 ? CoolKeyboard.getKeyboardHeightNotifier().value : data.viewInsets.bottom;
return MediaQuery(
        child: widget.child,
        data:data.copyWith(
        ​​​​​​​viewInsets: data.viewInsets.copyWith(
        ;bottom: bottom
        )

)
);

完整代码如下

class KeyboardMediaQuery extends StatefulWidget{
final Widget child;

KeyboardMediaQuery({required this.child});

@override
State<StatefulWidget> createState() =>KeyboardMediaQueryState();

}

class KeyboardMediaQueryState extends State<KeyboardMediaQuery >{
double keyboardHeight = 0;
ValueNotifier<double> keyboardHeightNotifier = CoolKeyboard.getKeyboardHeightNotifier();

@override
void initState(){
super.initState();
CoolKeyboard.getKeyboardHeightNotifier().addListener(onUpdateHeight);
}

@override
Widget build(BuildContext context) {

// TODO: implement build
var data = MediaQuery.maybeOf(context);
data ??= MediaQueryData.fromWindow(WidgetsBinding.instance.window);
var bottom = CoolKeyboard.getKeyboardHeightNotifier().value != 0 ? CoolKeyboard.getKeyboardHeightNotifier().value : data.viewInsets.bottom;
// TODO: implement build
return MediaQuery(
child: widget.child,
data:data.copyWith(
viewInsets: data.viewInsets.copyWith(
bottom: bottom
)
)
);
}

onUpdateHeight(){
try{
setState(()=>{});
}catch(_){
WidgetsBinding.instance.addPostFrameCallback((_){
setState(()=>{});
});
}
}

@override
void dispose(){
super.dispose();
CoolKeyboard.getKeyboardHeightNotifier().removeListener(onUpdateHeight);
}
}

Flutter实战-自定义键盘(一)相关推荐

  1. Flutter实战-自定义键盘(二)

    用了两年的flutter,有了一些心得,从今天开始陆续更新一些案例,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜 ...

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

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

  3. flutter -各类自定义弹窗(图片预览,输入框,键盘)以及如何阻止事件冒泡

    开局废话:由于公司app后期需要做混合开发,又担心h5的性能问题.于是迫不得已,只能两端齐搞,验证一些性能优化的问题.打开了一年前flutter正式发布时,蹭热度创建的现已布满藤蔓的仓库,微微颤抖的双 ...

  4. Flutter实战 | 从 0 搭建「网易云音乐」APP(五、播放功能逻辑)

    本系列可能会伴随大家很长时间,这里我会从0开始搭建一个「网易云音乐」的APP出来. 下面是该APP 功能的思维导图: 前期回顾: 1.Flutter实战 | 从 0 搭建「网易云音乐」APP(一.创建 ...

  5. Flutter 组件之 Flutter高级自定义TabBar(教程含源码)

    实战需求 Flutter 组件之 Flutter高级自定义TabBar(教程含源码) 本文价值与收获 看完本文后,您将能够作出下面的界面 实战代码 import 'package:flutter/ma ...

  6. Android的自定义键盘颜色,android自定义键盘(解决弹出提示的字体颜色问题)

    最近准备要做一个项目,需要用到自定义小键盘来确保安全,而且还需要精确获得用户点击键盘时的落点位置.力度.指尖接触屏幕的面积等参数. 在写自定义键盘的时 最近准备要做一个项目,需要用到自定义小键盘来确保 ...

  7. android键盘ui,android – 在自定义键盘中重新调整候选视图的UI

    我正在使用自定义键盘.我在onCreateCandidatesView()中设置了setCandidatesViewShown(true)函数,问题是UI没有得到正确的重新调整. 任何帮助都会很棒.以 ...

  8. Flutter实战之(Clubhouse App)

    flutter_ClubHouse 课程安排 每日一更, 最后达到的效果是1:1 项目简介 "Clubhouse"(俱乐部会馆)的音频聊天应用程序日前火了.这款社交软件的功能相对单 ...

  9. android自定义数字键盘和字母键盘,Android自定义键盘的实现(数字键盘和字母键盘)...

    Android自定义键盘的实现(数字键盘和字母键盘) 发布时间:2020-09-04 03:18:48 来源:脚本之家 阅读:100 作者:浪淘沙xud 在项目中,产品对于输入方式会有特殊的要求,需要 ...

最新文章

  1. 无向图的连通分量的数量
  2. 树莓派与阿里云服务器之间的无线通信(非局域网)
  3. 如何删除windowsXP的计算器
  4. java 手写 jvm高性能缓存
  5. c语言第1次作业答案,C语言第五次上机作业参考答案
  6. JDBC和MySQL的实现原理
  7. kotlin 使用viewStub
  8. php storm 安装,PhpStorm安装教程
  9. 几道经典逻辑推理题,提高你的逻辑思考能力
  10. cc2530 按键中断实验——按键控制LED灯的亮灭
  11. 什么是ring0-ring3
  12. 智能语音:好玩的语音控制是怎么实现的?学习笔记01
  13. 搜狗校招笔试题编程之一
  14. 论EBS的并发请求(报表中心)的必要性
  15. 爬取某知名网站的数据
  16. HTML基于蔡徐坤的打飞机游戏源码
  17. 现代编程语言(1):Rust (铁锈,一文掌握钢铁是怎样生锈的)
  18. QPS、TPS、RT、并发用户数、吞吐量
  19. 手把手教你使用hexo搭建属于你的个人博客
  20. 宏杰文件夹加密V2878【永久免费的文件加密软件】

热门文章

  1. 将一个很长(>30)的十进制数转换为二进制数
  2. hdu 2674(N!Again)
  3. mysql索引失效的替代方案,索引失效的十大杂症
  4. 华为gt手表绑定微信运动提示服务器忙,华为手表gt的微信通知显示
  5. 好的计划是通向成功的捷径
  6. 素描零基础知道啥是三大面跟五调子…
  7. java保留小数点后面两位(四舍五入)
  8. 对付身体小毛病的80妙招(转)
  9. CIO时代APP上线了!每天微讲座等让IT学习“兴趣随身”
  10. 如何在Excel里安装excel插件?