棉花app新增页面
This commit is contained in:
151
lib/pages/common/bezier_bottom_navigation_bar.dart
Normal file
151
lib/pages/common/bezier_bottom_navigation_bar.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user