@@ -49,6 +49,7 @@ class TDTreeSelect extends StatefulWidget {
4949 this .multiple = false ,
5050 this .style = TDTreeSelectStyle .normal,
5151 this .height = 336 ,
52+ this .outwardCornerRadius = 9 ,
5253 }) : super (key: key);
5354
5455 /// 展示的选项列表
@@ -69,6 +70,9 @@ class TDTreeSelect extends StatefulWidget {
6970 /// 一级菜单样式
7071 final TDTreeSelectStyle style;
7172
73+ /// 一级菜单选中项的外弯折圆角半径,默认为 9
74+ final double outwardCornerRadius;
75+
7276 @override
7377 State <TDTreeSelect > createState () => _TDTreeSelectState ();
7478}
@@ -165,6 +169,12 @@ class _TDTreeSelectState extends State<TDTreeSelect> {
165169 itemBuilder: (context, index) {
166170 final option = widget.options[index];
167171 final isSelected = firstValue == option.value;
172+ // 判断上一个和下一个选项是否被选中
173+ final isPrevSelected = index > 0 &&
174+ firstValue == widget.options[index - 1 ].value;
175+ final isNextSelected =
176+ index < widget.options.length - 1 &&
177+ firstValue == widget.options[index + 1 ].value;
168178
169179 return GestureDetector (
170180 onTap: () {
@@ -181,48 +191,71 @@ class _TDTreeSelectState extends State<TDTreeSelect> {
181191 widget.onChange? .call (values, 1 );
182192 });
183193 },
184- child: Container (
185- padding: const EdgeInsets .all (16 ),
186- decoration: BoxDecoration (
187- color: isSelected
188- ? TDTheme .of (context).bgColorContainer
189- : null ,
190- border: isSelected &&
191- widget.style == TDTreeSelectStyle .outline
192- ? Border (
193- left: BorderSide (
194- color: TDTheme .of (context).brandNormalColor,
195- width: 3 ,
196- ),
197- )
198- : null ,
199-
200- /// todo 上下 borderRadius
201- borderRadius: BorderRadius .only (
202-
203- /// 选中的上一个
204- /*topRight: Radius.circular(
205- topAdjacent ? TDTheme.of(context).radiusLarge : 0),*/
206-
207- /// 选中的下一个
208- /* bottomRight: Radius.circular(
209- bottomAdjacent ? TDTheme.of(context).radiusLarge : 0),*/
194+ child: Stack (
195+ children: [
196+ Container (
197+ width: double .infinity,
198+ padding: const EdgeInsets .all (16 ),
199+ decoration: BoxDecoration (
200+ color: isSelected
201+ ? TDTheme .of (context).bgColorContainer
202+ : null ,
203+ border: isSelected &&
204+ widget.style == TDTreeSelectStyle .outline
205+ ? Border (
206+ left: BorderSide (
207+ color:
208+ TDTheme .of (context).brandNormalColor,
209+ width: 3 ,
210+ ),
211+ )
212+ : null ,
213+ ),
214+ child: Text (
215+ option.label,
216+ maxLines: option.maxLines,
217+ overflow: TextOverflow .ellipsis,
218+ style: TextStyle (
219+ fontSize:
220+ TDTheme .of (context).fontBodyLarge? .size ?? 16 ,
221+ color: isSelected
222+ ? TDTheme .of (context).brandNormalColor
223+ : TDTheme .of (context).textColorPrimary,
224+ fontWeight: isSelected
225+ ? FontWeight .w600
226+ : FontWeight .normal,
210227 ),
211- ),
212- child: Text (
213- option.label,
214- maxLines: option.maxLines,
215- overflow: TextOverflow .ellipsis,
216- style: TextStyle (
217- fontSize:
218- TDTheme .of (context).fontBodyLarge? .size ?? 16 ,
219- color: isSelected
220- ? TDTheme .of (context).brandNormalColor
221- : TDTheme .of (context).textColorPrimary,
222- fontWeight:
223- isSelected ? FontWeight .w600 : FontWeight .normal,
228+ ),
224229 ),
225- ),
230+ // 未选中项:如果上一个是选中项,在右上角画向外弯折圆角
231+ if (! isSelected && isPrevSelected)
232+ Positioned (
233+ top: 0 ,
234+ right: 0 ,
235+ child: CustomPaint (
236+ size: Size (widget.outwardCornerRadius, widget.outwardCornerRadius),
237+ painter: _OutwardCornerPainter (
238+ color:
239+ TDTheme .of (context).bgColorContainer,
240+ corner: _Corner .topRight,
241+ ),
242+ ),
243+ ),
244+ // 未选中项:如果下一个是选中项,在右下角画向外弯折圆角
245+ if (! isSelected && isNextSelected)
246+ Positioned (
247+ bottom: 0 ,
248+ right: 0 ,
249+ child: CustomPaint (
250+ size: Size (widget.outwardCornerRadius, widget.outwardCornerRadius),
251+ painter: _OutwardCornerPainter (
252+ color:
253+ TDTheme .of (context).bgColorContainer,
254+ corner: _Corner .bottomRight,
255+ ),
256+ ),
257+ ),
258+ ],
226259 ),
227260 );
228261 },
@@ -429,3 +462,62 @@ class _TDTreeSelectState extends State<TDTreeSelect> {
429462 );
430463 }
431464}
465+
466+ /// 向外弯折圆角的位置枚举
467+ enum _Corner {
468+ topRight,
469+ bottomRight,
470+ }
471+
472+ /// 自定义画笔:绘制向外弯折的圆角效果
473+ /// 原理:在选中项的右上角/右下角绘制一个填充色的矩形,然后用白色圆弧挖出一个反向圆角
474+ class _OutwardCornerPainter extends CustomPainter {
475+ final Color color;
476+ final _Corner corner;
477+
478+ _OutwardCornerPainter ({required this .color, required this .corner});
479+
480+ @override
481+ void paint (Canvas canvas, Size size) {
482+ final paint = Paint ()
483+ ..color = color
484+ ..style = PaintingStyle .fill;
485+
486+ final path = Path ();
487+ final r = size.width;
488+
489+ switch (corner) {
490+ case _Corner .topRight:
491+ // 从右上角开始,画一个矩形区域,然后用圆弧挖出向外弯折的效果
492+ path.moveTo (0 , 0 );
493+ path.lineTo (r, 0 );
494+ path.lineTo (r, r);
495+ path.arcToPoint (
496+ Offset (0 , 0 ),
497+ radius: Radius .circular (r),
498+ clockwise: false ,
499+ );
500+ path.close ();
501+ break ;
502+ case _Corner .bottomRight:
503+ // 从右下角开始,画一个矩形区域,然后用圆弧挖出向外弯折的效果
504+ path.moveTo (r, 0 );
505+ path.lineTo (r, r);
506+ path.lineTo (0 , r);
507+ path.arcToPoint (
508+ Offset (r, 0 ),
509+ radius: Radius .circular (r),
510+ clockwise: false ,
511+ );
512+ path.close ();
513+ break ;
514+ }
515+
516+ canvas.drawPath (path, paint);
517+ }
518+
519+ @override
520+ bool shouldRepaint (covariant _OutwardCornerPainter oldDelegate) {
521+ return oldDelegate.color != color || oldDelegate.corner != corner;
522+ }
523+ }
0 commit comments