阅读视图

发现新文章,点击刷新页面。

Flutter输入框TextField的属性与实战用法全面解析+示例

在 Flutter 开发中,输入框是与用户交互的核心组件之一,无论是登录注册、搜索框还是表单填写,都离不开 TextField 或其封装组件 TextFormField。本文将详细介绍输入框的核心属性常用功能实战用法,预计阅读时间5分钟,下面开始吧~

1. 基础概念

Flutter 提供了两个主要的输入框组件:

  • TextField:基础输入框组件,提供基本的文本输入功能。
  • TextFormField:继承自 TextField,增加了表单验证、自动保存等功能,适合在 Form 组件中使用。

两者核心属性基本一致,本文以 TextField 为例讲解,差异部分会单独说明。

2. 核心属性详解

核心属性的详解,我会按照分类归纳,如下:

2.1. 基本配置

属性名 类型 说明
controller TextEditingController 控制输入框文本(获取、设置、监听文本变化)
keyboardType TextInputType 键盘类型(如数字、邮箱、手机号等)
textInputAction TextInputAction 键盘动作按钮(如完成、下一步、搜索)
obscureText bool 是否隐藏输入内容(密码框常用)
maxLines int 最大行数(单行输入设为 1,多行设为 null 或更大值)
minLines int 最小行数
maxLength int 最大输入长度(会显示计数器)
maxLengthEnforcement MaxLengthEnforcement 超出长度时的处理方式(截断/禁止输入)
scrollPhysics ScrollPhysics 输入框内容滚动时的物理效果(如禁止滚动、总是可滚动等)
textCapitalization TextCapitalization 自动大写规则(如句子首字母大写、所有字母大写等)

示例:基础配置

TextField(
  controller: _controller, // 绑定控制器
  keyboardType: TextInputType.number, // 数字键盘
  textInputAction: TextInputAction.done, // 键盘按钮为"完成"
  obscureText: false, // 不隐藏文本
  maxLines: 1, // 单行输入
  maxLength: 11, // 最大长度11(如手机号)
  // 多行输入时禁止滚动(内容超出时也不滚动)
  scrollPhysics: NeverScrollableScrollPhysics(),
  // 句子首字母自动大写(适合英文输入)
  textCapitalization: TextCapitalization.sentences,
  略......
)

2.2. 样式配置

属性名 类型 说明
style TextStyle 输入文本的样式(字体、大小、颜色等)
decoration InputDecoration 输入框装饰(边框、提示文本、图标等)
cursorColor Color 光标颜色
cursorWidth double 光标宽度
cursorHeight double 光标高度
textAlign TextAlign 文本对齐方式(左、中、右)
textDirection TextDirection 文本方向(从左到右/从右到左)
strutStyle StrutStyle 控制文本的基线对齐(解决不同字体大小导致的对齐问题)
toolbarOptions ToolbarOptions 长按文本时显示的工具栏选项(如复制、粘贴、剪切)
selectionControls TextSelectionControls 自定义文本选择控件(如替换系统默认的复制粘贴工具栏)

示例:自定义样式

TextField(
  style: TextStyle(
    fontSize: 16,
    color: Colors.black87,
  ),
  cursorColor: Colors.blue,
  cursorWidth: 2,
  textAlign: TextAlign.start,
  decoration: InputDecoration(
    hintText: "请输入用户名", // 提示文本
    hintStyle: TextStyle(color: Colors.grey), // 提示文本样式
    prefixIcon: Icon(Icons.person), // 左侧图标
    border: OutlineInputBorder( // 边框样式
      borderRadius: BorderRadius.circular(8),
    ),
    contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), // 内边距
  ),
  // 仅允许复制和粘贴操作(禁用剪切)
  toolbarOptions: ToolbarOptions(
    copy: true,
    paste: true,
    cut: false,
  ),
  // 自定义选择控件(需实现TextSelectionControls)
  // selectionControls: CustomSelectionControls(),
  略......
)

2.3. 交互控制

属性名 类型 说明
enabled bool 是否启用输入框(false 时禁用,不可输入)
readOnly bool 是否只读(可点击但不可编辑,区别于禁用)
autofocus bool 是否自动获取焦点
focusNode FocusNode 焦点控制器(手动管理焦点状态)
onChanged Function(String) 文本变化时触发(实时监听输入)
onSubmitted Function(String) 点击键盘动作按钮时触发(如点击"完成")
onTap Function() 点击输入框时触发
inputFormatters List<TextInputFormatter> 输入格式化(限制输入内容,如只允许数字)
onEditingComplete VoidCallback 编辑完成时触发(区别于onSubmitted,不接收文本参数)
onAppPrivateCommand Function(String, Map<String, dynamic>) 处理私有命令(通常用于原生与Flutter交互时传递指令)
enableIMEPersonalizedLearning bool 是否允许输入法个性化学习输入内容(默认true)

示例:

TextField(
  enabled: true, // 启用输入
  readOnly: false, // 可编辑
  autofocus: true, // 自动聚焦
  onChanged: (value) {
    print("输入变化:$value"); // 实时监听
  },
  onSubmitted: (value) {
    print("提交内容:$value"); // 点击完成时触发
  },
  // 编辑完成时触发(如手动调用_controller.text后)
  onEditingComplete: () {
    print("编辑已完成");
    // 通常配合焦点管理,如切换到下一个输入框
    FocusScope.of(context).nextFocus();
  },
  // 禁用输入法个性化学习(适用于敏感输入场景)
  enableIMEPersonalizedLearning: false,
  inputFormatters: [
    FilteringTextInputFormatter.digitsOnly, // 只允许输入数字
  ],
  略......
)

焦点管理

FocusNode 用于手动控制输入框的焦点状态,常见场景包括:切换输入框焦点、监听焦点变化、强制获取/失去焦点等。

示例:

// 1. 初始化焦点节点
final FocusNode _usernameFocus = FocusNode();
final FocusNode _passwordFocus = FocusNode();

@override
void dispose() {
  // 销毁焦点节点(避免内存泄漏)
  _usernameFocus.dispose();
  _passwordFocus.dispose();
  super.dispose();
}

// 2. 监听焦点变化
void initState() {
  super.initState();
  _usernameFocus.addListener(() {
    if (_usernameFocus.hasFocus) {
      print("用户名输入框获取焦点");
    } else {
      print("用户名输入框失去焦点");
    }
  });
}

// 3. 组件中使用
Column(
  children: [
    TextField(
      focusNode: _usernameFocus,
      decoration: InputDecoration(hintText: "用户名"),
      textInputAction: TextInputAction.next, // 键盘显示"下一步"
      onSubmitted: (_) {
        // 点击下一步时,将焦点切换到密码框
        FocusScope.of(context).requestFocus(_passwordFocus);
      },
    ),
    TextField(
      focusNode: _passwordFocus,
      decoration: InputDecoration(hintText: "密码"),
      obscureText: true,
    ),
    ElevatedButton(
      onPressed: () {
        // 手动让密码框获取焦点
        FocusScope.of(context).requestFocus(_passwordFocus);
        // 或手动失去所有焦点(收起键盘)
        // FocusScope.of(context).unfocus();
      },
      child: Text("操作焦点"),
    ),
  ],
)

2.4. 其他实用属性

属性名 类型 说明
autocorrect bool 是否启用自动纠错(默认 true)
autocompleteMode AutocompleteMode 自动完成模式(如关闭、用户名、邮箱等)
scrollPadding EdgeInsets 滚动时的内边距(避免被键盘遮挡)
enableInteractiveSelection bool 是否允许长按选中文本(默认 true)
mouseCursor MouseCursor 鼠标悬停时的光标样式(桌面端开发常用)
clipBehavior Clip 内容超出输入框时的裁剪方式(如Clip.none不裁剪)
restorationId String 用于状态恢复(配合RestorationMixin保存/恢复输入状态)
scribbleEnabled bool 是否启用手写输入(iPad等支持Apple Pencil的设备)
TextField(
  // 桌面端鼠标悬停时显示文本输入光标
  mouseCursor: SystemMouseCursors.text,
  // 内容超出时不裁剪(可能导致UI溢出,谨慎使用)
  clipBehavior: Clip.none,
  // 启用手写输入(iPad场景)
  scribbleEnabled: true,
  略......
)

3. 控制器TextEditingController的使用

TextEditingController 是控制输入框文本的核心工具,主要功能包括:

3.1. 获取输入文本

// 初始化控制器
final TextEditingController _controller = TextEditingController();

// 获取文本(通常在按钮点击等事件中调用)
ElevatedButton(
  onPressed: () {
    String inputText = _controller.text;
    print("用户输入:$inputText");
  },
  child: Text("获取输入"),
)

// 组件中绑定
TextField(controller: _controller)

3.2. 设置文本内容

ElevatedButton(
  onPressed: () {
    // 直接设置文本
    _controller.text = "默认文本";
  },
  child: Text("设置默认值"),
)

3.3. 清空文本

ElevatedButton(
  onPressed: () {
    // 清空输入框
    _controller.clear();
  },
  child: Text("清空输入"),
)

3.4. 监听文本变化

@override
void initState() {
  super.initState();
  // 监听文本变化(实时响应输入)
  _controller.addListener(() {
    String currentText = _controller.text;
    print("当前输入:$currentText");
    // 可在这里实现实时验证,如输入长度判断
    if (currentText.length > 5) {
      print("输入长度超过5个字符");
    }
  });
}

@override
void dispose() {
  // 销毁控制器(必须调用,避免内存泄漏)
  _controller.dispose();
  super.dispose();
}

3.5. 控制光标位置

ElevatedButton(
  onPressed: () {
    // 将光标移动到文本末尾
    _controller.selection = TextSelection.fromPosition(
      TextPosition(offset: _controller.text.length),
    );
  },
  child: Text("光标移至末尾"),
)

4. TextFormField与表单验证

TextFormField 用于 Form 组件中,支持表单验证,核心属性增加了 validator,例子如下:

Form(
  key: _formKey, // 表单key,用于触发验证
  child: Column(
    children: [
      TextFormField(
        decoration: InputDecoration(hintText: "请输入邮箱"),
        keyboardType: TextInputType.emailAddress,
        // 验证逻辑
        validator: (value) {
          if (value == null || value.isEmpty) {
            return "请输入邮箱";
          }
          if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
            return "请输入正确的邮箱格式";
          }
          return null; // 验证通过
        },
      ),
      ElevatedButton(
        onPressed: () {
          // 触发表单验证
          if (_formKey.currentState!.validate()) {
            // 验证通过,执行提交逻辑
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text("提交成功")),
            );
          }
        },
        child: Text("提交"),
      ),
    ],
  ),
)

5. 实战技巧

  1. 解决键盘遮挡问题

    • Scaffold 中设置 resizeToAvoidBottomInset: true(默认值),键盘弹出时自动调整布局。
    • 结合 SingleChildScrollView 等滑动组件包裹起来,使页面可滚动。
    • 解决键盘弹出会遮挡输入框的问题,可以参考我之前的文章:传送门
  2. 自定义输入框样式

    • 通过 InputDecorationborderfocusedBorderenabledBorder 区分不同状态的边框样式。
    • 示例:聚焦时显示蓝色边框,未聚焦时显示灰色边框。
  3. 密码框切换显示/隐藏

   bool _obscureText = true;

   TextField(
     obscureText: _obscureText,
     decoration: InputDecoration(
       suffixIcon: IconButton(
         icon: Icon(
           _obscureText ? Icons.visibility : Icons.visibility_off,
         ),
         onPressed: () {
           setState(() {
             _obscureText = !_obscureText;
           });
         },
       ),
     ),
   )
  1. 限制输入类型
    • 使用 inputFormatters 配合 FilteringTextInputFormatter 限制输入(如数字、字母、禁止表情等)。

6. 总结

TextFieldTextFormField 是 Flutter 中处理文本输入的核心组件,通过 TextEditingController 可灵活控制文本内容,通过 FocusNode 可精准管理焦点状态。掌握输入框的样式定制、文本控制、焦点管理和表单验证,能显著提升用户体验。实际开发中,需注意控制器和焦点节点的生命周期管理(及时销毁,避免内存泄漏),并根据具体场景选择合适的组件配置。


本次分享就到这儿啦,我是鹏多多,深耕前端的技术创作者,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

PS:在本页按F12,在console中输入document.getElementsByClassName('panel-btn')[0].click();有惊喜哦~

往期文章

Flutter自定义日历table_calendar完全指南+案例

1. 简介

table_calendar 是 Flutter 生态中功能强大的日历组件,支持多种视图切换、事件标记、日期范围选择等核心功能,适合需集成日历功能的应用场景(如日程管理、预约系统等)。其高度可定制化的特性使其能适配不同的 UI 需求。

2. 基础配置

安装

dependencies:
  table_calendar: ^3.0.1  # 请使用最新版本

最简实现

import 'package:table_calendar/table_calendar.dart';

TableCalendar(
  firstDay: DateTime(2020),
  lastDay: DateTime(2030),
  focusedDay: DateTime.now(),
  selectedDayPredicate: (day) {
    return isSameDay(_selectedDay, day);
  },
  onDaySelected: (selectedDay, focusedDay) {
    setState(() {
      _selectedDay = selectedDay;
      _focusedDay = focusedDay;
    });
  },
)

核心参数说明:

  • firstDay/lastDay:日历显示范围(必传)
  • focusedDay:当前聚焦的日期(控制滚动位置,必传)
  • selectedDayPredicate:判断日期是否被选中的条件
  • onDaySelected:日期选择回调(返回选中日期和新聚焦日期)

3. 核心属性全解析

3.1. 核心基础属性

属性名 类型 说明
firstDay DateTime 日历显示的起始日期(必传)
lastDay DateTime 日历显示的结束日期(必传)
focusedDay DateTime 当前聚焦的日期(必传,控制日历滚动位置)
selectedDayPredicate bool Function(DateTime) 判断日期是否被选中的条件
onDaySelected void Function(DateTime, DateTime) 单个日期选中回调(选中日期+聚焦日期)
onPageChanged void Function(DateTime) 日历页面切换时回调(返回新聚焦日期)

3.2. 视图控制属性

属性名 类型 说明
calendarFormat CalendarFormat 日历展示格式(month/week/twoWeeks)
onFormatChanged void Function(CalendarFormat) 视图格式切换回调
availableCalendarFormats Map<CalendarFormat, String> 允许的视图格式及对应显示文本
pageJumpingEnabled bool 是否允许点击表头月份快速跳转页面(默认true)
weekNumbersVisible bool 是否显示周数(默认false)
weekNumberStyle TextStyle 周数文本样式

示例:

TableCalendar(
  // ...基础参数
  calendarFormat: _calendarFormat,
  onFormatChanged: (format) {
    setState(() {
      _calendarFormat = format;
    });
  },
  availableCalendarFormats: {
    CalendarFormat.month: '月',
    CalendarFormat.week: '周',
    CalendarFormat.twoWeeks: '两周',
  },
)

3.3. 范围选择属性

属性名 类型 说明
rangeStartDay DateTime? 范围选择的起始日期
rangeEndDay DateTime? 范围选择的结束日期
rangeSelectionMode RangeSelectionMode 范围选择模式(toggledOff/toggledOn/forced)
onRangeSelected void Function(DateTime?, DateTime?, DateTime) 范围选择回调(起始/结束/聚焦日期)
rangeDayPredicate bool Function(DateTime) 判断日期是否允许被纳入范围选择

示例:

RangeSelectionMode _rangeSelectionMode = RangeSelectionMode.toggledOff;
DateTime? _rangeStart;
DateTime? _rangeEnd;

TableCalendar(
  // ...基础参数
  rangeStartDay: _rangeStart,
  rangeEndDay: _rangeEnd,
  rangeSelectionMode: _rangeSelectionMode,
  onRangeSelected: (start, end, focusedDay) {
    setState(() {
      _rangeStart = start;
      _rangeEnd = end;
      _rangeSelectionMode = RangeSelectionMode.toggledOn;
      _selectedDay = null;  // 清除单个选中
    });
  },
)

3.4. 事件与标记属性

属性名 类型 说明
eventLoader List<Object> Function(DateTime) 加载指定日期的事件数据
calendarBuilders CalendarBuilders 自定义日历元素构建器(标记/日期等)
holidayLoader List<Object> Function(DateTime) 加载指定日期的假日数据
eventFadeTransitionEnabled bool 事件标记是否启用淡入动画(默认true)

示例:

// 定义事件数据结构
final Map<DateTime, List> _events = {
  DateTime(2023, 10, 15): ['会议', '生日'],
  DateTime(2023, 10, 20): ['deadline'],
};

TableCalendar(
  // ...其他参数
  eventLoader: (day) {
    return _events[day] ?? [];
  },
  calendarBuilders: CalendarBuilders(
    markerBuilder: (context, date, events) {
      if (events.isEmpty) return SizedBox();
      return Positioned(
        bottom: 1,
        child: Container(
          width: 16,
          height: 4,
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(2),
          ),
        ),
      );
    },
  ),
)

3.5. 样式定制属性

属性名 类型 说明
calendarStyle CalendarStyle 日历主体样式配置
headerStyle HeaderStyle 表头(月份栏)样式配置
daysOfWeekStyle DaysOfWeekStyle 星期标题样式配置
rowHeight double 日历行高(影响整体高度)
columnWidth double? 日历列宽(null时自动计算)
padding EdgeInsets 日历内边距
margin EdgeInsets 日历外边距
clipBehavior Clip 裁剪行为(默认Clip.hardEdge)

CalendarStyle 子属性

属性名 类型 说明
defaultTextStyle TextStyle 默认日期文本样式
selectedTextStyle TextStyle 选中日期文本样式
todayTextStyle TextStyle 今天日期文本样式
weekendTextStyle TextStyle 周末日期文本样式
outsideTextStyle TextStyle 显示范围外日期文本样式
disabledTextStyle TextStyle 禁用日期文本样式
selectedDecoration Decoration 选中日期装饰(背景等)
todayDecoration Decoration 今天日期装饰
defaultDecoration Decoration 默认日期装饰
weekendDecoration Decoration 周末日期装饰
outsideDecoration Decoration 范围外日期装饰
disabledDecoration Decoration 禁用日期装饰
rangeStartDecoration Decoration 范围选择起始日期装饰
rangeEndDecoration Decoration 范围选择结束日期装饰
rangeMiddleDecoration Decoration 范围选择中间日期装饰
markersDecoration Decoration 事件标记容器装饰
markersMaxCount int 最多显示的事件标记数量
markerSize double 事件标记大小
markersOffset PositionedOffset 事件标记偏移量
canMarkersOverflow bool 标记是否允许溢出日期单元格
outsideDaysVisible bool 是否显示范围外的日期(默认true)

HeaderStyle 子属性

属性名 类型 说明
formatButtonVisible bool 是否显示视图切换按钮(默认true)
formatButtonShowsNext bool 切换按钮是否显示下一个格式(默认true)
formatButtonDecoration BoxDecoration 视图切换按钮装饰
formatButtonTextStyle TextStyle 视图切换按钮文本样式
leftChevronIcon Widget 左箭头图标
rightChevronIcon Widget 右箭头图标
titleTextStyle TextStyle 标题(月份)文本样式
titleCentered bool 标题是否居中(默认false)
titleFormatter String Function(DateTime, dynamic) 标题文本格式化器
headerPadding EdgeInsets 表头内边距
headerMargin EdgeInsets 表头外边距
chevronPadding EdgeInsets 箭头图标内边距
chevronVisible bool 是否显示箭头图标(默认true)

样式定制示例:

TableCalendar(
  // ...其他参数
  calendarStyle: CalendarStyle(
    // 选中日期样式
    selectedDecoration: BoxDecoration(
      color: Colors.blue,
      shape: BoxShape.circle,
    ),
    // 今天日期样式
    todayDecoration: BoxDecoration(
      color: Colors.grey[200],
      shape: BoxShape.circle,
    ),
    // 周末样式
    weekendTextStyle: TextStyle(color: Colors.red),
    // 事件标记样式
    markersMaxCount: 3,  // 最多显示3个标记
    markerSize: 6,
  ),
  // 表头样式
  headerStyle: HeaderStyle(
    formatButtonVisible: false,  // 隐藏视图切换按钮
    titleCentered: true,
    headerPadding: EdgeInsets.symmetric(vertical: 8),
    titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
  ),
)

3.6. 本地化属性

属性名 类型 说明
locale String? 本地化语言代码(如'zh_CN'、'en_US')
daysOfWeekLabels List<String> 星期标签文本(默认按locale生成)
daysOfWeekLabelsExceptions Map<int, String> 特定星期几的文本覆盖
weekNumberLabel String 周数标签文本(默认'W')

示例:

import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart';

// 初始化本地化
initializeDateFormatting().then((_) {
  setState(() {});
});

TableCalendar(
  // ...其他参数
  locale: 'zh_CN',  // 支持 'en_US', 'ja_JP' 等
  daysOfWeekStyle: DaysOfWeekStyle(
    weekdayStyle: TextStyle(),
    weekendStyle: TextStyle(color: Colors.red),
  ),
)

3.7. 交互控制属性

属性名 类型 说明
enabledDayPredicate bool Function(DateTime) 判断日期是否可交互(默认全部可交互)
onHeaderTapped void Function(DateTime) 表头点击回调
onHeaderLongPressed void Function(DateTime) 表头长按回调
onDayLongPressed void Function(DateTime, DateTime) 日期长按回调
dragStartBehavior DragStartBehavior 拖拽起始行为(默认start)

3.8. 高级自定义属性

属性名 类型 说明
calendarBuilders CalendarBuilders 自定义构建器集合(以下为常用子项)
- dayBuilder Widget Function(BuildContext, DateTime, DateTime, bool, bool, bool, bool, List) 自定义日期单元格
- markerBuilder Widget Function(BuildContext, DateTime, List) 自定义事件标记
- headerTitleBuilder Widget Function(BuildContext, DateTime) 自定义表头标题
- weekNumberBuilder Widget Function(BuildContext, int) 自定义周数显示
transitionDuration Duration 视图切换动画时长(默认200ms)
pageAnimationEnabled bool 是否启用页面切换动画(默认true)

4. 性能优化

  • 使用 ValueNotifier 管理事件数据,避免不必要重建
  • 复杂标记使用缓存Widget
  • 合理设置 firstDaylastDay 范围
final ValueNotifier<List> _selectedEvents = ValueNotifier([]);

// 监听选中日期变化更新事件
void _updateSelectedEvents() {
  _selectedEvents.value = _events[_selectedDay] ?? [];
}

// 构建时使用ValueListenableBuilder
ValueListenableBuilder<List>(
  valueListenable: _selectedEvents,
  builder: (context, value, _) {
    return // 事件列表
  },
)

5. 完整配置示例

TableCalendar(
  firstDay: DateTime(2020),
  lastDay: DateTime(2030),
  focusedDay: _focusedDay,
  selectedDayPredicate: (day) => isSameDay(_selectedDay, day),
  onDaySelected: (selectedDay, focusedDay) {
    if (!isSameDay(_selectedDay, selectedDay)) {
      setState(() {
        _selectedDay = selectedDay;
        _focusedDay = focusedDay;
      });
    }
  },
  // 视图配置
  calendarFormat: _calendarFormat,
  onFormatChanged: (format) => setState(() => _calendarFormat = format),
  availableCalendarFormats: const {
    CalendarFormat.month: '月',
    CalendarFormat.week: '周',
  },
  // 范围选择
  rangeStartDay: _rangeStart,
  rangeEndDay: _rangeEnd,
  rangeSelectionMode: _rangeSelectionMode,
  onRangeSelected: (start, end, focusedDay) => setState(() {
    _rangeStart = start;
    _rangeEnd = end;
    _rangeSelectionMode = RangeSelectionMode.toggledOn;
  }),
  // 事件加载
  eventLoader: (day) => _events[day] ?? [],
  // 样式定制
  calendarStyle: CalendarStyle(
    selectedDecoration: const BoxDecoration(
      color: Colors.blue,
      shape: BoxShape.circle,
    ),
    todayDecoration: BoxDecoration(
      color: Colors.grey[200],
      shape: BoxShape.circle,
    ),
    markersMaxCount: 3,
  ),
  headerStyle: const HeaderStyle(
    titleCentered: true,
    formatButtonVisible: false,
  ),
  // 本地化
  locale: 'zh_CN',
  // 自定义构建器
  calendarBuilders: CalendarBuilders(
    markerBuilder: (context, date, events) => events.isNotEmpty
        ? Container(
            width: 12,
            height: 12,
            decoration: const BoxDecoration(
              color: Colors.red,
              shape: BoxShape.circle,
            ),
          )
        : null,
  ),
)

6. 总结

table_calendar 提供了灵活的日历解决方案,核心关注:

  • 基础日期选择与范围选择的状态管理
  • 事件标记与自定义样式的视觉定制
  • 视图切换与本地化的用户体验优化
  • 性能优化技巧(如状态隔离、合理设置范围)

更复杂功能可参考官方文档Github仓库实现。使用时需注意范围选择与单个选择的互斥性,以及本地化配置的初始化步骤。


本次分享就到这儿啦,我是鹏多多,深耕前端的技术创作者,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

PS:在本页按F12,在console中输入document.getElementsByClassName('panel-btn')[0].click();有惊喜哦~

往期文章

❌