flutter 使用Overlay 自定义数字键盘

 我这边没有把 输入框 和 键盘封装在一起,只封装了键盘 这几本能满足日常用途了  日常使用到独立的数字键盘的场景不多 

用例

OverlayEntry overlayEntry;
TextEditingController controller = TextEditingController();

TextField(
  controller: controller,
  onTap: (){
    // 使用键盘
    numberKeypan(
      initialization: (v){
        /// 初始化
        overlayEntry = v;
        /// 唤起键盘
        openKeypan(context: context);
      },
      onDel: (){
        delCursor(textEditingController: controller);
      },
      onTap: (v){
        /// 更新输入框的值
        controller.text += v;
        /// 保持光标
        lastCursor(textEditingController: controller);
      },
    );
  },
  showCursor: true, //显示光标
  readOnly: true, // 禁用唤起系统键盘 
),

注:未点击回车键时 离开当前页面时 需要调用 disKeypan( )  销毁键盘 否则会一直浮动在最上层,除了回车事件带销毁 其他场景情况 需手动销毁浮动的键盘

封装


import 'package:flutter/material.dart';

/// <summary>
/// todo: 数字键盘
/// author:zwb
/// dateTime:2021/7/19 10:25
/// filePath:lib/app/widgets/number_keypan.dart
/// desc:  
/// <summary> 
OverlayEntry overlayEntry;
numberKeypan({@required Function(OverlayEntry) initialization,@required Function(String) onTap,Function onCommit,Function onDel,}){
  overlayEntry = OverlayEntry(builder: (context) {
    List<String> list = ['1','2','3','4','5','6','7','8','9','','0','.'];
    return new Positioned(
        bottom: 0,
        child: new Material(
          child: new Container(
            width: MediaQuery.of(context).size.width,
            alignment: Alignment.center,
            color: Colors.grey[200],
            child: Row(
              children: [
                Expanded(
                  child: Wrap(
                    alignment: WrapAlignment.spaceBetween,
                    children: List.generate(list.length, (index) {
                      return Material(
                        color: Colors.white,
                        child: Ink(
                          child: InkWell(
                            child: Container(
                              decoration: BoxDecoration(
                                border: Border.all(color: Colors.grey[200],width: 0.25),
                              ),
                              alignment: Alignment.center,
                              height: 50,
                              width: (MediaQuery.of(context).size.width - 60) / 3,
                              child: Text("${list[index]}",style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold),),
                            ),
                            onTap: (){
                              if(list[index] != ""){
                                onTap(list[index]);
                              }
                            },
                          ),
                          color: Colors.white,
                        ),
                      );
                    }),
                  ),
                ),
                Column(
                  children: [
                    SizedBox(
                      width: 60,
                      height: 50 * 1.5,
                      child: MaterialButton(
                        onPressed:  onDel ?? (){},
                        child: Text("删除",style: TextStyle(color: Colors.black,fontWeight: FontWeight.bold)),
                        color: Colors.grey[100],
                        elevation: 0,
                        padding: EdgeInsets.all(0),),
                    ),
                    SizedBox(
                      width: 60,
                      height: 50 * 2.5,
                      child: MaterialButton(
                        onPressed: (){
                          disKeypan();
                          if(onCommit != null ) onCommit();
                        },
                        child: Text("回车",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),),
                        color: Colors.blue,
                        elevation: 0,
                        padding: EdgeInsets.all(0),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ));
  });
  initialization(overlayEntry);
}

/// <summary>
/// todo: 保持光标在最后
/// author: zwb
/// date: 2021/7/19 11:43
/// param: 参数
/// return: void
/// <summary>
///
lastCursor({@required TextEditingController textEditingController}){
  /// 保持光标在最后
  final length = textEditingController.text.length;
  textEditingController.selection = TextSelection(baseOffset:length , extentOffset:length);
}

/// <summary>
/// todo: 自定义键盘的删除事件
/// author: zwb
/// date: 2021/7/19 11:45
/// param: 参数
/// return: void
/// <summary>
///
delCursor({@required TextEditingController textEditingController}){
  if(textEditingController != null && textEditingController.value.text != "") textEditingController.text = textEditingController.text.substring(0,textEditingController.text.length - 1);
}

/// <summary>
/// todo: 打开键盘
/// author: zwb
/// date: 2021/7/19 12:04
/// param: 参数
/// return: void
/// <summary>
///
openKeypan({BuildContext context}){
  Overlay.of(context).insert(overlayEntry);
}

/// <summary>
/// todo: 销毁键盘
/// author: zwb
/// date: 2021/7/19 12:03
/// param: 参数
/// return: void
/// <summary>
///
disKeypan(){
  overlayEntry.remove();
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Flutter中,可以使用自定义Widget来实现自定义键盘。以下是实现自定义键盘的一般步骤: 1. 创建一个StatefulWidget,该Widget将显示自定义键盘。 2. 实现一个键盘布局。可以使用Flutter提供的各种Widget(如Container、Row、Column等)来创建键盘布局,并使用GestureDetector Widget来处理键盘按钮的点击事件。 3. 在需要使用自定义键盘的地方,使用Flutter的FocusNode来控制输入框的焦点,并将自定义键盘与输入框关联起来。 下面是一个简单的实现自定义键盘的示例代码: ```dart import 'package:flutter/material.dart'; class CustomKeyboard extends StatefulWidget { @override _CustomKeyboardState createState() => _CustomKeyboardState(); } class _CustomKeyboardState extends State<CustomKeyboard> { TextEditingController _textEditingController = TextEditingController(); @override Widget build(BuildContext context) { return Container( child: Column( children: [ TextField( controller: _textEditingController, focusNode: FocusNode(), decoration: InputDecoration( hintText: 'Input something', ), ), Row( children: [ CustomButton('1'), CustomButton('2'), CustomButton('3'), ], ), Row( children: [ CustomButton('4'), CustomButton('5'), CustomButton('6'), ], ), Row( children: [ CustomButton('7'), CustomButton('8'), CustomButton('9'), ], ), Row( children: [ CustomButton('0'), CustomButton('backspace'), ], ), ], ), ); } } class CustomButton extends StatelessWidget { final String text; CustomButton(this.text); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { if (text == 'backspace') { String currentText = CustomKeyboard.of(context) .controller .text; if (currentText.isNotEmpty) { CustomKeyboard.of(context) .controller .text = currentText.substring(0, currentText.length - 1); } } else { CustomKeyboard.of(context) .controller .text += text; } }, child: Container( width: 100.0, height: 80.0, decoration: BoxDecoration( border: Border.all( color: Colors.grey, ), ), child: Center( child: Text(text), ), ), ); } } class CustomKeyboardController { final TextEditingController controller; CustomKeyboardController(this.controller); void clear() { controller.clear(); } void close() { FocusScope.of(controller.context).requestFocus(FocusNode()); } } class CustomKeyboardScope extends InheritedWidget { final CustomKeyboardController controller; CustomKeyboardScope({ Key key, @required Widget child, }) : assert(child != null), controller = CustomKeyboardController(TextEditingController()), super(key: key, child: child); static CustomKeyboardController of(BuildContext context) { return (context.dependOnInheritedWidgetOfExactType<CustomKeyboardScope>()) .controller; } @override bool updateShouldNotify(CustomKeyboardScope oldWidget) { return controller != oldWidget.controller; } } ``` 在上面的示例代码中,`CustomKeyboard` Widget是自定义键盘的主Widget,它包含了一个`TextField`和一些自定义的按钮。 `CustomButton` Widget是自定义键盘中的按键,它使用`GestureDetector`来处理按钮点击事件。 `CustomKeyboardController`是自定义键盘的控制器,用于控制输入框的文本内容。 最后,使用`CustomKeyboardScope` Widget来将`CustomKeyboardController`注入到自定义键盘中。 在需要使用自定义键盘的地方,可以使用以下代码来显示自定义键盘: ```dart CustomKeyboardScope( child: CustomKeyboard(), ); ``` 同时,需要将`CustomKeyboardController`与输入框关联起来,可以使用以下代码: ```dart TextField( controller: CustomKeyboardScope.of(context).controller.textEditingController, focusNode: FocusNode(), ); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值