feat: 更新代码仓库全部修改
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / build (push) Has been cancelled

This commit is contained in:
2025-10-30 04:47:53 -07:00
parent 145832093e
commit f42a481452
134 changed files with 8032 additions and 4270 deletions
+241
View File
@@ -0,0 +1,241 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
class HIDialog extends StatefulWidget {
final String? title;
final String? message;
final String? confirmText;
final String? cancelText;
final VoidCallback? onConfirm;
final VoidCallback? onCancel;
final Widget? customMessageWidget;
/// 是否允许点击外部关闭
final bool barrierDismissible;
/// 是否禁止物理返回键关闭
final bool preventBackDismiss;
/// 是否点击确认后自动关闭(默认 true)
final bool autoClose;
/// 是否显示按钮 loadingautoClose=false 时自动启用)
final bool? showLoading;
const HIDialog({
Key? key,
this.title,
this.message,
this.confirmText,
this.cancelText,
this.onConfirm,
this.onCancel,
this.customMessageWidget,
this.barrierDismissible = true,
this.preventBackDismiss = false,
this.autoClose = true,
this.showLoading,
}) : super(key: key);
static Future<void> show({
String? title,
String? message,
String? confirmText,
String? cancelText,
VoidCallback? onConfirm,
VoidCallback? onCancel,
Widget? customMessageWidget,
bool barrierDismissible = true,
bool preventBackDismiss = false,
bool autoClose = true,
bool? showLoading,
}) {
return Get.dialog(
HIDialog(
title: title,
message: message,
confirmText: confirmText,
cancelText: cancelText,
onConfirm: onConfirm,
onCancel: onCancel,
customMessageWidget: customMessageWidget,
barrierDismissible: barrierDismissible,
preventBackDismiss: preventBackDismiss,
autoClose: autoClose,
showLoading: showLoading,
),
barrierDismissible: barrierDismissible,
barrierColor: Colors.transparent,
);
}
@override
State<HIDialog> createState() => _HIDialogState();
}
class _HIDialogState extends State<HIDialog> {
bool _isLoading = false;
Future<void> _handleConfirm() async {
if (_isLoading) return;
final useLoading = widget.showLoading ?? !widget.autoClose;
if (useLoading) {
setState(() => _isLoading = true);
}
if (widget.autoClose) {
Get.back();
}
await Future.microtask(() => widget.onConfirm?.call());
if (useLoading && mounted) {
setState(() => _isLoading = false);
}
}
Widget _buildConfirmButton() {
return TextButton(
onPressed: _isLoading ? null : _handleConfirm,
style: TextButton.styleFrom(
backgroundColor: const Color(0xFFADFF5B),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
),
minimumSize: Size.fromHeight(40.w),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: _isLoading
? SizedBox(
height: 20.w,
width: 20.w,
child: const CircularProgressIndicator(
color: Colors.black,
strokeWidth: 2,
),
)
: Text(
widget.confirmText ?? AppTranslations.kr_dialog.kr_confirm,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
);
}
@override
Widget build(BuildContext context) {
final dialog = Dialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(20.w),
child: ClipRRect(
borderRadius: BorderRadius.circular(34.r),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 26, sigmaY: 26), // 毛玻璃模糊
child: Container(
width: 245.w,
padding: EdgeInsets.fromLTRB(30.w, 16.w, 30.w, 16.w),
decoration: BoxDecoration(
color: const Color(0xF5F5F5).withOpacity(0.6), // 半透明底色
borderRadius: BorderRadius.circular(34.r),
border: Border.all(
color: Colors.white.withOpacity(0.2), // 高光边框
width: 1.5,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.title != null) ...[
Align(
alignment: Alignment.centerLeft,
child: Text(
widget.title!,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: 'AlibabaPuHuiTi-Medium',
height: 1.3,
),
),
),
SizedBox(height: 4.w),
],
if (widget.message != null || widget.customMessageWidget != null) ...[
Container(
constraints: BoxConstraints(maxHeight: 200.h),
child: SingleChildScrollView(
child: widget.customMessageWidget ??
Text(
widget.message!,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 14.sp,
color: Colors.black,
height: 1.4,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
),
),
],
if (widget.confirmText != null || widget.cancelText != null) ...[
SizedBox(height: 28.w),
Row(
children: [
if (widget.confirmText != null) Expanded(child: _buildConfirmButton()),
if (widget.cancelText != null && widget.confirmText != null)
SizedBox(width: 12.w),
if (widget.cancelText != null)
Expanded(
child: TextButton(
onPressed: () {
Get.back();
widget.onCancel?.call();
},
style: TextButton.styleFrom(
backgroundColor: const Color(0xFFFF00B7),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
),
minimumSize: Size.fromHeight(40.w),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
widget.cancelText!,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
),
),
],
),
]
],
),
),
),
),
);
if (widget.preventBackDismiss) {
return WillPopScope(onWillPop: () async => false, child: dialog);
}
return dialog;
}
}
+190
View File
@@ -0,0 +1,190 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart';
/// 🔹 HIBaseScaffold
/// 用于统一页面结构:
/// ✅ 全屏背景图
/// ✅ 左上角返回按钮
/// ✅ 右上角套餐入口按钮(球形)
/// ✅ 自定义主体内容(body)
///
/// 使用:
/// ```dart
/// return HIBaseScaffold(
/// showBack: true,
/// showSubscriptionCorner: true,
/// body: YourWidget(),
/// );
/// ```
class HIBaseScaffold extends StatelessWidget {
/// 页面主体内容
final Widget child;
/// 是否显示左上角返回按钮
final bool showBack;
/// 【新增】是否显示左上角菜单按钮(用于首页)
final bool showMenuButton;
/// 返回按钮点击事件(默认 Get.back()
final VoidCallback? onBackTap;
/// 页面主标题
final String? title;
/// 页面副标题
final String? subtitle;
/// 是否显示背景图
final bool showBackgroundImage;
/// resizeToAvoidBottomInset
final bool? resizeToAvoidBottomInset;
/// 为顶部内容(如返回按钮、标题)预留的高度
final double topContentAreaHeight;
const HIBaseScaffold({
super.key,
required this.child,
this.showBack = true,
this.showMenuButton = false,
this.onBackTap,
this.title,
this.subtitle,
this.showBackgroundImage = true,
this.topContentAreaHeight = 120.0,
this.resizeToAvoidBottomInset = false,
});
@override
Widget build(BuildContext context) {
// 顶部状态栏高度
final double topPadding = MediaQuery.of(context).padding.top + 8;
return Scaffold(
extendBodyBehindAppBar: true,
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
backgroundColor: showBackgroundImage
? Colors.transparent
: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
toolbarHeight: 0.0,
elevation: 0,
systemOverlayStyle: const SystemUiOverlayStyle(
statusBarIconBrightness: Brightness.light,
),
),
body: Stack(
fit: StackFit.expand,
children: [
// 背景图全屏
// if (showBackgroundImage)
// const Positioned.fill(
// child: KrLocalImage(
// imageName: 'global-bg',
// imageType: ImageType.jpg,
// ),
// ),
// 页面主体内容(child
SafeArea(
child: Padding(
padding: EdgeInsets.only(top: topContentAreaHeight),
child: child,
),
),
// 左上角按钮区域
Positioned(
top: topPadding,
left: 40.w,
child: Builder(
builder: (context) {
// 优先显示菜单按钮
if (showMenuButton) {
return GestureDetector(
onTap: () {
Get.toNamed(Routes.HI_MENU);
},
child: Container(
width: 48,
height: 48,
alignment: Alignment.center,
child: KrLocalImage(
imageName: 'hi-home-stack',
width: 48,
height: 48,
imageType: ImageType.svg,
),
),
);
}
// 如果不显示菜单按钮,再根据 showBack 判断是否显示返回按钮
else if (showBack) {
return GestureDetector(
onTap: onBackTap ?? () => Get.back(),
child: Container(
width: 48,
height: 48,
alignment: Alignment.center,
child: KrLocalImage(
imageName: 'hi-back-icon',
width: 48,
height: 48,
imageType: ImageType.svg,
),
),
);
}
// 如果两者都不显示,则返回一个空容器
return const SizedBox.shrink();
},
),
),
// 标题和副标题
if (title != null || subtitle != null)
Positioned(
top: topPadding +
(showBack ? 12.w : 20.w), // 顶部空出状态栏高度,并根据是否有返回按钮调整间距
left: 0,
right: 0,
child: Column(
// 使用 Column 来垂直排列标题
crossAxisAlignment: CrossAxisAlignment.center, // 水平居中
children: [
if (title != null)
Text(
title!,
style: TextStyle(
color: Colors.black, // 在深色背景下使用白色
fontSize: 24.sp,
fontWeight: FontWeight.bold,
),
),
if (subtitle != null)
Padding(
padding: EdgeInsets.only(top: 0), // 副标题与主标题之间的小间距
child: Text(
subtitle!,
style: TextStyle(
color: Colors.black, // 副标题使用带透明度的白色
fontSize: 14.sp,
fontWeight: FontWeight.w100,
),
),
),
],
),
),
],
),
);
}
}
+194
View File
@@ -0,0 +1,194 @@
// lib/app/widgets/hi_collapsible_list.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'dart:math' as math; // 导入 math 库以使用 pi
import 'package:flutter/gestures.dart';
import 'package:get/get.dart';
import '../routes/app_pages.dart';
/// 可折叠列表项的数据模型
class HICollapsibleItem {
final String title;
// 👇 核心改动 1: 将 content 类型从 String 改为 List<String>
final List<String> content;
const HICollapsibleItem({required this.title, required this.content});
}
/// 一个独立的、自定义样式的可折叠面板组件 (HI 前缀)
///
/// 它接收一个标题和一个内容字符串,并渲染成一个带边框、可展开/收起的面板。
class HICollapsibleItemWidget extends StatefulWidget {
const HICollapsibleItemWidget({
super.key,
required this.item,
this.initiallyExpanded = false,
});
/// 要显示的数据项
final HICollapsibleItem item;
/// 初始是否展开
final bool initiallyExpanded;
@override
State<HICollapsibleItemWidget> createState() => _HICollapsibleItemWidgetState();
}
class _HICollapsibleItemWidgetState extends State<HICollapsibleItemWidget> {
bool _isExpanded = false;
@override
void initState() {
super.initState();
_isExpanded = widget.initiallyExpanded;
}
List<TextSpan> _buildTextSpans(String text) {
final List<TextSpan> spans = [];
final RegExp linkRegExp = RegExp(r'\[link\](.*?)\[/link\]'); // 正则表达式匹配 [link]...[/link]
text.splitMapJoin(
linkRegExp,
onMatch: (Match match) {
final linkText = match.group(1)!; // 获取链接文本,例如 "点击这里"
spans.add(
TextSpan(
text: linkText,
style: const TextStyle(
color: const Color(0xFFADFF5B), // 链接颜色
),
recognizer: TapGestureRecognizer()
..onTap = () {
// 在这里处理点击事件,例如打开一个网页
// 注意:您需要添加 url_launcher 依赖
Get.toNamed(
Routes.KR_WEBVIEW,
arguments: {
'url': 'https://www.baidu.com',
},
);
},
),
);
return '';
},
onNonMatch: (String nonMatch) {
spans.add(TextSpan(text: nonMatch)); // 普通文本部分
return '';
},
);
return spans;
}
@override
Widget build(BuildContext context) {
final BorderRadius borderRadius = BorderRadius.circular(40.w);
return AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 2.0),
borderRadius: borderRadius,
),
child: ClipRRect(
borderRadius: borderRadius,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// ===== 标题部分 =====
GestureDetector(
onTap: () {
setState(() {
_isExpanded = !_isExpanded;
});
},
behavior: HitTestBehavior.translucent,
child: Padding(
padding: EdgeInsets.fromLTRB(24.w, 16.w, 24.w, 16.w),
child: Row(
children: [
Expanded(
child: Text(
widget.item.title,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
AnimatedRotation(
turns: _isExpanded ? 0.75 : 0.25,
duration: const Duration(milliseconds: 200),
child: KrLocalImage(
imageName: 'arrow-right-icon',
imageType: ImageType.svg,
color: Colors.white,
),
),
],
),
),
),
// ===== 内容部分 =====
AnimatedSize(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
child: _isExpanded
? Container(
padding: EdgeInsets.fromLTRB(24.w, 0, 24.w, 16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: widget.item.content.map((itemText) {
return Padding(
padding: EdgeInsets.only(bottom: 8.h),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 11.w, right: 8.w),
child: Container(
width: 5.w,
height: 5.w,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
),
Expanded(
child: Text.rich(
TextSpan(
style: TextStyle(
color: Colors.white,
fontSize: 13.sp,
height: 1.8,
fontWeight: FontWeight.w300,
),
children: _buildTextSpans(itemText),
),
),
),
],
),
);
}).toList(),
),
)
: const SizedBox.shrink(),
),
],
),
),
);
}
}
+114
View File
@@ -0,0 +1,114 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class HiFixedScrollbar extends StatefulWidget {
final Widget child;
final ScrollController controller;
final bool isShowScrollbar;
/// 距离右边的间距(默认 18
final double right;
/// 滚动条宽度
final double thickness;
/// 滚动条颜色(默认白色 30%)
final Color thumbColor;
/// 背景轨道颜色(默认白色 15%)
final Color trackColor;
/// 滚动条固定高度(默认 50
final double thumbHeight;
const HiFixedScrollbar({
super.key,
required this.child,
required this.controller,
this.right = 18,
this.isShowScrollbar = true,
this.thickness = 5,
this.thumbHeight = 50,
this.thumbColor = const Color.fromRGBO(255, 255, 255, 0.3),
this.trackColor = const Color.fromRGBO(255, 255, 255, 0.15),
});
@override
State<HiFixedScrollbar> createState() => _HiFixedScrollbarState();
}
class _HiFixedScrollbarState extends State<HiFixedScrollbar> {
double _thumbOffset = 0.0;
@override
void initState() {
super.initState();
widget.controller.addListener(_updateThumbPosition);
}
void _updateThumbPosition() {
if (!mounted) return;
final position = widget.controller.position;
if (!position.hasPixels || !position.hasContentDimensions) return;
final maxScrollExtent = position.maxScrollExtent;
final offset = position.pixels;
final viewport = position.viewportDimension;
// ✅ 固定高度滚动条,只根据滚动比例移动位置
final trackHeight = viewport - widget.thumbHeight;
final scrollRatio = maxScrollExtent == 0 ? 0 : offset / maxScrollExtent;
setState(() {
_thumbOffset = (trackHeight * scrollRatio).clamp(0, trackHeight);
});
}
@override
void dispose() {
widget.controller.removeListener(_updateThumbPosition);
super.dispose();
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (_, constraints) {
return Stack(
children: [
// 滚动内容
widget.child,
if(widget.isShowScrollbar)
...[
// 滚动条轨道
Positioned(
right: widget.right.w,
top: 0,
bottom: 0,
child: Container(
width: widget.thickness.w,
decoration: BoxDecoration(
color: widget.trackColor,
borderRadius: BorderRadius.circular(4),
),
),
),
// 滚动条拇指
Positioned(
right: widget.right.w,
top: _thumbOffset,
child: Container(
width: widget.thickness.w,
height: widget.thumbHeight,
decoration: BoxDecoration(
color: widget.thumbColor,
borderRadius: BorderRadius.circular(4),
),
),
),
]
],
);
},
);
}
}
+78
View File
@@ -0,0 +1,78 @@
// lib/app/widgets/hi_help_entrance.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart';
/// 全局统一的帮助入口 Widget (HI 前缀)
///
/// 通常放置在 Stack 的顶层,通过 Positioned 控制位置。
class HIHelpEntrance extends StatelessWidget {
const HIHelpEntrance({
super.key,
this.bottom = 40.0,
this.isLight = true,
});
final double bottom;
final bool isLight; // 用于控制主题颜色
@override
Widget build(BuildContext context) {
final Color displayColor = isLight ? Colors.white : Colors.black;
return Positioned(
bottom: bottom,
left: 0,
right: 0,
child: GestureDetector(
onTap: () {
Get.toNamed(Routes.HI_HELP);
},
child: AbsorbPointer(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
KrLocalImage(
imageName: 'hi-home-logo',
imageType: ImageType.svg,
color: displayColor,
width: 32.w,
height: 32.w,
),
SizedBox(width: 4.w),
Stack(
clipBehavior: Clip.none,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 2.0),
child: Text(
'遇到问题?',
style: TextStyle(
color: displayColor,
fontSize: 16.sp,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
height: 1.2,
color: displayColor,
),
),
],
),
],
),
),
),
);
}
}
+82 -33
View File
@@ -1,16 +1,20 @@
import 'package:flutter/material.dart';
/// 简单的加载动画组件,替代有问题的flutter_spinkit
/// ====================================================================
/// 1. KRSimpleLoading: 旋转和扇形加载动画 (支持暂停,已修复重合)
/// ====================================================================
class KRSimpleLoading extends StatefulWidget {
final Color? color;
final double size;
final Duration duration;
final bool isPaused; // 控制动画暂停/恢复
const KRSimpleLoading({
super.key,
this.color,
this.size = 40.0,
this.size = 30.0, // 环的宽高默认为 30.0 像素
this.duration = const Duration(milliseconds: 1000),
this.isPaused = false, // 默认不暂停
});
@override
@@ -20,23 +24,48 @@ class KRSimpleLoading extends StatefulWidget {
class _KRSimpleLoadingState extends State<KRSimpleLoading>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
late Animation<double> _rotationAnimation;
// 环的宽度 5px
static const double _strokeWidth = 5.0;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: widget.duration,
vsync: this,
);
_animation = Tween<double>(
_rotationAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
curve: Curves.linear,
));
_controller.repeat();
// 根据初始状态决定是重复播放还是停止
_setAnimationState(widget.isPaused);
}
void _setAnimationState(bool isPaused) {
if (isPaused) {
_controller.stop();
} else {
// 如果之前停止了,调用 repeat 重新开始
_controller.repeat();
}
}
@override
void didUpdateWidget(covariant KRSimpleLoading oldWidget) {
super.didUpdateWidget(oldWidget);
// 监听 isPaused 参数的变化,并更新动画状态
if (widget.isPaused != oldWidget.isPaused) {
_setAnimationState(widget.isPaused);
}
}
@override
@@ -47,38 +76,58 @@ class _KRSimpleLoadingState extends State<KRSimpleLoading>
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Transform.rotate(
angle: _animation.value * 2 * 3.14159,
child: Container(
width: widget.size,
height: widget.size,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: widget.color ?? Theme.of(context).primaryColor,
width: 2.0,
),
),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor: AlwaysStoppedAnimation<Color>(
widget.color ?? Theme.of(context).primaryColor,
final defaultColor = widget.color ?? Theme.of(context).primaryColor;
// 强制动画组件拥有固定的 30x30 尺寸
return SizedBox(
width: widget.size,
height: widget.size,
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.rotate(
angle: _rotationAnimation.value * 2 * 3.14159,
// 关键修复: 使用 Stack 和 Center+SizedBox 确保两个环完美重合
child: Stack(
children: [
// 1. 底环 (Container): 绘制 30x30 边界内的 5px 边框
Positioned.fill(
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: defaultColor.withOpacity(0.3),
width: _strokeWidth,
),
),
),
),
),
// 2. 顶扇形 (CircularProgressIndicator):
// 通过 Center+SizedBox 强制其绘制区域收缩,以消除渲染偏差。
Center(
child: SizedBox(
// 关键:将尺寸减去笔触宽度 (30 - 5 = 25)
width: widget.size - _strokeWidth,
height: widget.size - _strokeWidth,
child: CircularProgressIndicator(
value: 0.2, // 彩色扇形长度
strokeCap: StrokeCap.round, // 圆角
strokeWidth: _strokeWidth, // 宽度 5px
backgroundColor: Colors.transparent, // 必须透明
valueColor: AlwaysStoppedAnimation<Color>(
defaultColor,
),
),
),
),
],
),
),
);
},
);
},
),
);
}
}
/// 脉冲加载动画
class KRSimplePulse extends StatefulWidget {
final Color? color;
final double size;
+1 -1
View File
@@ -100,7 +100,7 @@ class _ToastWidget extends StatelessWidget {
message,
style: const TextStyle(
fontSize: 15.0,
color: Colors.white,
color: const Color(0xFFADFF5B),
fontWeight: FontWeight.w500,
letterSpacing: 0.3,
),