简介
文本输入框,这个是不可避免需要使用的。比如像这样的搜索框

组件选择
-
一种是安卓风格的
TextField
-
另外一种是
iOS
风格的CupertinoTextField
一开始因为熟悉,我们选择了CupertinoTextField
,并且有输入内容的时候会自动显示删除按钮,非常方便。只是后来,UI要求删除按钮的图标要换,没有办法,只能换成TextField
属性设置
-
由于需要更新状态,所以选择了
StatefulWidget
;一开始的想法是引入GetX
,不过后来想想,将GetX
引入组件不大合适 -
TextEditingController
肯定要一个的。如果外部给了,那么就用外部的;如果没有,内部自己生成一个。
/// 初始化控制器
_controller = widget.controller ?? TextEditingController();
-
FocusNode
内部自己生产一个,需要监控焦点。得到焦点显示删除按钮,失去焦点隐藏删除按钮。
/// 焦点监控
_focusNode.addListener(() {
LogUtil.log("Has focus: ${_focusNode.hasFocus}");
setState(() {
if (_focusNode.hasFocus) {
_isShowDelete = true;
} else {
_isShowDelete = false;
}
});
});
-
由于图标和输入区的间距也有要求,所以
prefix
和suffix
等属性都不用,直接放入一个Row
之中进行自定义。 -
由于
TextField
的属性实在太多,所以根据UI给的样式设置一个,其他的属性全部屏蔽,减少使用难度。 -
对外提供只需要以下几个必要的参数就可以了,其他的样式内部写死就可以了。
TextField
属性太多,使用起来很不方便,在一个地方封装一下就可以了。
final TextEditingController? controller;
final String? placeholder;
final void Function(String)? onChanged;
final void Function(String)? onSubmitted;
参考代码
不能copy使用,仅能做参考
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:pandabuy/r.dart';
import 'package:pandabuy/theme/panda_color_config.dart';
import 'package:pandabuy/utils/log_util.dart';
class SearchWidget extends StatefulWidget {
const SearchWidget({
Key? key,
this.controller,
this.placeholder,
this.onChanged,
this.onSubmitted,
}) : super(key: key);
final TextEditingController? controller;
final String? placeholder;
final void Function(String)? onChanged;
final void Function(String)? onSubmitted;
@override
State<SearchWidget> createState() => SearchWidgetState();
}
class SearchWidgetState extends State<SearchWidget> {
late TextEditingController _controller;
final _focusNode = FocusNode();
bool _isShowDelete = false;
@override
void initState() {
super.initState();
/// 初始化控制器
_controller = widget.controller ?? TextEditingController();
/// 焦点监控
_focusNode.addListener(() {
LogUtil.log("Has focus: ${_focusNode.hasFocus}");
setState(() {
if (_focusNode.hasFocus) {
_isShowDelete = true;
} else {
_isShowDelete = false;
}
});
});
}
@override
void dispose() {
/// 销毁控制器
_focusNode.dispose();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
height: 32.h,
margin: EdgeInsets.only(left: 5.w),
decoration: BoxDecoration(
color: PandaColorConfig().backgroundF5F5F5,
borderRadius: BorderRadius.circular(16.h),
),
child: Row(
children: [
Container(
margin: EdgeInsets.only(left: 15.w, right: 5.w),
child: Image.asset(
R.assetsImg44Search,
width: 18,
height: 18,
fit: BoxFit.contain,
),
),
Expanded(
child: Center(
child: TextField(
controller: _controller,
focusNode: _focusNode,
cursorColor: PandaColorConfig().background11BA66Both,
textInputAction: TextInputAction.search,
style: TextStyle(
color: PandaColorConfig().text333333,
fontSize: 14.sp,
fontWeight: FontWeight.w400,
),
decoration: InputDecoration(
border: InputBorder.none,
hintText: widget.placeholder ?? 'Name/OrderNo./ItemNo.'.tr,
hintStyle: TextStyle(
color: PandaColorConfig().text999999,
fontSize: 14.sp,
fontWeight: FontWeight.w400,
),
isCollapsed: true,
),
onChanged: widget.onChanged,
onSubmitted: widget.onSubmitted,
),
),
),
Visibility(
visible: _isShowDelete,
child: GestureDetector(
onTap: () {
setState(() {
_controller.clear();
});
},
child: Container(
margin: EdgeInsets.only(left: 5.w, right: 15.w),
child: Image.asset(
R.assetsImgTagDelete,
width: 12,
height: 12,
fit: BoxFit.contain,
),
),
),
),
],
),
);
}
}
网友评论