Skip to content

Commit d3db748

Browse files
authored
Merge pull request #667 from epoll-j/feat/calendar-custom-cell
`TDCalendar`: 支持自定义 cell 的组件
2 parents 6c6bc00 + 45999e9 commit d3db748

File tree

3 files changed

+125
-34
lines changed

3 files changed

+125
-34
lines changed

tdesign-component/example/lib/page/td_calendar_page.dart

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ class TDCalendarPage extends StatelessWidget {
3333
return const CodeWrapper(builder: _buildStyle);
3434
},
3535
),
36+
ExampleItem(
37+
desc: '自定义日期单元格',
38+
ignoreCode: true,
39+
center: false,
40+
builder: (BuildContext context) {
41+
return const CodeWrapper(builder: _buildCustomCell);
42+
},
43+
),
3644
ExampleItem(
3745
desc: '不使用Popup',
3846
ignoreCode: true,
@@ -351,3 +359,74 @@ Widget _buildBlock(BuildContext context) {
351359
],
352360
);
353361
}
362+
363+
@Demo(group: 'calendar')
364+
Widget _buildCustomCell(BuildContext context) {
365+
final size = MediaQuery.of(context).size;
366+
final selected = ValueNotifier<List<int>>([DateTime.now().millisecondsSinceEpoch + 30 * 24 * 60 * 60 * 1000]);
367+
return ValueListenableBuilder(
368+
valueListenable: selected,
369+
builder: (context, value, child) {
370+
final date = DateTime.fromMillisecondsSinceEpoch(value[0]);
371+
return TDCellGroup(
372+
cells: [
373+
TDCell(
374+
title: '自定义日期单元格',
375+
arrow: true,
376+
note: '${date.year}-${date.month}-${date.day}',
377+
onClick: (cell) {
378+
TDCalendarPopup(
379+
context,
380+
visible: true,
381+
onConfirm: (value) {
382+
print('onConfirm:$value');
383+
selected.value = value;
384+
},
385+
onClose: () {
386+
print('onClose');
387+
},
388+
child: TDCalendar(
389+
title: '请选择日期',
390+
value: value,
391+
height: size.height * 0.6 + 176,
392+
onCellClick: (value, type, tdate) {
393+
print('onCellClick:$value');
394+
},
395+
onCellLongPress: (value, type, tdate) {
396+
print('onCellLongPress:$value');
397+
},
398+
onHeaderClick: (index, week) {
399+
print('onHeaderClick:$week');
400+
},
401+
onChange: (value) {
402+
print('onChange:$value');
403+
},
404+
cellWidget: (context, tdate, selectType) {
405+
if (selectType == DateSelectType.selected) {
406+
return Column(
407+
mainAxisAlignment: MainAxisAlignment.center,
408+
children: [
409+
Text('${tdate.date.day}', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white)),
410+
Text('文案文案', style: TextStyle(fontSize: 6, color: Colors.white)),
411+
Text('自定义', style: TextStyle(fontSize: 12, color: Colors.white)),
412+
],
413+
);
414+
}
415+
return Column(
416+
mainAxisAlignment: MainAxisAlignment.center,
417+
children: [
418+
Text('${tdate.date.day}', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
419+
Text('文案文案', style: TextStyle(fontSize: 8)),
420+
Text('自定义', style: TextStyle(fontSize: 8)),
421+
],
422+
);
423+
}
424+
),
425+
);
426+
},
427+
),
428+
],
429+
);
430+
},
431+
);
432+
}

tdesign-component/lib/src/components/calendar/td_calendar.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class TDCalendar extends StatefulWidget {
4646
this.pickerItemCount = 3,
4747
this.isTimeUnit = true,
4848
this.animateTo = false,
49+
this.cellWidget,
4950
}) : super(key: key);
5051

5152
/// 第一天从星期几开始,默认 0 = 周日
@@ -123,6 +124,9 @@ class TDCalendar extends StatefulWidget {
123124
/// 动画滚动到指定位置
124125
final bool? animateTo;
125126

127+
/// 自定义日期单元格组件
128+
final Widget? Function(BuildContext context, TDate tdate, DateSelectType selectType)? cellWidget;
129+
126130
List<DateTime>? get _value => value?.map((e) {
127131
final date = DateTime.fromMillisecondsSinceEpoch(e);
128132
return DateTime(date.year, date.month, date.day);
@@ -235,6 +239,7 @@ class _TDCalendarState extends State<TDCalendar> {
235239
dateList: dateList,
236240
rowIndex: rowIndex,
237241
colIndex: colIndex,
242+
cellWidget: widget.cellWidget,
238243
);
239244
},
240245
),

tdesign-component/lib/src/components/calendar/td_calendar_cell.dart

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class TDCalendarCell extends StatefulWidget {
1818
required this.rowIndex,
1919
required this.colIndex,
2020
required this.dateList,
21+
this.cellWidget,
2122
}) : super(key: key);
2223

2324
final TDate? tdate;
@@ -32,6 +33,7 @@ class TDCalendarCell extends StatefulWidget {
3233
final int rowIndex;
3334
final int colIndex;
3435
final List<TDate?> dateList;
36+
final Widget? Function(BuildContext context, TDate tdate, DateSelectType selectType)? cellWidget;
3537

3638
@override
3739
_TDCalendarCellState createState() => _TDCalendarCellState();
@@ -72,6 +74,44 @@ class _TDCalendarCellState extends State<TDCalendarCell> {
7274
final cellStyle = TDCalendarStyle.cellStyle(context, widget.tdate!._type);
7375
final decoration = tdate.decoration ?? cellStyle.cellDecoration;
7476
final positionColor = _getColor(cellStyle, decoration);
77+
78+
// 新增自定义cell内容判断逻辑
79+
final content = widget.cellWidget?.call(context, tdate, widget.tdate!._type) ??
80+
Column(
81+
children: [
82+
Expanded(
83+
flex: 2,
84+
child: tdate.prefixWidget ??
85+
TDText(
86+
tdate.prefix ?? '',
87+
style: tdate.prefixStyle ?? cellStyle.cellPrefixStyle,
88+
maxLines: 1,
89+
overflow: TextOverflow.ellipsis,
90+
),
91+
),
92+
Expanded(
93+
flex: 3,
94+
child: Center(
95+
child: TDText(
96+
forceVerticalCenter: true,
97+
widget.tdate!.date.day.toString(),
98+
style: (isToday ? cellStyle.todayStyle : null) ?? tdate.style ?? cellStyle.cellStyle,
99+
),
100+
),
101+
),
102+
Expanded(
103+
flex: 2,
104+
child: tdate.suffixWidget ??
105+
TDText(
106+
tdate.suffix ?? '',
107+
style: tdate.suffixStyle ?? cellStyle.cellSuffixStyle,
108+
maxLines: 1,
109+
overflow: TextOverflow.ellipsis,
110+
),
111+
),
112+
],
113+
);
114+
75115
return GestureDetector(
76116
behavior: HitTestBehavior.translucent,
77117
onTap: _cellTap,
@@ -87,40 +127,7 @@ class _TDCalendarCellState extends State<TDCalendarCell> {
87127
height: widget.height,
88128
decoration: decoration,
89129
padding: EdgeInsets.all(widget.padding),
90-
child: Column(
91-
children: [
92-
Expanded(
93-
flex: 2,
94-
child: tdate.prefixWidget ??
95-
TDText(
96-
tdate.prefix ?? '',
97-
style: tdate.prefixStyle ?? cellStyle.cellPrefixStyle,
98-
maxLines: 1,
99-
overflow: TextOverflow.ellipsis,
100-
),
101-
),
102-
Expanded(
103-
flex: 3,
104-
child: Center(
105-
child: TDText(
106-
forceVerticalCenter: true,
107-
widget.tdate!.date.day.toString(),
108-
style: (isToday ? cellStyle.todayStyle : null) ?? tdate.style ?? cellStyle.cellStyle,
109-
),
110-
),
111-
),
112-
Expanded(
113-
flex: 2,
114-
child: tdate.suffixWidget ??
115-
TDText(
116-
tdate.suffix ?? '',
117-
style: tdate.suffixStyle ?? cellStyle.cellSuffixStyle,
118-
maxLines: 1,
119-
overflow: TextOverflow.ellipsis,
120-
),
121-
),
122-
],
123-
),
130+
child: content, // 使用自定义内容
124131
),
125132
if (widget.colIndex < 6)
126133
Positioned(

0 commit comments

Comments
 (0)