feat:更新主题色适配

This commit is contained in:
2025-11-23 15:27:50 +08:00
parent 6308169013
commit 245edd9d27
15 changed files with 306 additions and 128 deletions

View File

@@ -4,50 +4,54 @@ import 'package:flutter/material.dart';
InputDecoration buildInputDecoration({
required BuildContext context,
required String hintText,
Widget? prefixIcon,
required IconData prefixIcon,
}) {
final colors = Theme.of(context).colorScheme;
return InputDecoration(
hintText: hintText,
hintStyle: const TextStyle(
color: Color(0xFF999999),
fontSize: 15,
height: 1.2,
),
hintStyle: TextStyle(color: colors.onSurface.withAlpha(100)),
filled: true,
fillColor: Colors.white,
fillColor: colors.surface,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
borderRadius: BorderRadius.circular(8),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 1.5),
borderSide: BorderSide(color: colors.primary, width: 2),
borderRadius: BorderRadius.circular(8),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.red, width: 1.5),
borderSide: const BorderSide(color: Colors.red, width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.symmetric(horizontal: 15, vertical: 14),
errorStyle: const TextStyle(fontSize: 12, height: 1, color: Colors.red),
prefixIcon: prefixIcon,
prefixIcon: Icon(prefixIcon, size: 20, color: Color(0xFF86909C)),
prefixIconConstraints: const BoxConstraints(minWidth: 40),
isDense: true,
);
}
Widget buildFormLabel(String text, {bool required = false}) {
Widget buildFormLabel({
required BuildContext context,
required String text,
required bool isRequired,
}) {
final colors = Theme.of(context).colorScheme;
return RichText(
text: TextSpan(
text: text,
style: const TextStyle(
color: Color(0xFF1D2129),
style: TextStyle(
color: colors.onSurface,
fontSize: 16,
fontWeight: FontWeight.w500,
fontFamily: 'CustomFont',
height: 1.2,
),
children: [
if (required)
if (isRequired)
const TextSpan(
text: ' *',
style: TextStyle(color: Colors.red, fontSize: 16),
@@ -60,12 +64,19 @@ Widget buildFormLabel(String text, {bool required = false}) {
/// 表单底部按钮组组件
Widget buildFormButtonGroup({
required BuildContext context,
required bool isShowDelete,
required VoidCallback onConfirm,
required VoidCallback onDelete,
}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: _buildCancelButton(context)),
const SizedBox(width: 16),
if (isShowDelete) ...[
SizedBox(width: 16),
Expanded(child: _buildDeleteButton(context, onDelete)),
],
SizedBox(width: 16),
Expanded(child: _buildSubmitButton(context, onConfirm)),
],
);
@@ -76,9 +87,8 @@ Widget _buildCancelButton(BuildContext context) {
return ElevatedButton(
onPressed: () => Navigator.pop(context), // 直接使用传入的context返回
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
backgroundColor: Theme.of(context).colorScheme.surface,
foregroundColor: const Color(0xFF4E5969),
side: const BorderSide(color: Color(0xFFDCDFE6)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
elevation: 0,
),
@@ -98,3 +108,16 @@ Widget _buildSubmitButton(BuildContext context, VoidCallback onConfirm) {
child: const Text('提交', style: TextStyle(color: Colors.white)),
);
}
/// 删除按钮
Widget _buildDeleteButton(BuildContext context, VoidCallback onDelete) {
return ElevatedButton(
onPressed: () => onDelete(),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
elevation: 0,
),
child: const Text('删除', style: TextStyle(color: Colors.white)),
);
}

View File

@@ -203,7 +203,12 @@ class ImagePreview extends StatelessWidget {
}
}
Widget buildImageUploadButton({required VoidCallback onTap}) {
Widget buildImageUploadButton({
required BuildContext context,
required VoidCallback onTap,
}) {
final colors = Theme.of(context).colorScheme;
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(8),
@@ -211,16 +216,16 @@ Widget buildImageUploadButton({required VoidCallback onTap}) {
width: 96,
height: 96,
decoration: BoxDecoration(
color: Colors.white,
color: colors.surface,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.black),
),
child: const Column(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add, color: Color(0xFF86909C)),
Icon(Icons.add, color: colors.onSurface.withAlpha(100)),
SizedBox(height: 6),
Text('添加图片', style: TextStyle(color: Color(0xFF86909C))),
Text('添加图片', style: TextStyle(color: colors.onSurface.withAlpha(100))),
],
),
),

View File

@@ -146,42 +146,47 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
bool isToday,
FoodProvider provider,
) {
final colors = Theme.of(context).colorScheme;
// 检查当前日期是否在需要显示红点的列表中
bool shouldShowRedDot = provider.recordList.any(
(item) => item.date == formatDateTime(day),
);
late Color boxColor;
if (isSelected) {
boxColor = colors.secondary;
} else {
boxColor = isToday ? colors.primary : Colors.transparent;
}
late Color textColor;
if (isSelected) {
textColor = colors.surface;
} else {
textColor = isToday ? colors.surface : colors.onSurface;
}
return Container(
width: 40,
height: 40,
margin: EdgeInsets.all(2),
decoration: BoxDecoration(
color:
isSelected
? Theme.of(context).primaryColor
: isToday
? Colors.grey[300]
: Colors.transparent,
shape: BoxShape.circle,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
decoration: BoxDecoration(color: boxColor, shape: BoxShape.circle),
child: Stack(
alignment: Alignment.center,
children: [
// 日期数字
Text(
day.day.toString(),
style: TextStyle(color: isSelected ? Colors.white : Colors.black),
),
// 底部红点 - 只在指定日期显示
// 日期数字始终居中
Text(day.day.toString(), style: TextStyle(color: textColor)),
// 红点
if (shouldShowRedDot)
Container(
margin: EdgeInsets.only(top: 2),
width: 6,
height: 6,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
Align(
alignment: Alignment(0, 0.8),
child: Container(
width: 6,
height: 6,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
),
],

View File

@@ -31,7 +31,6 @@ class _RecipeListState extends State<RecipeList> {
decoration: BoxDecoration(
color: colors.surfaceContainer,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey[200]!),
),
padding: EdgeInsets.symmetric(horizontal: 16),
child: DropdownButton<String>(
@@ -64,15 +63,28 @@ class _RecipeListState extends State<RecipeList> {
);
}).toList(),
onChanged: (value) {
setState(() {
provider.queryCategory = value!;
provider.refreshRecipeList();
});
provider.queryCategory = value!;
provider.refreshRecipeList();
},
),
);
}
Widget _buildRecipeList(FoodProvider provider) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 0.9,
),
itemCount: provider.recipeSummaryList.length,
itemBuilder: (context, index) {
return RecipeCard(recipe: provider.recipeSummaryList[index]);
},
);
}
Widget _buildContent(FoodProvider provider) {
if (provider.recipeSummaryList.isEmpty) {
return buildEmptyData();
@@ -81,20 +93,7 @@ class _RecipeListState extends State<RecipeList> {
children: [
_buildSelectCategory(provider),
SizedBox(height: 5),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // 每行2个
crossAxisSpacing: 8, // 水平间距
mainAxisSpacing: 8, // 垂直间距
childAspectRatio: 0.9,
),
itemCount: provider.recipeSummaryList.length,
itemBuilder: (context, index) {
return RecipeCard(recipe: provider.recipeSummaryList[index]);
},
),
),
Expanded(child: _buildRecipeList(provider)),
],
);
}

View File

@@ -56,20 +56,17 @@ class _RecipeTimeline extends State<RecipeTimeline> {
if (recordList.isEmpty) {
return buildEmptyData();
} else {
final colors = Theme.of(context).colorScheme;
return Timeline.tileBuilder(
theme: TimelineThemeData(nodePosition: 0, indicatorPosition: 0),
builder: TimelineTileBuilder.connected(
itemCount: recordList.length,
connectorBuilder:
(context, index, type) => Connector.solidLine(
thickness: 2,
color: Theme.of(context).colorScheme.primary,
),
(context, index, type) =>
Connector.solidLine(thickness: 2, color: colors.primary),
indicatorBuilder: (context, index) {
return Indicator.dot(
size: 12.0,
color: Theme.of(context).colorScheme.primary,
);
return Indicator.dot(size: 12.0, color: colors.primary);
},
contentsBuilder: (context, index) {
return Padding(