企业网的配置优化
2026/6/15 18:30:52
天气应用是移动端常见应用类型之一。本项目实现以下功能:
| 功能模块 | 技术要点 |
|---|---|
| 实时天气展示 | 状态绑定、数据驱动 |
| 动态主题切换 | 条件渐变背景 |
| 生活指数展示 | @Builder组件复用 |
| 逐小时/7日预报 | 列表渲染、数据生成 |
| 城市切换 | 模态弹窗、状态联动 |
// 天气主数据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}项目采用本地模拟数据,支持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:'优'},// ... 其他城市数据]@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[]}城市切换时,所有状态同步更新:
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}根据天气状况动态计算渐变色:
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 | 清新凉爽 |
温度条宽度与颜色根据温度动态计算:
// 宽度计算:基于温差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'// 绿色-凉}逐小时预报:
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]}))}@Builder用于封装可复用的UI描述,支持参数传递。
@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)}@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)}@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})}@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))}Stack ├── Scroll (主内容) │ └── Column │ ├── Column (天气展示区 - 渐变背景) │ ├── Row (信息卡片) │ ├── Column (逐小时预报) │ ├── Column (7天预报) │ └── Text (更新时间) └── Column (城市选择弹窗 - 条件渲染)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)}# DevEco Studio菜单Build>Build Hap(s)/APP(s)>Build Hap(s)| 技术点 | 实现方式 |
|---|---|
| 状态驱动 | @State装饰器 |
| 组件复用 | @Builder装饰器 |
| 动态主题 | 条件渐变背景 |
| 温度可视化 | 动态宽度+颜色计算 |
| 模态弹窗 | Stack叠加+条件渲染 |
| 数据生成 | 随机算法+基准值偏移 |
| 扩展项 | 技术方案 |
|---|---|
| 真实API | HTTP请求 + JSON解析 |
| 地理定位 | @ohos.geoLocationManager |
| 数据缓存 | @ohos.data.preferences |
| 天气动画 | Canvas / Lottie |
| 下拉刷新 | Refresh组件 |
本文详细讲解了鸿蒙天气App的实现过程,涵盖动态主题、数据可视化、组件封装等核心内容。通过本项目,可快速掌握ArkUI声明式开发的核心范式。
参考资料: