Flutter 日记APP-添加笔记本-常用组件封装

前言

先上效果图: 功能很简单:

  1. 输入标题
  2. 是否开启闹钟
  3. 选择闹钟循环样式
  4. 选择提醒时间
  5. 输入描述
  6. 保存

实现方式

首先实现输入标题,考虑到这个样式在开发中会经常用到,决定将这个封装下,方便后面开发使用。

封装 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();
  }
}
相关推荐
事圆则缓1 小时前
从零搭建一套 Flutter 架构:先跑通数据流
flutter
承渊政道2 小时前
iOS远程控制电脑用什么好?iPhoneiPad远程控制Windows电脑最佳方案2026横评
windows·ios·远程控制·1024程序员节·iphone ipad
茶底世界之下2 小时前
彩色建筑适合转黑白吗?用 Awaking 检查颜色消失后的层次
ios
黑科技iOS上架3 小时前
App Store 26年10月新应用审核放缓大量应用不进审
ios·审核
OxYGC4 小时前
手机为什么能“自动跳过“开屏广告?李跳跳、GKD 与 iOS 代理软件原理盘点
android·ios·开屏广告·广告屏蔽
终端安全笔记15 小时前
一份配置管十项 AI 功能:它关的是入口,不是数据
网络安全·ios·移动设备管理
程序员老刘18 小时前
Flutter版本选择指南:3.44稳定了11周正式转正 | 2026年10月
flutter·ai编程·客户端
2501_9151063220 小时前
跨平台抓包工具怎么选?TraceEagle抓包鹰 的四种跨平台能力
网络协议·计算机网络·网络安全·ios·adb·https·udp
黑科技iOS上架1 天前
iOS应用上架:提前规避审核被拒风险
ios·审核
chicken_h1 天前
【无标题】
flutter·打包