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();
  }
}
相关推荐
2501_9160074713 小时前
iOS 压力测试的工程化体系,构建高强度、多维度、跨工具协同的真实负载测试流程
android·ios·小程序·uni-app·cocoa·压力测试·iphone
2501_9160088915 小时前
API接口调试全攻略 Fiddler抓包工具、HTTPS配置与代理设置实战指南
前端·ios·小程序·https·fiddler·uni-app·webview
2501_9159214316 小时前
iOS 开发者工具推荐,构建从调试到性能优化的多维度生产力工具链(2025 深度工程向)
android·ios·性能优化·小程序·uni-app·iphone·webview
00后程序员张18 小时前
全面解析网络抓包工具使用:Wireshark和TCPDUMP教程
网络·ios·小程序·uni-app·wireshark·iphone·tcpdump
游戏开发爱好者819 小时前
Mac 抓包软件怎么选?从 HTTPS 调试、TCP 数据流分析到多工具协同的完整抓包方案
tcp/ip·macos·ios·小程序·https·uni-app·iphone
马拉萨的春天20 小时前
iOS中广告SDK如何判断一个广告是否真实展示
macos·ios·cocoa
ajassi200021 小时前
开源 Objective-C IOS 应用开发(十九)视频的播放
ios·开源·objective-c
苦逼的搬砖工21 小时前
基于 easy_rxdart 的轻量响应式与状态管理架构实践
android·flutter
2501_9159184121 小时前
苹果上架 iOS 应用的工程实践,一次从零到上线的完整记录
android·ios·小程序·https·uni-app·iphone·webview