Flutter实现带自定义曲线与选中态红色边框的自定义Tab问题求助
Flutter实现带自定义曲线与选中态红色边框的自定义Tab问题求助
我最近在尝试用Flutter复刻参考图里的Tab设计,这个设计的核心是Tab要有自定义的曲线形状,还有选中Tab时的红色边框效果(就像图里展示的那样)。
我已经写了一段代码尝试实现这个效果,但目前还没做出想要的曲线样式,想请各位帮忙看看问题出在哪,或者给点实现思路的指导,谢谢啦!
我当前的实现代码
import 'package:flutter/material.dart'; class TabShapePainter extends CustomPainter { final Color tabColor; final bool isSelected; final bool isFirst; final bool isLast; final double slantOffset; TabShapePainter({ required this.tabColor, required this.isSelected, required this.isFirst, required this.isLast, required this.slantOffset, }); @override void paint(Canvas canvas, Size size) { final Paint paint = Paint() ..color = tabColor ..style = PaintingStyle.fill; final Path path = Path(); final double borderRadius = 10.0; if (isFirst) { path.moveTo(borderRadius, 0); path.quadraticBezierTo(0, 0, 0, borderRadius); path.lineTo(0, size.height); } else { path.moveTo(0, 0); path.lineTo(slantOffset, size.height); } path.lineTo(size.width, size.height); path.lineTo(size.width - slantOffset, 0); path.close(); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant TabShapePainter oldDelegate) { return oldDelegate.tabColor != tabColor || oldDelegate.isSelected != isSelected || oldDelegate.isFirst != isFirst || oldDelegate.isLast != isLast || oldDelegate.slantOffset != slantOffset; } } class CustomTabItem extends StatelessWidget { final String text; final Color tabColor; final bool isSelected; final VoidCallback onTap; final bool isFirst; final bool isLast; final double tabWidth; final double slantOffset; CustomTabItem({ required this.text, required this.onTap, this.tabColor = Colors.blue, this.isSelected = false, this.isFirst = false, this.isLast = false, required this.tabWidth, required this.slantOffset, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( width: tabWidth, height: 55, child: Stack( children: [ Positioned.fill( child: CustomPaint( painter: TabShapePainter( tabColor: isSelected ? tabColor : tabColor.withOpacity(0.7), isSelected: isSelected, isFirst: isFirst, isLast: isLast, slantOffset: slantOffset, ), ), ), Center( child: Padding( padding: EdgeInsets.only( left: isFirst ? 0 : slantOffset * 0.5, right: isLast ? 0 : slantOffset * 0.5, ), child: Text( text, style: TextStyle( color: isSelected ? Colors.white : Colors.white70, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, fontSize: 16, ), ), ), ), ], ), ), ); } } class CustomTabsScreen extends StatefulWidget { @override _CustomTabsScreenState createState() => _CustomTabsScreenState(); } class _CustomTabsScreenState extends State<CustomTabsScreen> { int _selectedIndex = 0; final int _totalTabs = 3; final double _tabSlantOffset = 15.0; final double _baseTabWidth = 120.0; final List<Widget> _tabContents = [ Center(child: Text('محتوى التبويب الأول', style: TextStyle(fontSize: 24, color: Colors.deepPurple))), Center(child: Text('محتوى التبويب الثاني هنا', style: TextStyle(fontSize: 24, color: Colors.teal))), Center(child: Text('التبويب الثالث ومحتواه', style: TextStyle(fontSize: 24, color: Colors.orange))), ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('تبويبات متلاصقة ومائلة'), backgroundColor: Colors.blueGrey, ), body: Column( children: [ Container( height: 60, color: Colors.grey[200], child: Row( children: List.generate(_totalTabs, (index) { double offsetX = 0.0; if (index > 0) { offsetX = -(_tabSlantOffset * index); } return Transform.translate( offset: Offset(offsetX, 0), child: CustomTabItem( text: 'تبويب ${index + 1}', tabColor: [Colors.deepPurple, Colors.teal, Colors.orange][index], isSelected: _selectedIndex == index, onTap: () { setState(() { _selectedIndex = index; }); }, isFirst: index == 0, isLast: index == _totalTabs - 1, tabWidth: _baseTabWidth, slantOffset: _tabSlantOffset, ), ); }), ), ), Expanded( child: _tabContents[_selectedIndex], ), ], ), ); } } void main() { runApp(MaterialApp(home: CustomTabsScreen())); }
目前我的代码还没能实现参考图里的自定义曲线效果,希望能得到大家的建议或者指导,帮我达成想要的Tab样式~
内容来源于stack exchange
相关产品推荐
相关产品推荐

