OpenHarmony开源社区
直播中

翁嘉杰

1年用户 204经验值
擅长:控制/MCU
私信 关注

【汇思博SEEK100开发板试用体验】05 天气app开发--支持24小时+7天天气预报

demo

1 前言

这次接着开发天气APP,上次已经实现了从和风天气获取实时、24h以及7天的天气数据了,但只是将实时数据显示出来。这次要完成24h和7天的数据显示,用到List和Scroll容器。

2 List组件

2.1 介绍

列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。

使用列表可以轻松高效地显示结构化、可滚动的信息。通过在List组件中按垂直或者水平方向线性排列子组件ListItemGroup或ListItem,为列表中的行或列提供单个视图,或使用循环渲染迭代一组行或列,或混合任意数量的单个视图和ForEach结构,构建一个列表。List组件支持使用条件渲染、循环渲染、懒加载等渲染控制方式生成子组件。

2.2 布局

列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。

如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。

ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。

布局关系.png

2.3 设置主轴方向

List组件主轴默认是垂直方向,即默认情况下不需要手动设置List方向,就可以构建一个垂直滚动列表。

若是水平滚动列表场景,将List的listDirection属性设置为Axis.Horizontal即可实现。listDirection默认为Axis.Vertical,即主轴默认是垂直方向。

List() {
  // ...
}
.listDirection(Axis.Horizontal)

2.4 使用forEach迭代列表内容

通常,应用通过数据集合动态地创建列表。使用循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件,降低代码复杂度。

ArkTS通过ForEach提供了组件的循环渲染能力。以简单形式的联系人列表为例,将联系人名称和头像数据以Contact类结构存储到contacts数组,使用ForEach中嵌套ListItem的形式来代替多个平铺的、内容相似的ListItem,从而减少重复代码。

示例

build() {
    List() {
      ForEach(this.contacts, (item: Contact) => {
        ListItem() {
          Row() {
            Image(item.icon)
              .width(40)
              .height(40)
              .margin(10)
            Text(item.name).fontSize(20)
          }
          .width('100%')
          .justifyContent(FlexAlign.Start)
        }
      }, (item: Contact) => JSON.stringify(item))
    }
    .width('100%')
  }

3 Scroll容器

3.1 基本介绍

Scroll是可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。

  • 从API version 7开始支持,后续版本新增内容会用上角标标记起始版本。
  • 嵌套List子组件滚动时,若List不设置宽高则默认全部加载,对性能有要求的场景建议指定List的宽高。
  • 滚动的前提是主轴方向大小小于内容大小。
  • 通用属性clip的默认值为true。
  • 支持单个子组件。

3.2 接口

接口 描述
Scroll(scroller?: Scroller) 创建Scroll滚动容器。scroller为可滚动组件的控制器,用于与可滚动组件绑定,不允许和其他滚动类组件绑定同一个滚动控制对象。从API version 11开始支持在原子化服务中使用。

3.3 属性

除支持通用属性和滚动组件通用属性外,还支持以下属性:

属性 类型 说明 原子化服务API支持版本
scrollable (value: ScrollDirection) 设置滚动方向,默认值为ScrollDirection.Vertical。 11+
scrollBar (barState: BarState) 设置滚动条状态,若容器组件无法滚动或子组件大小为无穷大,滚动条不显示或不支持拖动和伴随滚动。从API version 10开始,滚动组件有圆角时,滚动条会自动计算避让距离。 11+
scrollBarColor (color: Color number string)
scrollBarWidth (value: number string) 设置滚动条的宽度,不支持百分比设置。宽度设置后,正常和按压状态宽度均为此值,若超过Scroll组件主轴方向的高度则变为默认值。默认值为4vp,取值范围:小于0按默认值处理,0时不显示滚动条。
scrollSnap^{10+} (value: ScrollSnapOptions) 设置Scroll组件的限位滚动模式。 11+
edgeEffect (edgeEffect: EdgeEffect, options?: EdgeEffectOptions) 设置边缘滑动效果,支持弹簧效果和阴影效果,默认值为EdgeEffect.None。options(11+)用于设置组件内容大小小于自身时是否开启滑动效果,默认{ alwaysEnabled: true }。 11+
enableScrollInteraction^{10+} (value: boolean) 设置是否支持滚动手势,true时可通过手指或鼠标滚动,false时不行,但不影响控制器Scroller的滚动接口,默认值为true。 11+
nestedScroll^{10+} (value: NestedScrollOptions) 设置前后两个方向的嵌套滚动模式,实现与父组件的滚动联动,默认值为{ scrollForward: NestedScrollMode.SELF_ONLY, scrollBackward: NestedScrollMode.SELF_ONLY }。 11+
friction^{10+} (value: number Resource) 设置摩擦系数,手动划动滚动区域时生效,仅影响惯性滚动过程。默认值:非可穿戴设备11+为0.7,12+为0.75;可穿戴设备为0.9。取值范围:(0, +∞),小于等于0按默认值处理。
enablePaging^{11+} (value: boolean) 设置是否支持划动翻页,若同时设置划动翻页和限位滚动,限位滚动优先生效。默认值为false。 12+
initialOffset^{12+} (value: OffsetOptions) 设置初始滚动偏移量,只在首次布局时生效,后续动态修改不生效。输入为百分比时,偏移量为Scroll组件主轴方向大小与百分比数值之积。 12+

4 代码实现

4.1 Index.ets

新增了Scroll容器,然后将实时数据、24h、7天的数据都封装进单独的组件中,以保持主页代码的整洁。

build() {
    Scroll() {
      Column() {
        // 实时天气数据
        nowWeatherDataComponent({
          selectCity: $selectCity,
          cityArr: $cityArr,
          weatherNow: $weatherNow,
          weatherUiModel: $weatherUiModel,
          readDataSuccess: $readDataSuccess
        })
          .margin({ bottom: 10 })
        //24小时天气数据
        weatherData24hComponent({
          readDataSuccess:$readDataSuccess,
          weatherUiModel:$weatherUiModel
        })
          .margin({ bottom: 10 })
        //7天 天气数据
        weatherData7dComponent({
          weatherUiModel:$weatherUiModel,
          readDataSuccess:$readDataSuccess
        })
          .margin({ bottom: 10 })

      }
    }
    .scrollable(ScrollDirection.Vertical) // 滚动方向为垂直方向
    .scrollBar(BarState.Off) // 滚动条不显示
    .edgeEffect(EdgeEffect.None)
    .backgroundColor('#ffdee0e0')
  }

4.2 weatherData24hComponent 组件

获取24h天气数据代码如下,其中使用到了forEach遍历来创建ListItem的方式,精简代码。

export struct  weatherData24hComponent {
  @Link readDataSuccess: boolean
  @Link weatherUiModel :WeatherUiModel
  build() {
    if (this.readDataSuccess == true) {
      //未来24小时预报
      List() {
        ForEach(this.weatherUiModel.hoursArr, (hour: string, index: number) => {
          ListItem() {
            Column({ space: 15 }) {
              // 显示温度
              Text(this.weatherUiModel.hourlyTemp[index] + '℃')
                .textAlign(TextAlign.Center)
                .fontSize(16)
                .height(20)
              // 显示天气图标
              Image($rawfile((this.weatherUiModel.hourlyIcon[index].toString() + '.svg')))
                .height(16)
                .width(16)
              // 显示降水概率
              if(this.weatherUiModel.hourlyRain[index]>0){
                Text(this.weatherUiModel.hourlyRain[index] + '%')
                  .textAlign(TextAlign.Center)
                  .fontSize(16)
                  .height(20)
                  .fontColor('#ff3176bc')
              }
              else{
                Text(this.weatherUiModel.hourlyRain[index] + '%')
                  .textAlign(TextAlign.Center)
                  .fontSize(16)
                  .height(20)
                  .fontColor(Color.Gray)
              }
              // 显示时间(小时)
              Text(hour)
                .textAlign(TextAlign.Center)
                .fontSize(16)
                .height(20)
            }
            .margin({ bottom: 5, top: 5 })
          }
          .width(80)
          .height(150)
        })
      }
      .listDirection(Axis.Horizontal)
      .backgroundColor(Color.White)
      .borderRadius(15)
      .width('90%')
      .height(150)
    } else {
      Row() {
        Text('无数据')
          .fontSize(20)
          .fontColor(Color.Gray)
      }
      .justifyContent(FlexAlign.Center)
      .backgroundColor(Color.White)
      .borderRadius(15)
      .width('90%')
      .height(150)
    }
  }
}

4.3 weatherData7dComponent

获取7天天气的组件代码如下

@Component
export struct  weatherData7dComponent {
  @Link weatherUiModel: WeatherUiModel
  @Link readDataSuccess: boolean
  @State selectDay: string = '今天';
  build() {
    if (this.readDataSuccess == true){
      Column() {
        // 天气icon
        Row() {
          ForEach(this.weatherUiModel.iconDays, (item:number) => {
            Column() {
              Image($rawfile((item.toString()+'.svg')))
                .size({ width: 24, height: 24 })
            }
            .align(Alignment.Center)
            .layoutWeight(1)
          })
        }
        .margin({top:5})
        //最高温
        Row() {
          ForEach(this.weatherUiModel.tempDayMax, (item:number) => {
            Column() {
              Text(item.toString()+ '°')
                .fontSize(14)
                .fontColor('#ffec9e0d')
            }
            .align(Alignment.Center)
            .layoutWeight(1)
          })
        }
        //最低温
        Row() {
          ForEach(this.weatherUiModel.tempDayMin, (item:number) => {
            Column() {
              Text(item.toString()+ '°')
                .fontSize(14)
                .fontColor('#ff2b8de2')
            }
            .align(Alignment.Center)
            .layoutWeight(1)
          })
        }

        // 日期
        Row() {
          ForEach(this.weatherUiModel.dayArr, (item:string) => {
            Column() {
              if (item == this.selectDay) {
                Text(item)
                  .fontColor(Color.White)
                  .textAlign(TextAlign.Center)
                  .height(40)
                  .width(40)
                  .border({ radius: 40 })
                  .fontSize(14)
                  .backgroundColor(Color.Black)
              } else {
                Text(item)
                  .textAlign(TextAlign.Center)
                  .height(40)
                  .width(40)
                  .fontSize(14)
              }
            }
            .layoutWeight(1)
            .align(Alignment.Center)
          })
        }
        .margin({bottom:5})
      }
      .width('90%')
      .backgroundColor(Color.White)
      .borderRadius(15)
      .height(150)
      .justifyContent(FlexAlign.SpaceAround)
    }
    else{
      Column(){
        Text('无数据')
          .fontSize(20)
          .fontColor(Color.Gray)
      }
      .justifyContent(FlexAlign.Center)
      .width('90%')
      .backgroundColor(Color.White)
      .borderRadius(15)
      .height(150)
    }
  }
}

5 实机演示

基本数据展示多加了相对湿度和云量的展示

实机演示1.png

24小时数据以及7天数据的显示

实机演示2.png

更多回帖

发帖
×
20
完善资料,
赚取积分