棉花app新增页面

This commit is contained in:
czz
2025-06-03 09:34:31 +08:00
parent 79a9f165e1
commit 7e0dfa7494
112 changed files with 18479 additions and 73 deletions

View File

@@ -0,0 +1,151 @@
// bezier_bottom_navigation_bar.dart
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
class BezierBottomNavigationBar extends StatelessWidget {
final int selectedIndex;
final double animatedPosition;
final ValueChanged<int> onTap;
final List<String> path;
final List<String> titles;
const BezierBottomNavigationBar({
Key? key,
required this.selectedIndex,
required this.animatedPosition,
required this.onTap,
required this.path,
required this.titles,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final itemCount = path.length;
return SizedBox(
height: 130.rpx,
child: Stack(
children: [
Positioned.fill(
child: CustomPaint(
size: Size(MediaQuery.of(context).size.width, 130.rpx),
painter: BezierPainter(
position: animatedPosition,
itemCount: itemCount,
),
),
),
Row(
children: path.asMap().entries.map((entry) {
final i = entry.key;
final icon = entry.value;
return Expanded(
child: GestureDetector(
// 用 InkWell 替换 GestureDetector支持点击反馈
onTap: () => onTap(i),
// splashColor: Colors.transparent, // 可选:关闭 splash 效果
// highlightColor: Colors.transparent, // 可选:关闭高亮效果
child: SizedBox.expand(
child: Padding(
padding: EdgeInsets.only(top: 14.rpx),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 11.rpx),
child: SvgPicture.asset(icon,
width: 42.rpx,
height: 42.rpx,
color: selectedIndex == i
? Colors.white
: Color(0XFF929699)),
),
SizedBox(height: 3),
Text(
titles[i],
style: TextStyle(
fontSize: 22.rpx,
color: selectedIndex == i
? Colors.white
: Colors.grey.shade400,
),
),
],
),
)
// 关键点:撑满 Expanded 区域
),
),
);
}).toList(),
),
],
),
);
}
}
class BezierPainter extends CustomPainter {
final double position;
final int itemCount;
BezierPainter({required this.position, required this.itemCount});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.white
..style = PaintingStyle.stroke
..strokeWidth = 1.0;
final path = Path();
final itemWidth = size.width / itemCount;
final curveWidth = itemWidth * 0.8;
double curveHeight = 8.5;
final centerX = itemWidth * position + itemWidth / 2;
final left = centerX - curveWidth / 2;
final right = centerX + curveWidth / 2;
// 控制点偏移比例(越小越平滑)
final controlOffsetX = curveWidth * 0.2;
final controlOffsetY = curveHeight * 0.9;
// 起点
path.moveTo(0, 0);
// 到左侧前的一段直线
path.lineTo(left, 0);
// 凸起贝塞尔曲线
path.cubicTo(
left + controlOffsetX,
0,
centerX - controlOffsetX,
-controlOffsetY,
centerX,
-controlOffsetY,
);
path.cubicTo(
centerX + controlOffsetX,
-controlOffsetY,
right - controlOffsetX,
0,
right,
0,
);
// 右边剩余直线
path.lineTo(size.width, 0);
// 向下平移,保证凸起在容器内部
canvas.translate(0, controlOffsetY);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant BezierPainter oldDelegate) {
return oldDelegate.position != position;
}
}