feat: 首页,收藏页的UI,字体 组件封装

This commit is contained in:
chengsiwen committed 2026-07-03 15:38:01 +08:00
1 parent f233f1c642
commit 7f329aef44
32 files changed
+1110 -41

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
class CutCornerClipper extends StatelessWidget {
const CutCornerClipper({super.key,
this.width,
this.height,
this.cutCorner = CutCorner.topRight,
this.cutSize,
this.child,
});
final double? width;
final double? height;
final CutCorner cutCorner;
final double? cutSize;
final Widget? child;
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: EqualCutCornerClipper(
cutSize: cutSize ?? 35,
corner: cutCorner,
),
child: Container(
width: width,
height: height,
decoration: BoxDecoration(
color: Colors.white,
),
child: child,
),
);
}
}
/// 长方形缺一个角(等边缺角)
class EqualCutCornerClipper extends CustomClipper<Path> {
final double cutSize; // 缺角两条直角边的长度(相等)
final CutCorner corner;
const EqualCutCornerClipper({
this.cutSize = 20,
this.corner = CutCorner.topRight,
});
@override
Path getClip(Size size) {
final path = Path();
final w = size.width;
final h = size.height;
final c = cutSize;
switch (corner) {
case CutCorner.topRight:
path.moveTo(0, 0);
path.lineTo(w - c, 0); // 上边到缺角起点
path.lineTo(w, c); // 🔥 45° 斜线(两条边相等)
path.lineTo(w, h);
path.lineTo(0, h);
break;
case CutCorner.topLeft:
path.moveTo(c, 0);
path.lineTo(w, 0);
path.lineTo(w, h);
path.lineTo(0, h);
path.lineTo(0, c);
break;
case CutCorner.bottomRight:
path.moveTo(0, 0);
path.lineTo(w, 0);
path.lineTo(w, h - c);
path.lineTo(w - c, h);
path.lineTo(0, h);
break;
case CutCorner.bottomLeft:
path.moveTo(0, 0);
path.lineTo(w, 0);
path.lineTo(w, h);
path.lineTo(c, h);
path.lineTo(0, h - c);
break;
}
path.close();
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
if (oldClipper is EqualCutCornerClipper) {
return oldClipper.cutSize != cutSize || oldClipper.corner != corner;
}
return true;
}
}
enum CutCorner { topLeft, topRight, bottomLeft, bottomRight }
+82
View File
@@ -0,0 +1,82 @@
import 'package:flutter/material.dart';
import 'package:novyronst/root/lib_export.dart';
import 'package:novyronst/tools/widgets/novy_com_widget.dart';
class NyProgressWidget extends StatelessWidget {
const NyProgressWidget({super.key,
this.progress = 0.4,
this.width,
});
final double progress;
final double? width;
static final double _width = AppScreen.screenWidth - 50;
@override
Widget build(BuildContext context) {
return Stack(
children: [
SizedBox(
height: 14,
width: width ?? _width
),
Positioned(
left: 0, right: 0, top: 4.5,
child: Container(
height: 5,
padding: EdgeInsets.symmetric(horizontal: 2),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(2.5),
),
child: Row(
children: [
Expanded(
flex: (progress * 100).toInt(),
child: _line(),
),
Expanded(
flex: 100 - (progress * 100).toInt(),
child: _line(isActive: false),
)
],
),
),
),
Positioned(
top: 0, left: (width ?? _width - 50) * progress,
child: _pTag(),
)
],
);
}
Container _line({bool isActive = true}) {
return Container(
height: 2,
decoration: BoxDecoration(
color: isActive ? ConstColor.btGreen : ConstColor.btGreen.withAlpha(127),
),
);
}
Widget _pTag() {
return Container(
height: 14,
padding: EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration(
color: ConstColor.btGreen,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4),
topRight: Radius.circular(16),
bottomRight: Radius.circular(4),
)
),
child: NovyText('${(progress * 100).toInt()}%',
fontSize: 10,
color: Colors.black,
),
);
}
}
+55
View File
@@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
import 'package:novyronst/common/const/const_color.dart';
import 'package:novyronst/common/help/help_image.dart';
import 'package:novyronst/tools/widgets/novy_com_widget.dart';
class NyTagWidget extends StatelessWidget {
const NyTagWidget({super.key,
required this.text,
this.bgColor,
this.textColor,
});
final String text;
final Color? bgColor;
final Color? textColor;
@override
Widget build(BuildContext context) {
return Container(
height: 20,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: bgColor ?? ConstColor.withValue('EEEEEE'),
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: NovyText(text,
fontSize: 10,
color: textColor ?? ConstColor.black,
),
),
);
}
}
class NyHotWidget extends StatelessWidget {
const NyHotWidget({super.key,
required this.text,
});
final String text;
@override
Widget build(BuildContext context) {
return Row(
children: [
HelpImage.asset(ConstImage.hot, width: 12),
NovyText(text,
fontSize: 10,
color: Colors.black,
)
],
);
}
}