【鸿蒙ArkUI】天气App开发实践——动态主题与数据可视化实现
2026/6/15 14:14:50 网站建设 项目流程

一、技术背景

1.1 项目概述

天气应用是移动端常见应用类型之一。本项目实现以下功能:

功能模块技术要点
实时天气展示状态绑定、数据驱动
动态主题切换条件渐变背景
生活指数展示@Builder组件复用
逐小时/7日预报列表渲染、数据生成
城市切换模态弹窗、状态联动

1.2 技术栈

  • 框架:ArkUI
  • 语言:ArkTS
  • 模型:Stage Model
  • 工具:DevEco Studio

二、数据模型设计

2.1 接口定义

// 天气主数据interfaceWeatherInfo{city:stringtemp:numbercond:stringhumid:numberwind:stringuv:stringhigh:numberlow:numberaqi:numberaqiDesc:string}// 小时预报interfaceHourlyItem{time:stringtemp:numbericon:string}// 日预报interfaceDailyItem{day:stringdate:stringicon:stringhigh:numberlow:numberdesc:string}

2.2 数据源

项目采用本地模拟数据,支持8个城市:

privatereadonlyCITIES:string[]=['北京市','上海市','广州市','深圳市','杭州市','成都市','武汉市','南京市']privatereadonlyWEATHER_DATA:WeatherInfo[]=[{city:'北京市',temp:26,cond:'晴',humid:45,wind:'3级',uv:'中等',high:30,low:18,aqi:72,aqiDesc:'良'},{city:'上海市',temp:24,cond:'多云',humid:62,wind:'4级',uv:'中等',high:27,low:20,aqi:55,aqiDesc:'良'},{city:'广州市',temp:31,cond:'雷阵雨',humid:78,wind:'3级',uv:'强',high:33,low:25,aqi:38,aqiDesc:'优'},// ... 其他城市数据]

三、状态管理

3.1 状态变量定义

@Entry@Componentstruct Index{// 基础天气信息@Statelocation:string='北京市'@StatecurrentTemp:number=26@StatecurrentCondition:string='晴'// 生活指数@StatecurrentHumidity:number=45@StatecurrentWind:string='3级'@StatecurrentUV:string='中等'// 温度范围@StatecurrentHigh:number=30@StatecurrentLow:number=18// 空气质量@StatecurrentAQI:number=72@StatecurrentAQIDesc:string='良'// UI状态@StateshowCityPicker:boolean=false// 预报数据@StatehourlyData:HourlyItem[]@StatedailyData:DailyItem[]}

3.2 状态联动机制

城市切换时,所有状态同步更新:

privateswitchCity(city:string):void{constdata=this.getWeatherByCity(city)// 批量状态更新this.location=citythis.currentTemp=data.tempthis.currentCondition=data.condthis.currentHumidity=data.humidthis.currentWind=data.windthis.currentUV=data.uvthis.currentHigh=data.highthis.currentLow=data.lowthis.currentAQI=data.aqithis.currentAQIDesc=data.aqiDesc// 重新生成预报数据this.hourlyData=this.generateHourlyData(data.cond,data.temp)this.dailyData=this.generateDailyData(data.cond,data.high,data.low)// 关闭弹窗this.showCityPicker=false}

四、核心实现

4.1 动态渐变背景

根据天气状况动态计算渐变色:

privategetBgGradient(cond:string):string{constgradientMap:Record<string,string>={'晴':'#FF9F0A','多云':'#8E8E93','阴':'#8E8E93','小雨':'#5AC8FA','阵雨':'#5AC8FA','雷阵雨':'#5AC8FA'}returngradientMap[cond]||'#4A90D9'}privategetBgEnd(cond:string):string{constendMap:Record<string,string>={'晴':'#FFD60A','多云':'#636366','阴':'#636366','小雨':'#007AFF','阵雨':'#007AFF','雷阵雨':'#007AFF'}returnendMap[cond]||'#87CEEB'}

应用渐变:

Column(){// ...}.linearGradient({direction:GradientDirection.Bottom,colors:[[this.getBgGradient(this.currentCondition),0],[this.getBgEnd(this.currentCondition),1]]})

主题效果:

天气起始色结束色视觉效果
#FF9F0A#FFD60A温暖明亮
多云/阴#8E8E93#636366沉稳内敛
#5AC8FA#007AFF清新凉爽

4.2 温度条可视化

温度条宽度与颜色根据温度动态计算:

// 宽度计算:基于温差privatetempBarWidth(low:number,high:number):string{constdiff=high-lowconstwidth=Math.floor((diff/20)*100+20)returnwidth+'%'}// 颜色计算:基于平均温度privatetempBarColor(low:number,high:number):string{constavg=(low+high)/2if(avg>=28)return'#FF3B30'// 红色-热if(avg>=20)return'#FF9F0A'// 橙色-温return'#34C759'// 绿色-凉}

4.3 数据生成算法

逐小时预报:

privategenerateHourlyData(cond:string,baseTemp:number):HourlyItem[]{consttimes=['现在','15:00','18:00','21:00','00:00','03:00','06:00','09:00']consticons=['🌙','🌙','🌤️','☀️','☀️','☀️','🌤️','🌙']returntimes.map((time,i)=>({time,temp:i===0?baseTemp:baseTemp+Math.floor(Math.random()*6)-3,icon:icons[i]}))}

7日预报:

privategenerateDailyData(cond:string,high:number,low:number):DailyItem[]{constdays=['今天','明天','周三','周四','周五','周六','周日']consticons=['☀️','⛅','🌧️','☁️','☀️','☀️','⛅']constdescs=['晴','多云','小雨','阴','晴','晴','多云']returndays.map((day,i)=>({day,date:'6月'+(i+1)+'日',icon:icons[i],high:high+Math.floor(Math.random()*6)-3,low:low+Math.floor(Math.random()*4)-2,desc:descs[i]}))}

五、组件封装

5.1 @Builder装饰器

@Builder用于封装可复用的UI描述,支持参数传递。

5.2 信息卡片组件

@BuildercompactCard(icon:string,value:string,desc:string,color:string){Column(){Text(icon).fontSize(20)Text(value).fontSize(16).fontWeight(FontWeight.Bold).fontColor(Color.White).margin({top:6})if(desc.length>0){Text(desc).fontSize(12).fontColor(color).margin({top:2})}}.layoutWeight(1).padding({top:10,bottom:10}).alignItems(HorizontalAlign.Center)}

5.3 小时预报项组件

@BuilderhourlyItem(item:HourlyItem){Column(){Text(item.time).fontSize(12).fontColor('#8E8E93')Text(item.icon).fontSize(22).margin({top:6})Text(String(item.temp)+'°').fontSize(15).fontWeight(FontWeight.Medium).fontColor(Color.White).margin({top:6})}.padding({left:10,right:10}).alignItems(HorizontalAlign.Center)}

5.4 日预报行组件

@BuilderdailyRow(item:DailyItem){Row(){Text(item.day).fontSize(15).fontColor(Color.White).width(48)Text(item.icon).fontSize(18).width(30)Text(item.desc).fontSize(14).fontColor('#8E8E93').width(36)Blank()Text(String(item.low)+'°').fontSize(14).fontColor('#8E8E93').width(32).textAlign(TextAlign.End)// 温度条容器Column(){Column().width(this.tempBarWidth(item.low,item.high)).height(6).borderRadius(3).backgroundColor(this.tempBarColor(item.low,item.high))}.width(60).height(6).backgroundColor('#333333').borderRadius(3).margin({left:4,right:4})Text(String(item.high)+'°').fontSize(14).fontColor(Color.White).width(32).textAlign(TextAlign.End)}.width('100%').padding({left:16,right:16,top:6,bottom:6})}

5.5 城市按钮组件

@BuildercityButton(city:string){Button(city).fontSize(14).fontWeight(FontWeight.Medium).height(44).borderRadius(22).backgroundColor(this.location===city?'#FF9F0A':'#2C2C2E').fontColor(this.location===city?Color.White:'#8E8E93').layoutWeight(1).margin({left:4,right:4}).onClick(()=>this.switchCity(city))}

六、页面布局

6.1 布局结构

Stack ├── Scroll (主内容) │ └── Column │ ├── Column (天气展示区 - 渐变背景) │ ├── Row (信息卡片) │ ├── Column (逐小时预报) │ ├── Column (7天预报) │ └── Text (更新时间) └── Column (城市选择弹窗 - 条件渲染)

6.2 模态弹窗实现

if(this.showCityPicker){Column(){Column(){Text('选择城市').fontSize(20).fontWeight(FontWeight.Bold).fontColor(Color.White).margin({top:20,bottom:16})Row(){this.cityButton(this.CITIES[0])this.cityButton(this.CITIES[1])this.cityButton(this.CITIES[2])this.cityButton(this.CITIES[3])}.width('100%').padding({left:12,right:12})Row(){this.cityButton(this.CITIES[4])this.cityButton(this.CITIES[5])this.cityButton(this.CITIES[6])this.cityButton(this.CITIES[7])}.width('100%').padding({left:12,right:12}).margin({top:8})Button('取消').fontSize(16).fontColor('#FF9F0A').backgroundColor('#2C2C2E').width('90%').height(44).borderRadius(22).margin({top:16,bottom:20}).onClick(()=>this.showCityPicker=false)}.width('85%').backgroundColor('#1C1C1E').borderRadius(20)}.width('100%').height('100%').backgroundColor('#80000000').justifyContent(FlexAlign.Center).onClick(()=>this.showCityPicker=false)}

七、运行验证

7.1 构建命令

# DevEco Studio菜单Build>Build Hap(s)/APP(s)>Build Hap(s)

7.2 运行效果





八、技术要点总结

技术点实现方式
状态驱动@State装饰器
组件复用@Builder装饰器
动态主题条件渐变背景
温度可视化动态宽度+颜色计算
模态弹窗Stack叠加+条件渲染
数据生成随机算法+基准值偏移

九、扩展方向

扩展项技术方案
真实APIHTTP请求 + JSON解析
地理定位@ohos.geoLocationManager
数据缓存@ohos.data.preferences
天气动画Canvas / Lottie
下拉刷新Refresh组件

十、结语

本文详细讲解了鸿蒙天气App的实现过程,涵盖动态主题、数据可视化、组件封装等核心内容。通过本项目,可快速掌握ArkUI声明式开发的核心范式。


参考资料:

  1. ArkUI开发指南
  2. HarmonyOS应用开发文档

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询