前言
先上效果图: 功能很简单:
- 输入标题
- 是否开启闹钟
- 选择闹钟循环样式
- 选择提醒时间
- 输入描述
- 保存
实现方式
首先实现输入标题,考虑到这个样式在开发中会经常用到,决定将这个封装下,方便后面开发使用。
封装 SSLInputRow.dart
分析:组件需要传入标题、显示样式、可选的输入内容。需要返回点击事件、输入改变事件、输入完成事件。颜色啥的由于是项目中统一定义的颜色管理,这里就没添加可传入参数,可根据需要添加。
定义如下:
kotlin
enum SSLInputStyle{
text,//输入文本
num,//输入数字
arrow;//不可输入,可点击选择
}
class SSLInputRow extends StatefulWidget{
final SSLInputStyle style;//样式
final String title;//标题
final String? inputText;//输入信息或子标题
final ValueChanged<String>? onTextChange;//输入改变
final ValueChanged<String>? onEditComplete;//输入完成事件
final int tag;
final GestureTapCallback? onTap;//arrow 类型点击事件
const SSLInputRow({
Key? key,
this.style = SSLInputStyle.text,
required this.title,
this.onTextChange,
this.callback,
this.tag = 0,
this.inputText,
this.onTap,
this.onEditComplete,
}):super(key: key);
}
具体实现:
php
class SSLInputRowState extends State <SSLInputRow>{
TextEditingController? textControl;//输入控制器
@override
void initState() {
// TODO: implement initState
//根据类型判断是否初始化输入控制器并将数据赋值
if (widget.style != SSLInputStyle.arrow){
textControl = TextEditingController();
if (widget.inputText != null){
var str = widget.inputText!;
debugPrint("set default text $str");
textControl!.text = str;//如果有已输入文本则显示已输入文本
}
}
super.initState();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Padding(
padding: const EdgeInsets.only(top: 1),
child: GestureDetector(//点击手势
child: Container(
color: sslUI.cellBackColor,
child: Flex(
direction: Axis.horizontal,
children: [
Expanded(
flex: 1,//标题和输入区占比1:1
child: Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 15),
height: 50,
child: Text(widget.title, style: TextStyle(color: sslUI.mainText),),
)
),
Expanded(
flex: widget.style == SSLInputStyle.num ? 1 : 1,
child: Container(
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 0,top: 5,bottom: 5),
height: 50,
child: showText()
)
),
styleChange(),
],
),
),
//手势点击回调
onTap: (){
if (widget.onTap != null){
widget.onTap!();
}
},
)
);
}
//判断显示类型,区分显示的组件
Widget showText(){
if (widget.style == SSLInputStyle.arrow){
if (widget.inputText != null){
return Text(widget.inputText!, style: TextStyle(color: sslUI.subText),);
}else{
return const Padding(padding: EdgeInsets.zero);
<img src="}" alt="" width="30%" />
}else{
return TextField(
controller: textControl,
readOnly: widget.style == SSLInputStyle.arrow ? true : false,
textAlign: TextAlign.right,
style: TextStyle(color: sslUI.subText),
keyboardType: widget.style == SSLInputStyle.num ? const TextInputType.numberWithOptions(signed: false, decimal: true) : TextInputType.text,
decoration: InputDecoration(
// labelText: widget.inputText,
hintText: SSLLocales.l_input_placeholder.tr + widget.title,
fillColor: sslUI.cellBackColor,
border: InputBorder.none,
// border: OutlineInputBorder(
// borderSide: BorderSide(color: sslUI.priColor, width: 1),
// ),
),
//输入变化回调
onChanged: (v){
if (widget.onTextChange != null){
widget.onTextChange!(v);
}
},
//输入完成回调
onEditingComplete: (){
if (widget.onEditComplete != null){
widget.onEditComplete!(textControl!.text);
}
},
);
}
}
根据不同风格决定返回widget
Widget styleChange(){
if (widget.style == SSLInputStyle.arrow){
return Padding(
padding: const EdgeInsets.only(right: 15),
child: Icon(Icons.arrow_forward_ios, color: sslUI.iconColor,),
);
}else{
return const Padding(padding: EdgeInsets.only(left: 15),);
}
}
@override
void dispose() {
//销毁文本输入控制器
// TODO: implement dispose
if (textControl != null){
textControl!.dispose();
}
super.dispose();
}
}