You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
9.0 KiB
313 lines
9.0 KiB
import 'package:common_utils/common_utils.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// 构建天气内容卡片
|
|
Widget buildWeatherContent(BuildContext context, String city,
|
|
Map<String, dynamic> now, List<Map<String, dynamic>> days) {
|
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'查询天气情况:',
|
|
style: TextStyle(
|
|
color: isDarkMode ? Colors.white.withOpacity(0.9) : Colors.black87,
|
|
fontSize: 14,
|
|
height: 1.4,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Container(
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
gradient: isDarkMode
|
|
? LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [Color(0xFF1E40AF), Color(0xFF1E3A8A)],
|
|
)
|
|
: LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [Color(0xFF60A5FA), Color(0xFF3B82F6)],
|
|
),
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(isDarkMode ? 0.3 : 0.1),
|
|
blurRadius: 8,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"${city} ${now["date"]}",
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
SizedBox(height: 4),
|
|
Text(
|
|
now["dayweather"],
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: Colors.white.withOpacity(0.9),
|
|
),
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
"${now["daytemp"]}°",
|
|
style: const TextStyle(
|
|
fontSize: 36,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
SizedBox(width: 8),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'最高: ${now["daytemp"]}°',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.white.withOpacity(0.9),
|
|
),
|
|
),
|
|
Text(
|
|
'最低: ${now["nighttemp"]}°',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.white.withOpacity(0.9),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
Icon(
|
|
getWeatherIcon(now['dayweather']),
|
|
size: 48,
|
|
color: Colors.white,
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 16),
|
|
Container(
|
|
height: 1,
|
|
color: Colors.white.withOpacity(isDarkMode ? 0.15 : 0.2),
|
|
),
|
|
SizedBox(height: 16),
|
|
const Text(
|
|
'未来预报',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
SizedBox(height: 8),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: List.generate(
|
|
days.length,
|
|
(index) {
|
|
String dateStr = days[index]['date'];
|
|
DateTime? date = DateUtil.getDateTime(dateStr);
|
|
IconData weatherIcon =
|
|
getWeatherIcon(days[index]['dayweather']);
|
|
String weekday = DateUtil.getWeekday(date,
|
|
languageCode: "zh", short: true);
|
|
String temp = "${days[index]['daytemp']}°";
|
|
return _buildForecastDay(
|
|
weekday,
|
|
weatherIcon,
|
|
temp,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
SizedBox(height: 16),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
|
decoration: BoxDecoration(
|
|
color: isDarkMode
|
|
? Colors.white.withOpacity(0.15)
|
|
: Colors.white.withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: const Row(
|
|
children: [
|
|
Icon(
|
|
Icons.info_outline,
|
|
size: 16,
|
|
color: Colors.white,
|
|
),
|
|
SizedBox(width: 8),
|
|
Flexible(
|
|
child: Text(
|
|
'今日紫外线指数较高,外出请做好防晒',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
/// 构建单日天气预报
|
|
Widget _buildForecastDay(String day, IconData icon, String temp) {
|
|
return Column(
|
|
children: [
|
|
Text(
|
|
day,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: Colors.white.withOpacity(0.9),
|
|
),
|
|
),
|
|
SizedBox(height: 4),
|
|
Icon(
|
|
icon,
|
|
size: 20,
|
|
color: Colors.white,
|
|
),
|
|
SizedBox(height: 4),
|
|
Text(
|
|
temp,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
/// 获取天气图标
|
|
IconData getWeatherIcon(String description) {
|
|
description = description.trim();
|
|
|
|
if (["晴", "少云", "晴间多云"].contains(description)) {
|
|
return Icons.wb_sunny;
|
|
}
|
|
|
|
if (["多云", "阴"].contains(description)) {
|
|
return Icons.cloud;
|
|
}
|
|
|
|
if (description.contains("雾") ||
|
|
["雾", "浓雾", "强浓雾", "轻雾", "大雾", "特强浓雾", "霾", "中度霾", "重度霾", "严重霾"]
|
|
.contains(description)) {
|
|
return Icons.blur_on;
|
|
}
|
|
|
|
if (description.contains("风") ||
|
|
[
|
|
"有风",
|
|
"平静",
|
|
"微风",
|
|
"和风",
|
|
"清风",
|
|
"强风/劲风",
|
|
"疾风",
|
|
"大风",
|
|
"烈风",
|
|
"风暴",
|
|
"狂爆风",
|
|
"飓风",
|
|
"热带风暴"
|
|
].contains(description)) {
|
|
return Icons.air;
|
|
}
|
|
|
|
if (description.contains("雨") ||
|
|
[
|
|
"阵雨",
|
|
"雷阵雨",
|
|
"雷阵雨并伴有冰雹",
|
|
"小雨",
|
|
"中雨",
|
|
"大雨",
|
|
"暴雨",
|
|
"大暴雨",
|
|
"特大暴雨",
|
|
"强阵雨",
|
|
"强雷阵雨",
|
|
"极端降雨",
|
|
"毛毛雨/细雨",
|
|
"雨",
|
|
"小雨-中雨",
|
|
"中雨-大雨",
|
|
"大雨-暴雨",
|
|
"暴雨-大暴雨",
|
|
"大暴雨-特大暴雨"
|
|
].contains(description)) {
|
|
return Icons.grain; // 或使用 community icon 包:weather_icons 中的 rain
|
|
}
|
|
|
|
if (description.contains("雪") ||
|
|
[
|
|
"雨雪天气",
|
|
"雨夹雪",
|
|
"阵雨夹雪",
|
|
"冻雨",
|
|
"雪",
|
|
"阵雪",
|
|
"小雪",
|
|
"中雪",
|
|
"大雪",
|
|
"暴雪",
|
|
"小雪-中雪",
|
|
"中雪-大雪",
|
|
"大雪-暴雪"
|
|
].contains(description)) {
|
|
return Icons.ac_unit;
|
|
}
|
|
|
|
if (["浮尘", "扬沙", "沙尘暴", "强沙尘暴"].contains(description)) {
|
|
return Icons.filter_drama;
|
|
}
|
|
|
|
if (["龙卷风"].contains(description)) {
|
|
return Icons.waves;
|
|
}
|
|
|
|
if (["热"].contains(description)) {
|
|
return Icons.local_fire_department;
|
|
}
|
|
|
|
if (["冷"].contains(description)) {
|
|
return Icons.ac_unit;
|
|
}
|
|
|
|
// 默认或未知天气
|
|
return Icons.help_outline;
|
|
}
|
|
|