| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:nomo/app/widgets/ix_image.dart';
- import 'package:nomo/config/theme/dark_theme_colors.dart';
- /// 信息卡片组件 - 用于显示带图标的信息列表
- /// 常用于订阅说明、功能介绍等场景
- class InfoCard extends StatelessWidget {
- final String? title;
- final List<InfoItem> items;
- final Color? backgroundColor;
- final EdgeInsets? padding;
- const InfoCard({
- super.key,
- this.title,
- required this.items,
- this.backgroundColor,
- this.padding,
- });
- @override
- Widget build(BuildContext context) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- if (title != null) ...[
- Text(
- title!,
- style: TextStyle(
- fontSize: 16.sp,
- color: DarkThemeColors.hintTextColor,
- fontWeight: FontWeight.w500,
- ),
- ),
- 16.verticalSpace,
- ],
- Container(
- padding: padding ?? EdgeInsets.all(16.w),
- decoration: BoxDecoration(
- color: backgroundColor ?? DarkThemeColors.bgDisable,
- borderRadius: BorderRadius.circular(12.r),
- ),
- child: Column(
- children: items
- .asMap()
- .entries
- .map(
- (entry) => _InfoItemWidget(
- item: entry.value,
- isLast: entry.key == items.length - 1,
- ),
- )
- .toList(),
- ),
- ),
- ],
- );
- }
- }
- /// 信息项数据模型
- class InfoItem {
- final IconData? icon;
- final String? imageSource;
- final String title;
- final String description;
- final Color? iconColor;
- final Gradient? iconGradient;
- final double? iconSize;
- final double? imageWidth;
- final double? imageHeight;
- const InfoItem({
- this.icon,
- this.imageSource,
- required this.title,
- required this.description,
- this.iconColor,
- this.iconGradient,
- this.iconSize,
- this.imageWidth,
- this.imageHeight,
- }) : assert(
- icon != null || imageSource != null,
- 'Either icon or imageSource must be provided',
- );
- }
- /// 信息项组件(内部使用)
- class _InfoItemWidget extends StatelessWidget {
- final InfoItem item;
- final bool isLast;
- const _InfoItemWidget({required this.item, this.isLast = false});
- @override
- Widget build(BuildContext context) {
- return IntrinsicHeight(
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // 左侧时间线(图标/图片 + 竖线)
- Column(
- children: [
- // 图标或图片容器
- _buildIconOrImage(),
- // 连接线(最后一个不显示)
- if (!isLast)
- Expanded(
- child: Container(
- width: 1,
- margin: EdgeInsets.only(top: 8.h, bottom: 8.h),
- color: Colors.white.withValues(alpha: 0.1),
- ),
- ),
- ],
- ),
- 12.horizontalSpace,
- // 文本内容
- Expanded(
- child: Padding(
- padding: EdgeInsets.only(bottom: isLast ? 0 : 10.w),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- item.title,
- style: TextStyle(
- fontSize: 14.sp,
- height: 1.6,
- color: DarkThemeColors.bodyTextColor,
- fontWeight: FontWeight.w500,
- ),
- ),
- 4.verticalSpace,
- Text(
- item.description,
- style: TextStyle(
- fontSize: 12.sp,
- color: DarkThemeColors.hintTextColor,
- height: 1.7,
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- ),
- );
- }
- /// 构建图标或图片
- Widget _buildIconOrImage() {
- if (item.imageSource != null) {
- // 显示图片
- return IXImage(
- source: item.imageSource!,
- width: item.imageWidth ?? 20.w,
- height: item.imageHeight ?? 20.w,
- sourceType: _getImageSourceType(item.imageSource!),
- );
- } else {
- // 显示图标
- return Icon(
- item.icon,
- size: item.iconSize ?? 20.w,
- color: item.iconColor ?? Colors.white,
- );
- }
- }
- /// 判断图片资源类型
- ImageSourceType _getImageSourceType(String source) {
- if (source.startsWith('http://') || source.startsWith('https://')) {
- return ImageSourceType.network;
- } else if (source.startsWith('assets/')) {
- return ImageSourceType.asset;
- } else {
- return ImageSourceType.asset;
- }
- }
- }
|