鸿蒙项目《查询天气》

打印 上一主题 下一主题

主题 967|帖子 967|积分 2901

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
天气查询

一、项目目标

综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开辟一款具有实用性和创新
性的移动应用软件。
二、项目先容

根据高德地图获取都会天气数据,将今日天气状态和最近几天的天气状态可视化,即数据的内容转化为图标的情势,显现出来。可以选择地点的一个都会也可以选择多个都会大概删除之前所选的都会。
三、代码结构解读

├──entry/src/main/ets // 代码区
│ ├──pages
│ │ ├──index.ets // 启动页
│ │ ├──AddCity.ets // 添加都会页
│ ├──cityView
│ │ ├──cityView.ets // 今日和最近天气
│ ├──viewmodel
│ │ ├──casts.ets // 天气状态类
│ │ ├──forecasts.ets // 都会类
│ │ ├──WeatherModel.ets // 都会编号类
│ ├──resources/base/media //图片夹
│ │ ├──cloud.png //多云图标
│ │ ├──icon.png //软件图标
│ │ ├──rain.png //下雨图标
│ │ ├──sun.png //太阳图标
└──entry/src/main/resources // 资源文件夹
四、关键技能

Tabs组件都会切换

  1. import { cityView } from '../view/cityView'
  2. //.....
  3.   //tarBar 自定义函数
  4.   @Builder tabBuild(index: number) {
  5.     Circle({ width: 10, height: 10 })
  6.         .fill(this.cityIndex === index ? Color.White : Color.Gray).opacity(0.4)
  7.   }
  8. //城市切换
  9. Tabs({ barPosition: BarPosition.Start, controller: this.tancontroller }) {
  10.   ForEach(this.cityWeatherList, (cityWeatherList: WeatherModel) => {
  11.     TabContent() {
  12.       cityView({ casts: cityWeatherList.forecasts[0].casts })
  13.     }.tabBar(this.tabBuild(this.cityWeatherList.findIndex(obj => obj === cityWeatherList)))
  14.   })
  15. }
  16. .barHeight(20)
  17. .barWidth(40)
  18. .onChange((index: number) => {
  19.   this.cityIndex = index
  20. })
复制代码
五、实验过程

1.通过获取的数据,举行类的构建

在module.json5文件内加入代码
  1. "requestPermissions": [
  2.   {"name": "ohos.permission.INTERNET"}
  3. ],
复制代码
创建方法

通过异步获取,将数据以对象的情势返回
  1. //获取数据
  2. getWeather(cityCode:number){
  3.   return new Promise<WeatherModel>((resolve,reject)=>{
  4.     //创建
  5.     let request = http.createHttp()
  6.     let url= `https://restapi.amap.com/v3/weather/weatherInfo?key=<输入你申请的key值>&city=${cityCode}&extensions=all`
  7.     let options = {
  8.       method:http.RequestMethod.GET,
  9.       header:{'Content-Type':'application/json'},
  10.     } as http.HttpRequestOptions
  11.     let result = request.request(url,options)
  12.     result.then((res)=>{
  13.       if (res.responseCode === 200) {
  14.         console.log(res.result.toString())
  15.         resolve( JSON.parse(res.result.toString()))
  16.       }
  17.     }).catch((err)=>{
  18.       console.log(err)
  19.     })
  20.   })
  21. }
  22. 使用Promise.all方法,同时返回多条数据
  23. //直接获取所有数据
  24. async  getWeathers (cityCodeList:Array<number>){
  25.   let WeathersDate: Array<WeatherModel> = []
  26.   let promises :Array<Promise<WeatherModel>> = []
  27.   for (let i = 0; i < cityCodeList.length; i++) {
  28.     promises.push(this.getWeather(cityCodeList[i]))
  29.   }
  30.   await Promise.all(promises).then(result =>{
  31.     for (const element of result) {
  32.       console.log(element.forecasts[0].city);
  33.     }
  34.     WeathersDate = result
  35.   })
  36.   return WeathersDate
  37. }
复制代码
根据返回的json数据,创建相应的对象
  1. casts
  2. export class casts{
  3.   date:string
  4.   dayweather:string
  5.   nightweather:string
  6.   daytemp:number
  7.   nighttemp:number
  8.   daywind:string
  9.   daypower:string
  10.   daytemp_float:number
  11.   nighttemp_float:number
  12. }
  13. forecasts
  14. import {casts} from "../viewmodel/casts"
  15. export class forecasts{
  16.   city:string
  17.   adcode:number
  18.   casts:Array<casts>
  19. }
  20. WeatherModel
  21. import {forecasts} from "./forecasts"
  22. export class WeatherModel{
  23.   status:number
  24.   count:number
  25.   infocode:number
  26.   forecasts:Array<forecasts> = []
  27. }
复制代码
2.主页面举行构建,将添加按钮,删除按钮,以及多个都会名称滑动时对应起来,也就是显示的天气状态和都会名称保持一致

  1. 页面显示框
  2.   //当前tab组件索引
  3.   @State cityIndex: number = 0
  4. //城市选择+城市标题
  5. Row() {
  6.   Button("添加")
  7.     .fontSize(25)
  8.     .fontColor(Color.Gray)
  9.     .opacity(0.7)
  10.     .backgroundColor("#87CEEB")
  11.     .margin({ bottom: 15 })
  12.   Text(this.cityNameList[this.cityIndex])
  13.       .fontSize(40).fontColor(Color.Orange)
  14.   Button("删除")
  15.     .fontSize(25)
  16.     .fontColor(Color.Gray)
  17.     .opacity(0.7)
  18.     .backgroundColor("#87CEEB")
  19.     .margin({ bottom: 15 })
  20. }.height("10%")
  21. .width("100%")
  22. .justifyContent(FlexAlign.SpaceBetween)
复制代码
Tabs组件都会切换

  1. import { cityView } from '../view/cityView'
  2. //.....
  3.   //tarBar 自定义函数
  4.   @Builder tabBuild(index: number) {
  5.     Circle({ width: 10, height: 10 })
  6.         .fill(this.cityIndex === index ? Color.White : Color.Gray).opacity(0.4)
  7.   }
  8. //城市切换
  9. Tabs({ barPosition: BarPosition.Start, controller: this.tancontroller }) {
  10.   ForEach(this.cityWeatherList, (cityWeatherList: WeatherModel) => {
  11.     TabContent() {
  12.       cityView({ casts: cityWeatherList.forecasts[0].casts })
  13.     }.tabBar(this.tabBuild(this.cityWeatherList.findIndex(obj => obj === cityWeatherList)))
  14.   })
  15. }
  16. .barHeight(20)
  17. .barWidth(40)
  18. .onChange((index: number) => {
  19.   this.cityIndex = index
  20. })
复制代码
3.将主页面的今日天气和近期天气状态显示出来,将数据转化为图标

今日天气显示
遍历列表,索引为0的对象为今日天气数据
//当前都会天气
  1.   casts: casts[] = []
  2. ForEach(this.casts, (cast: casts) => {
  3.   if (cast === this.casts[0]) {
  4.         
  5.   }
  6. })
  7. 设置天气图片
  8. //图片
  9. Row() {
  10.   if (cast.dayweather === "晴") {
  11.     Image($r('app.media.sun')).width(260)
  12.   }
  13.   if (cast.dayweather === "多云") {
  14.     Image($r("app.media.cloud")).width(260)
  15.   }
  16.   if (cast.dayweather === "阴") {
  17.     Image($r("app.media.cloud")).width(260)
  18.   }
  19.   if (cast.dayweather.includes("雨")) {
  20.     Image($r("app.media.rain")).width(260)
  21.   }
  22. }.height("30%")
  23. 设置天气数据
  24. Column() {
  25.   //天气 温度
  26.   Row() {
  27.     Text(cast.dayweather).fontSize(30)
  28.         .fontColor(Color.White).fontWeight(FontWeight.Bold)
  29.     Text("  " + cast.daytemp + "°~" + cast.nighttemp + "°")
  30.       .fontSize(30)
  31.       .fontColor(Color.White)
  32.       .fontWeight(FontWeight.Bold)
  33.   }
  34.   //风力 等级
  35.   Row() {
  36.     Text(cast.daywind + "风  ").fontSize(30)
  37.         .fontColor(Color.White).fontWeight(FontWeight.Bold)
  38.     Text(cast.daypower + "级").fontSize(30)
  39.         .fontColor(Color.White).fontWeight(FontWeight.Bold)
  40.   }
  41. }.margin({ top: 10 })
复制代码
casts聚集内全部天气数据
天气图标自定义函数

  1. @Builder weatherImage(dayweather: string) {
  2.   if (dayweather === "晴") {
  3.     Image($r('app.media.sun')).width(30)
  4.   }
  5.   if (dayweather === "多云") {
  6.     Image($r("app.media.cloud")).width(30)
  7.   }
  8.   if (dayweather === "阴") {
  9.     Image($r("app.media.cloud")).width(30)
  10.   }
  11.   if (dayweather.includes("雨")) {
  12.     Image($r("app.media.rain")).width(30)
  13.   }
  14. }
  15. 近期天气列表
  16. //近期天气列表
  17. Column() {
  18.   Text("查看近期天气").fontSize(26).margin({ top: 30 })
  19.   //天气列表
  20.   Row() {
  21.     ForEach(this.casts, (cast: casts) => {
  22.       Column() {
  23.         Text(cast.date.substring(5))
  24.         this.weatherImage(cast.dayweather)
  25.         Blank()
  26.         Text(cast.daytemp.toString())
  27.         Line()
  28.         .width(20).height(80).startPoint([10, 0])
  29.         .endPoint([10, 70]).stroke(Color.Black)
  30.         .strokeWidth(3).strokeDashArray([10, 3])
  31.          
  32.         Text(cast.nighttemp.toString())
  33.         Blank()
  34.         this.weatherImage(cast.dayweather)
  35.       }.height("90%").width("20%")
  36.     })
  37.   }
  38.   .width("80%")
  39.   .height("60%")
  40.   .backgroundColor("#ffbab8b8")
  41.   .opacity(0.5)
  42.   .justifyContent(FlexAlign.SpaceAround)
  43. }.height("45%").width("100%")
复制代码
四、添加都会的页面,当点击添加时,将网络获取的数据都会,可以添加到主页面,将已经添加的和未添加的做标识,实现都会的添加

添加都会页面
  1. 添加城市跳转
  2. //主页面按钮跳转
  3. Button("添加")
  4. .onClick(() => {
  5.   router.pushUrl({
  6.     url: "pages/AddCity",
  7.     params: {
  8.       Codes: this.cityCodeList,
  9.       Names: this.cityNameList
  10.     }
  11.   })
  12. })
  13. //.....
  14. //添加城市页面接收数据
  15.   onPageShow(){
  16.     let params = router.getParams()
  17.     this.cityCodeList = params["Codes"]
  18.     this.cityNameList = params["Names"]
  19.   }
  20. 页面数据
  21. @State AllCityCodeList :Array<number> =
  22. [110000,120000,130000,140000,210000,220000,310000]
  23. @State AllCityNameList :Array<string> =
  24. ["北京市","天津市","河北省","山西省","辽宁省","吉林省","上海市"]
  25. //当前城市代码列表 接收传入数据的载体
  26. @State cityCodeList :Array<number> = []
  27. @State cityNameList :Array<string> = []
  28. 页面标头
  29. Row(){
  30.   Text("添加城市列表").fontSize(35).fontColor(Color.White)
  31.   Blank()
  32.   Button("完成").backgroundColor("").fontSize(26)
  33. }.height("10%").width("95%")
  34. 城市列表
  35. List遍历
  36. //城市列表
  37. Column() {
  38.   List() {
  39.     ForEach(this.AllCityNameList, (name: string) => {
  40.       ListItem() {
  41.         //写入单个城市名字
  42.       }
  43.     })
  44.   }
  45. }.width("100%").height("90%")
  46. 判断当前遍历的AllCityNameList元素是否包含在cityNameList集合中,并作出对应样式 ,方法调整
  47. if (this.cityNameList.includes(name)) {
  48.   Column() {
  49.     Row() {     Text(name).fontSize(35).fontColor(Color.White).width("60%")
  50.         .margin({ top: 20, left: 30 })
  51.       Blank()
  52.       Text("已添加").backgroundColor("").fontSize(18)
  53.         .margin({ right: 5 })
  54.         .opacity(0.8)
  55.     }.width("100%")
  56.     Blank()
  57.     Divider().strokeWidth(5)
  58.   }.height(90).width("100%").margin({ top: 20 })
  59.   .backgroundColor("#4682B4")
  60. } else {
  61.   Column() {
  62.     Row() {
  63.       Text(name).fontSize(35).fontColor(Color.White).width("60%")
  64.         .margin({ top: 20, left: 30 })
  65.       Blank()
  66.       Button("添加").backgroundColor("").fontSize(18)
  67.         .margin({ right: 5 })
  68.         .onClick(() => {
  69.           //根据name 获取所在索引
  70.           let index = this.AllCityNameList.findIndex(obj => obj === name)
  71.           console.log("index:"+index)
  72.           //根据索引获得 城市对应的编码
  73.           let cityCode: number = this.AllCityCodeList[index]
  74.           console.log("cityCode= "+cityCode)
  75.           //将编码加入列表
  76.           this.cityCodeList.push(cityCode)
  77.           this.cityNameList.push(name)
  78.           console.log(this.cityCodeList.toString())
  79.         })
  80.     }.width("100%")
  81.     Blank()
  82.     Divider().strokeWidth(5)
  83.   }.height(90).width("100%").margin({ top: 20 })
  84.   .backgroundColor("#87CEEB")
  85. }
  86. 页面返回
  87. Button("完成")
  88. .onClick(()=>{
  89.   router.back({
  90.     url:"pages/Index",
  91.     params:{
  92.       Codes:this.cityCodeList
  93.     }
  94.   })
  95. })
  96. //主界面接收数据
  97.   onPageShow() {
  98.     let params = router.getParams()
  99.     if (params) {
  100.       this.cityCodeList = params["Codes"]
  101.       this.cityWeatherList = []
  102.       this.cityNameList = []
  103.       this.initData()
  104.     }
  105.   }
复制代码
五、都会的删除,当点击删除按钮时,将弹出对话框,确认删除后,即可将当前的都会

  1. 城市删除方法
  2. Button("删除")
  3. .onClick(() => {
  4.   AlertDialog.show({ title: "删除",
  5.     message: `你确定要删除${this.cityNameList[this.cityIndex]}消息吗?`,
  6.     confirm: {
  7.       value: "确定",
  8.       action: () => {
  9.         this.cityNameList = this.cityNameList.filter(item => item !== this.cityNameList[this.cityIndex])
  10.         this.cityCodeList = this.cityCodeList.filter(item => item !== this.cityCodeList[this.cityIndex])
  11.         this.cityWeatherList = this.cityWeatherList.filter(item => item !== this.cityWeatherList[this.cityIndex])
  12.         
  13.       }
  14.     }
  15.   })
  16. })
复制代码
六、添加风力的卡片

  1. Text("风向风力").fontSize(26).margin({ top: 30 })
  2.       Row() {
  3.         ForEach(this.casts, (cast: casts, index: number) => {
  4.           // 风向风力内容
  5.           Column() {
  6.             Row() {
  7.               Image($r("app.media.wind")) // 假设 'app.media.wind' 是风力的图片资源
  8.                 .width(120) // 设置图片宽度
  9.                 .height(100) // 设置图片高度
  10.                 .margin({ right: 35 }) // 设置图片与右边距
  11.               Image($r("app.media.w2")) // 假设 'app.media.wind' 是风力的图片资源
  12.                 .width(120) // 设置图片宽度
  13.                 .height(100) // 设置图片高度
  14.                 .margin({ right: 35 })
  15.             }
  16.             .width("100%")
  17.               Text("风向:" + cast.daywind)
  18.                 .fontSize(24)
  19.                 .fontColor(Color.White)
  20.                 .fontWeight(FontWeight.Bold)
  21.                 .margin({ right: 20 }) // 右边距,根据需要调整
  22.             Text("风力:" + cast.daypower)
  23.               .fontSize(24)
  24.               .fontColor(Color.White)
  25.               .fontWeight(FontWeight.Bold)
  26.               .margin({ right: 20 })
  27.           }.margin({ top: 10 })
  28.           // 根据需要添加分隔线或间距
  29.           if (index !== this.casts.length - 1) {
  30.             Line().width("100%").height(1).stroke(Color.Black).strokeWidth(1)
  31.           }
  32.         })
  33.       }
  34.       .width("100%")
  35.       .height("45%")
  36.       .backgroundColor("#ffbab8b8")
  37.       .opacity(0.5)
  38.       .justifyContent(FlexAlign.SpaceAround)
  39.     }
  40.   }
  41. })
复制代码
七、将两个卡片实现滑动

  1. build() {
  2.     //单个tabcontent 展示的所有内容
  3.     Column() {
  4.       ForEach(this.casts, (cast: casts) => {
  5.         if (cast === this.casts[0]) {
  6.           //上半部分 图片+当天天气
  7.           //图片
  8.           Row() {
  9.             if (cast.dayweather === "晴") {
  10.               Image($r('app.media.sun')).width(260)
  11.             }
  12.             if (cast.dayweather === "多云") {
  13.               Image($r("app.media.cloud")).width(260)
  14.             }
  15.             if (cast.dayweather === "阴") {
  16.               Image($r("app.media.cloud")).width(260)
  17.             }
  18.             if (cast.dayweather.includes("雨")) {
  19.               Image($r("app.media.rain")).width(260)
  20.             }
  21.             if (cast.dayweather.includes("沙")) {
  22.               Image($r("app.media.sand")).width(260)
  23.             }
  24.           }.height("30%")
  25.           Column() {
  26.             //天气 温度
  27.             Row() {
  28.               Text(cast.dayweather).fontSize(30).fontColor(Color.White).fontWeight(FontWeight.Bold)
  29.               Text("  " + cast.daytemp + "°~" + cast.nighttemp + "°")
  30.                 .fontSize(30)
  31.                 .fontColor(Color.White)
  32.                 .fontWeight(FontWeight.Bold)
  33.             }
  34.             //风力 等级
  35.             Row() {
  36.               Text(cast.daywind + "风  ").fontSize(30).fontColor(Color.White).fontWeight(FontWeight.Bold)
  37.               Text(cast.daypower + "级").fontSize(30).fontColor(Color.White).fontWeight(FontWeight.Bold)
  38.             }
  39.           }.margin({ top: 10 })
  40.         }
  41.       })
  42.       List() {
  43.         ForEach(this.casts, (cast: casts, index: number) => {
  44.           ListItem() {
  45.             //近期天气列表
  46.             Column() {
  47.               Text("查看近期天气").fontSize(26).margin({ top: 30 })
  48.               //天气列表
  49.               Row() {
  50.                 ForEach(this.casts, (cast: casts) => {
  51.                   Column() {
  52.                     Text(cast.date.substring(5))
  53.                     this.weatherImage(cast.dayweather)
  54.                     Blank()
  55.                     Text(cast.daytemp.toString() + "°")
  56.                     Line()
  57.                       .width(20)
  58.                       .height(80)
  59.                       .startPoint([10, 0])
  60.                       .endPoint([10, 70])
  61.                       .stroke(Color.Black)
  62.                       .strokeWidth(3)
  63.                       .strokeDashArray([10, 3])
  64.                     Text(cast.nighttemp.toString() + "°")
  65.                     Blank()
  66.                     this.weatherImage(cast.dayweather)
  67.                   }.height("90%").width("20%")
  68.                 })
  69.               }
  70.               .width("100%")
  71.               .height("40%")
  72.               .backgroundColor("#ffbab8b8")
  73.               .opacity(0.5)
  74.               .justifyContent(FlexAlign.SpaceAround)
  75. .padding({left:15,right:15})
  76. .margin({bottom:35})
  77.               Text("风向风力").fontSize(26).margin({ top: 30 })
  78.               Row() {
  79.                 ForEach(this.casts, (cast: casts, index: number) => {
  80.                   // 风向风力内容
  81.                   Column() {
  82.                     Row() {
  83.                       Image($r("app.media.wind")) // 假设 'app.media.wind' 是风力的图片资源
  84.                         .width(120) // 设置图片宽度
  85.                         .height(100) // 设置图片高度
  86.                         .margin({ right: 35 }) // 设置图片与右边距
  87.                       Image($r("app.media.w2")) // 假设 'app.media.wind' 是风力的图片资源
  88.                         .width(120) // 设置图片宽度
  89.                         .height(100) // 设置图片高度
  90.                         .margin({ right: 35 })
  91.                     }
  92.                     .width("100%")
  93.                       Text("风向:" + cast.daywind)
  94.                         .fontSize(24)
  95.                         .fontColor(Color.White)
  96.                         .fontWeight(FontWeight.Bold)
  97.                         .margin({ right: 20 }) // 右边距,根据需要调整
  98.                     Text("风力:" + cast.daypower)
  99.                       .fontSize(24)
  100.                       .fontColor(Color.White)
  101.                       .fontWeight(FontWeight.Bold)
  102.                       .margin({ right: 20 })
  103.                   }.margin({ top: 10 })
  104.                   // 根据需要添加分隔线或间距
  105.                   if (index !== this.casts.length - 1) {
  106.                     Line().width("100%").height(1).stroke(Color.Black).strokeWidth(1)
  107.                   }
  108.                 })
  109.               }
  110.               .width("100%")
  111.               .height("45%")
  112.               .backgroundColor("#ffbab8b8")
  113.               .opacity(0.5)
  114.               .justifyContent(FlexAlign.SpaceAround)
  115.             }
  116.           }
  117.         })
  118.       }
  119.       .width("90%").height("80%")
  120.     }
  121.     .width("100%")
  122.     .height("100%")
  123.   }}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表