Git Product home page Git Product logo

Comments (11)

Im-Kevin avatar Im-Kevin commented on September 14, 2024

每一个页面都需要调用init的

:octocat: From gitme iOS

from cool_ui.

 avatar commented on September 14, 2024

其它页面,比如是登录页面,没有NumberKeyboard.inputType的类型,需要吗?

from cool_ui.

Im-Kevin avatar Im-Kevin commented on September 14, 2024

其他页面不用的不需要

from cool_ui.

kennenfromchina avatar kennenfromchina commented on September 14, 2024

谢谢,解决了我的问题,

from cool_ui.

kennenfromchina avatar kennenfromchina commented on September 14, 2024

复现:在NumberKeyboard.inputType的输入框输入并完成,退出页面,然后在其它页面的字符输入框中,系统键盘可以呼出,但输入任何字符,但输入框没有输入内容。

目前我的解决方法是在页面的dispose中调用以下方法,虽然能解决,但感觉不是最好的方法。
在类CoolKeyboard中增加以下方法
static dispose(){
isInterceptor = false;
BinaryMessages.setMockMessageHandler("flutter/textinput",null);
}

在引用键盘的页面调用
void dispose() {
CoolKeyboard.dispose();//销毁自定义键盘,不然其它页面输入不了
}

请大神有空看看。谢谢你及时解决上个问题(弹出键盘后返回上页后无法打开自定义键盘)

我也是自己加的这个dispose方法才解决的,不知道作者大大修复这个问题了没有,只要打开了自定义键盘的页面,如果不调用dispose这个方法,其他页面的输入框就无法输入了

from cool_ui.

oh-jy avatar oh-jy commented on September 14, 2024

复现:在NumberKeyboard.inputType的输入框输入并完成,退出页面,然后在其它页面的字符输入框中,系统键盘可以呼出,但输入任何字符,但输入框没有输入内容。

目前我的解决方法是在页面的dispose中调用以下方法,虽然能解决,但感觉不是最好的方法。
在类CoolKeyboard中增加以下方法
static dispose(){
isInterceptor = false;
BinaryMessages.setMockMessageHandler("flutter/textinput",null);
}

在引用键盘的页面调用
void dispose() {
CoolKeyboard.dispose();//销毁自定义键盘,不然其它页面输入不了
}

请大神有空看看。谢谢你及时解决上个问题(弹出键盘后返回上页后无法打开自定义键盘)

确实这样可以解决问题。不同的表单页面,父级销毁了就会报这个错。

from cool_ui.

Im-Kevin avatar Im-Kevin commented on September 14, 2024

你好,我这边无法重现这个问题

from cool_ui.

chilimyan avatar chilimyan commented on September 14, 2024

同样的问题,如果我先调用自定义键盘然后再其他页面再调用系统键盘,那么系统键盘无法输入。

from cool_ui.

Im-Kevin avatar Im-Kevin commented on September 14, 2024

能否贴个例子代码,我这边无法重现,最好录制个视频

from cool_ui.

kennenfromchina avatar kennenfromchina commented on September 14, 2024

自定义车牌号输入键盘代码:

import 'package:flutter/material.dart';
import 'package:cool_ui/cool_ui.dart';

/// 每个按钮的高度
const double kBtnHeight = 48.0;

enum CarNumberInputType {
  /// 省份
  CarNumberInputTypeProvince,

  /// 字母和数字
  CarNumberInputTypeLetterAndDigital,
}

/// 车牌号输入键盘
class CarNumberKeyboard extends StatelessWidget {
  /// 自定义inputType类型
  static const CKTextInputType inputType =
      const CKTextInputType(name: 'CarNumberKeyboard');

  /// 获取键盘高度
  static double getHeight(BuildContext ctx) {
    return kBtnHeight * 5;
  }

  /// 键盘输入控制器
  final KeyboardController controller;

  /// 构造方法
  const CarNumberKeyboard({this.controller});

  /// 注册
  static register() {
    CoolKeyboard.addKeyboard(
      CarNumberKeyboard.inputType,
      KeyboardConfig(
        builder: (context, controller) {
          return CarNumberKeyboard(
            controller: controller,
          );
        },
        getHeight: CarNumberKeyboard.getHeight,
      ),
    );
  }

  /// 自定义视图
  @override
  Widget build(BuildContext context) {
    return CarNumberInput(
      carNumberInputType: controller.text.length < 1 ? CarNumberInputType.CarNumberInputTypeProvince : CarNumberInputType.CarNumberInputTypeLetterAndDigital,
      controller: this.controller,
    );
  }
}

class CarNumberInput extends StatefulWidget {
  ///控制器
  final KeyboardController controller;

  ///类型(省份/字母||数字)
  CarNumberInputType carNumberInputType;

  /// 构造方法
  CarNumberInput({
    Key key,
    @required this.controller,
    @required this.carNumberInputType,
  }) : super(key: key);

  @override
  _CarNumberInputState createState() => _CarNumberInputState();
}

class _CarNumberInputState extends State<CarNumberInput> {
  ///省份数组
  static const List<String> _provinceList = [
    '京',
    '津',
    '晋',
    '冀',
    '蒙',
    '辽',
    '吉',
    '黑',
    '沪',
    '苏',
    '浙',
    '皖',
    '闽',
    '赣',
    '鲁',
    '豫',
    '鄂',
    '湘',
    '粤',
    '桂',
    '琼',
    '渝',
    '川',
    '贵',
    '云',
    '藏',
    '陕',
    '甘',
    '青',
    '宁',
    '新',
    '使',
    '1',
    '2',
    '3',
    'W',
    'V',
    'K',
    'H',
    'B',
    'S',
    'L',
    'J',
    'N',
    'G',
    'C',
    'E',
    'Z',
  ];

  ///数字字母数组
  static const List<String> _letterAndDigitalList = [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '0',
    'Q',
    'W',
    'E',
    'R',
    'T',
    'Y',
    'U',
    'I',
    'O',
    'P',
    'A',
    'S',
    'D',
    'F',
    'G',
    'H',
    'J',
    'K',
    'L',
    '',
    'Z',
    'X',
    'C',
    'V',
    'B',
    'N',
    'M',
    '港',
    '澳',
    '',
    '学',
    '警',
    '挂',
    '领',
    '试',
    '超',
    '练',
    '使',
  ];

  /// 更新键盘类型
  void updateType() {
    var currentText = widget.controller.text;
    print(widget.controller.text);
    setState(() {
      if (currentText.length < 1) {
        widget.carNumberInputType =
            CarNumberInputType.CarNumberInputTypeProvince;
      } else {
        widget.carNumberInputType =
            CarNumberInputType.CarNumberInputTypeLetterAndDigital;
      }
    });
  }

  ///点击事件
  void _onBtnClick(String name) {
    widget.controller.addText(name);
    updateType();
  }

  /// 删除事件
  void _onDeleteClick() {
    widget.controller.deleteOne();
    updateType();
  }

  ///键盘视图
  Widget _showKeyBoard() {
    /// 临时数组
    List<String> tempList;
    if (widget.carNumberInputType ==
        CarNumberInputType.CarNumberInputTypeProvince) {
      tempList = _provinceList;
    } else {
      tempList = _letterAndDigitalList;
    }

    /// 最终Widgets数组
    List<Widget> provinceWidgets = List();

    /// 根据临时数组构造最终数组(添加空白视图和最后删除按钮)
    for (int i = 0; i < tempList.length; i++) {
      String name = tempList[i];
      if (name.length <= 0) {
        provinceWidgets.add(Container(
          color: Color(0xFFF2F2F2),
          width: MediaQuery.of(context).size.width / 10.0,
          height: kBtnHeight,
        ));
        continue;
      }
      provinceWidgets.add(
        Material(
          child: Container(
            child: Ink(
              color: Color(0xFFF2F2F2),
              width: MediaQuery.of(context).size.width / 10.0,
              height: kBtnHeight,
              child: Padding(
                padding: EdgeInsets.all(4.0),
                child: InkWell(
                  onTap: () => _onBtnClick(tempList[i]),
                  child: Ink(
                    decoration: name.length > 0
                        ? BoxDecoration(
                            color: Color(0xFFFFFFFF),
                            borderRadius: BorderRadius.circular(4.0),
                            border: Border.all(
                              color: Color(0xFFE4E4E4),
                              width: 1.0,
                            ),
                          )
                        : null,
                    child: Center(
                      child: Text(
                        name,
                        style: TextStyle(
                          fontSize: 17,
                          color: Color(0xFF333333),
                        ),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      );
    }

    ///删除按钮
    provinceWidgets.add(Material(
      child: Container(
        child: Ink(
          color: Color(0xFFF2F2F2),
          width: MediaQuery.of(context).size.width / 5.0,
          height: kBtnHeight,
          child: Padding(
            padding: EdgeInsets.all(4.0),
            child: InkWell(
              onTap: widget.controller.text.length > 0
                  ? () {
                      _onDeleteClick();
                    }
                  : null,
              child: Ink(
                decoration: BoxDecoration(
                  color: Color(0xFFFFFFFF),
                  borderRadius: BorderRadius.circular(4.0),
                  border: Border.all(
                    color: Color(0xFFE4E4E4),
                    width: 1.0,
                  ),
                ),
                child: Center(
                  child: Icon(
                    Icons.backspace,
                    color: widget.controller.text.length > 0
                        ? Color(0xFF333333)
                        : Color(0xFF999999),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    ));

    // TODO:解决wrap不能自动换行的临时方案
    List<Widget> temp = List<Widget>();
    for (int i = 0; i < 5; i++) {
      List<Widget> rowList = List<Widget>();
      for (int j = 0; j < 10; j++) {
        if (i == 4 && j > 8) continue;
        int index = i * 10 + j;
        Widget focus = provinceWidgets[index];
        rowList.add(focus);
      }
      temp.add(Row(
        children: rowList,
      ));
    }
//    /*
    return Column(
      children: <Widget>[
        temp[0],
        temp[1],
        temp[2],
        temp[3],
        temp[4],
      ],
    );
//    */
    /*
    return Wrap(
      children: provinceWidgets,
    );
    */
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Container(
        height: kBtnHeight * 5,
        alignment: Alignment.bottomCenter,
        child: _showKeyBoard(),
      ),
    );
  }
}

使用自定义键盘代码:

/**
 * PROJECT_NAM: driver_custom
 * PACKAGE_NAME: HomePage.StoreService
 * NAME: order_dialog
 * Describe:
 *
 * Created by kennen on 2019-06-11.
 * Copyright (c) 2019 Zhilun (Hangzhou) Technology Co., Ltd. All rights reserved.
 */

import 'package:flutter/material.dart';
import 'package:driver_custom/utils/CarNumberKeyboard.dart';
import 'package:cool_ui/cool_ui.dart';
import 'package:driver_custom/common/colours.dart';
import 'package:driver_custom/utils/utils.dart';

typedef void CallBack(Map<String, dynamic> result);

Future showOrderDialog(
  BuildContext context, {
  @required CallBack callBack,
  bool needVCCode = false,
  String phone,
  String vcCode,
  String carNumber,
  String name,
  String remark,
}) async {
  if (phone == null) {
    phone = await UserUtil.getUserTelephone();
  }
  var result = await showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return OrderDialog(
        needVCCode: needVCCode,
        phone: phone,
        vcCode: vcCode,
        carNumber: carNumber,
        name: name,
        remark: remark,
      );
    },
  );
  if (callBack != null && result != null) {
    callBack(result);
  }
}

class OrderDialog extends StatefulWidget {
  final bool needVCCode;
  final String phone;
  final String vcCode;
  final String carNumber;
  final String name;
  final String remark;

  OrderDialog({
    Key key,
    this.needVCCode,
    this.phone,
    this.vcCode,
    this.carNumber,
    this.name,
    this.remark,
  }) : super(key: key);

  @override
  _OrderDialogState createState() => _OrderDialogState();
}

class _OrderDialogState extends State<OrderDialog> {
  TextEditingController phoneController;
  TextEditingController vcCodeController;
  TextEditingController carNumberController;
  TextEditingController nameController;
  TextEditingController remarkController;

  @override
  void dispose() {
    phoneController.dispose();
    vcCodeController.dispose();
    carNumberController.dispose();
    nameController.dispose();
    remarkController.dispose();
    CoolKeyboard.clearKeyboard();
    //MARK: 销毁自定义键盘,不然其它页面输入不了
    CoolKeyboard.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    phoneController = TextEditingController(text: widget.phone);
    phoneController.selection = TextSelection.fromPosition(
        TextPosition(offset: phoneController.text.length));

    vcCodeController = TextEditingController(text: widget.vcCode);
    carNumberController = TextEditingController(text: widget.carNumber);
    nameController = TextEditingController(text: widget.name);
    remarkController = TextEditingController(text: widget.remark);
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardMediaQuery(
      child: Builder(builder: (BuildContext context) {
        CoolKeyboard.init(context);
        return Center(
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: 4.0),
            width: MediaQuery.of(context).size.width - 32.0,
            height: MediaQuery.of(context).size.width - 32.0,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(4.0),
            ),
            child: Material(
              child: Column(
                children: <Widget>[
                  Expanded(
                    child: _buildListView(),
                  ),
                  _buildFooter(),
                ],
              ),
            ),
          ),
        );
      }),
    );
  }

  Widget _buildListView() {
    List<Widget> children = [];
    children.add(
      _buildItem(
        title: '手机:',
        placeholder: '请填写您的手机号码',
        isVCCode: false,
        keyboardType: TextInputType.phone,
        controller: phoneController,
      ),
    );
    if (widget.needVCCode) {
      children.add(
        _buildItem(
          title: '验证码:',
          placeholder: null,
          isVCCode: true,
          keyboardType: TextInputType.number,
          controller: vcCodeController,
        ),
      );
    }
    children.add(
      _buildItem(
        title: '车牌:',
        placeholder: '请填写您的车牌',
        isVCCode: false,
        keyboardType: CarNumberKeyboard.inputType,
        controller: carNumberController,
      ),
    );
    children.add(
      _buildItem(
        title: '姓名:',
        placeholder: '请填写您的姓名(选填)',
        isVCCode: false,
        controller: nameController,
      ),
    );
    children.add(
      _buildItem(
        title: null,
        placeholder: null,
        isVCCode: false,
        controller: remarkController,
      ),
    );
    return ListView(
      children: children,
    );
  }

  Widget _buildItem({
    @required String title,
    @required String placeholder,
    @required bool isVCCode,
    TextInputType keyboardType,
    @required TextEditingController controller,
  }) {
    int maxLines = 1;
    if (title == null) {
      maxLines = 3;
      placeholder = '请填写备注(选填)';
      keyboardType = TextInputType.text;
    } else if (isVCCode) {
      placeholder = '请填写您的验证码';
      keyboardType = TextInputType.number;
    }
    TextField textField = TextField(
      controller: controller,
      keyboardType: keyboardType,
      maxLines: maxLines,
      maxLength: title == "手机:" ? 11 : (title == "车牌:" ? 8 : 50),
      decoration: InputDecoration(
        hintText: placeholder,
        border: InputBorder.none,
        counterText: title == null ? "50" : "",
      ),
      style: TextStyle(
        fontSize: 14.0,
        color: Colours.text_color,
      ),
//      onChanged: (String res) {
//        if (controller == phoneController) {
//          if (res.trim().length > 11) {
//            controller.text = controller.text.substring(0, 11);
//          }
//        } else if (controller == carNumberController ||
//            controller == nameController ||
//            controller == vcCodeController) {
//          if (res.trim().length > 10) {
//            controller.text = controller.text.substring(0, 10);
//          }
//        }
//      },
    );
    List<Widget> children = [];
    if (title != null) {
      children.add(Container(
        width: 60.0,
        child: Text(
          title,
          style: TextStyle(
            fontSize: 14.0,
            color: Colours.title_color,
            decoration: TextDecoration.none,
          ),
        ),
      ));
    }
    children.add(Expanded(child: textField));
    if (isVCCode) {
      children.add(
        Container(
          width: 100.0,
          height: 32.0,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(4.0),
            border: Border.all(color: Colours.border_color, width: 1.0),
          ),
          child: Center(
            child: Text(
              '获取验证码',
              style: TextStyle(fontSize: 14.0, color: Colours.text_color),
            ),
          ),
        ),
      );
    }
    return Container(
      height: title != null ? 48.0 : null,
      padding: EdgeInsets.symmetric(horizontal: 12.0),
      decoration: title != null
          ? UnderlineTabIndicator(
              borderSide: BorderSide(color: Colours.border_color, width: 1.0))
          : null,
      child: Row(
        children: children,
      ),
    );
  }

  Widget _buildFooter() {
    return Row(
      children: <Widget>[
        Expanded(
          child: FlatButton(
            padding: null,
            onPressed: () {
              Navigator.pop(context);
            },
            child: Text(
              '取消',
              style: TextStyle(
                fontSize: 14.0,
                color: Colours.title_color,
                decoration: TextDecoration.none,
              ),
            ),
          ),
        ),
        Expanded(
          child: FlatButton(
            padding: null,
            onPressed: () {
              _checkData();
            },
            child: Text(
              '确认下单',
              style: TextStyle(
                fontSize: 14.0,
                color: Colours.title_color,
                decoration: TextDecoration.none,
              ),
            ),
          ),
        ),
      ],
    );
  }

  /// 校验数据
  void _checkData() async {
    if (!RegexUtil.isMobileSimple(phoneController.text.trim())) {
      showCenterToast('请输入正确的手机号');
      return;
    }
    if (!RegexUtil.isCarNumber(carNumberController.text.trim())) {
      showCenterToast('请输入正确的车牌号');
      return;
    }

    Map<String, String> result = {};
    result['phone'] = phoneController.text.trim() ?? null;
    result['vcCode'] = vcCodeController.text.trim() ?? null;
    result['carNumber'] = carNumberController.text.trim() ?? null;
    result['name'] = nameController.text.trim() ?? null;
    result['remark'] = remarkController.text.trim() ?? null;
    print(result.toString());
    Navigator.pop(context, result);
  }
}

其它页面正常使用TextField,就会出现无法输入的bug。

复现bug视频链接

from cool_ui.

Im-Kevin avatar Im-Kevin commented on September 14, 2024

问题已修复

from cool_ui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.