-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NumberKeyboard.inputType的输入框切换到其它无法输入 #14
Comments
每一个页面都需要调用init的 |
其它页面,比如是登录页面,没有NumberKeyboard.inputType的类型,需要吗? |
其他页面不用的不需要 |
谢谢,解决了我的问题, |
我也是自己加的这个dispose方法才解决的,不知道作者大大修复这个问题了没有,只要打开了自定义键盘的页面,如果不调用dispose这个方法,其他页面的输入框就无法输入了 |
确实这样可以解决问题。不同的表单页面,父级销毁了就会报这个错。 |
你好,我这边无法重现这个问题 |
同样的问题,如果我先调用自定义键盘然后再其他页面再调用系统键盘,那么系统键盘无法输入。 |
能否贴个例子代码,我这边无法重现,最好录制个视频 |
自定义车牌号输入键盘代码: 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。 |
问题已修复 |
复现:在NumberKeyboard.inputType的输入框输入并完成,退出页面,然后在其它页面的字符输入框中,系统键盘可以呼出,但输入任何字符,但输入框没有输入内容。
目前我的解决方法是在页面的dispose中调用以下方法,虽然能解决,但感觉不是最好的方法。
在类CoolKeyboard中增加以下方法
static dispose(){
isInterceptor = false;
BinaryMessages.setMockMessageHandler("flutter/textinput",null);
}
在引用键盘的页面调用
void dispose() {
CoolKeyboard.dispose();//销毁自定义键盘,不然其它页面输入不了
}
请大神有空看看。谢谢你及时解决上个问题(弹出键盘后返回上页后无法打开自定义键盘)
The text was updated successfully, but these errors were encountered: