#盲盒+码##深入浅出学习eTs#(十六)主人来电话了 原创 精华

发布于 2022-11-24 13:22
浏览
3收藏

【本文正在参加「盲盒」+码有奖征文活动】https://ost.51cto.com/posts/19288

本项目Gitee仓地址:深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com)

一、需求分析

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区
相信大家都接过电话吧,咳咳,本节来模拟一个不喜欢接电话的小朋友,在切换界面上加上小红点,具体的通话界面之后可能会做

  • 实现页面切换
  • 不同页面显示不同内容
  • 可显示角标(小红点)

二、控件介绍

(1)Tabs

一种可以通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。

说明:

该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

接口

Tabs(value?: {barPosition?: BarPosition, index?: number, controller?: TabsController})

参数:

参数名 参数类型 必填 参数描述
barPosition BarPosition 指定页签位置来创建Tabs容器组件。 默认值:BarPosition.Start
index number 指定初次初始页签索引。 默认值:0
controller TabsController 设置Tabs控制器。

BarPosition枚举说明

名称 描述
Start vertical属性方法设置为true时,页签位于容器左侧;vertical属性方法设置为false时,页签位于容器顶部。
End vertical属性方法设置为true时,页签位于容器右侧;vertical属性方法设置为false时,页签位于容器底部。

属性

不支持触摸热区设置,除支持通用属性外,还支持以下属性:

名称 参数类型 描述
vertical boolean 设置为false是为横向Tabs,设置为true时为纵向Tabs。 默认值:false
scrollable boolean 设置为true时可以通过滑动页面进行页面切换,为false时不可滑动切换页面。 默认值:true
barMode BarMode TabBar布局模式,具体描述见BarMode枚举说明。 默认值:BarMode.Fixed
barWidth number | Length8+ TabBar的宽度值。
barHeight number | Length8+ TabBar的高度值。
animationDuration number TabContent滑动动画时长。 默认值:200

BarMode枚举说明

名称 描述
Scrollable TabBar使用实际布局宽度, 超过总长度后可滑动。
Fixed 所有TabBar平均分配宽度。

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

(2)TabContentOpenAtom OpenHarmony

仅在Tabs中使用,对应一个切换页签的内容视图。

说明:

该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

属性

除支持通用属性外,还支持以下属性:

名称 参数类型 描述
tabBar string | Resource | { icon?: string | Resource, text?: string | Resource } | CustomBuilder8+ 设置TabBar上显示内容。 CustomBuilder: 构造器,内部可以传入组件(API8版本以上适用)。 > 说明: > 如果icon采用svg格式图源,则要求svg图源删除其自有宽高属性值。如采用带有自有宽高属性的svg图源,icon大小则是svg本身内置的宽高属性值大小。

说明:

  • TabContent组件不支持设置通用宽度属性,其宽度默认撑满Tabs父组件。
  • TabContent组件不支持设置通用高度属性,其高度由Tabs父组件高度与TabBar组件高度决定。
  • TabContent组件不支持触摸热区设置

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

// xxx.ets
@Entry
@Component
struct TabContentExample  {
  @State fontColor: string = 'rgba(0, 0, 0, 0.4)'
  @State selectedFontColor: string = 'rgba(10, 30, 255, 1)'
  @State currentIndex: number = 0
  private controller: TabsController = new TabsController()
  @Builder TabBuilder(index: number) {
    Column() {
      Image(this.currentIndex === index ? '/resources/ic_public_contacts_filled_selected.png' : '/resources/ic_public_contacts_filled.png')
        .width(10)
        .height(10)
        .opacity(this.currentIndex === index ? 1 : 0.4)
        .objectFit(ImageFit.Contain)
      Text(`Tab${(index > 2 ? (index - 1) : index) + 1}`)
        .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
        .fontSize(10)
        .margin({top: 2})
    }
  }

  @Builder AddBuilder() {
    Column() {
      Image(this.currentIndex === 2 ? '/resources/ic_public_add_norm_filled_selected.png' : '/resources/ic_public_add_norm_filled.png')
        .width(this.currentIndex === 2 ? 26 : 24)
        .height(this.currentIndex === 2 ? 26 : 24)
        .opacity(this.currentIndex === 2 ? 1 : 0.4)
        .objectFit(ImageFit.Contain)
        .animation({duration: 200})
    }
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
        TabContent() {
          Flex({justifyContent: FlexAlign.Center}) {
            Text('Tab1').fontSize(32)
          }
        }.tabBar(this.TabBuilder(0))

        TabContent() {
          Flex({justifyContent: FlexAlign.Center}) {
            Text('Tab2').fontSize(32)
          }
        }.tabBar(this.TabBuilder(1))

        TabContent() {
          Flex({justifyContent: FlexAlign.Center}) {
            Text('Add').fontSize(32)
          }
        }.tabBar(this.AddBuilder())

        TabContent() {
          Flex({justifyContent: FlexAlign.Center}) {
            Text('Tab3').fontSize(32)
          }
        }.tabBar(this.TabBuilder(3))

        TabContent() {
          Flex({justifyContent: FlexAlign.Center}) {
            Text('Tab4').fontSize(32)
          }
        }.tabBar(this.TabBuilder(4))
      }
      .vertical(false)
      .barWidth(300).barHeight(56)
      .onChange((index: number) => {
        this.currentIndex = index
      })
      .width('90%').backgroundColor('rgba(241, 243, 245, 0.95)')
    }.width('100%').height(200).margin({ top: 5 })
  }
}

(3)BadgeOpenAtom OpenHarmony

可以附加在单个组件上用于信息标记的容器组件。

说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。

Badge({
  value: ' ',
  position: BadgePosition.Left,                // 设置 badge 居左显示
  style: {badgeSize: 10, badgeColor: Color.Red}// 设置 badge 的显示样式
}) {
  Text("Badge")
    .size({width: 100, height: 50})
    .fontSize(20)
    .backgroundColor("#aabbcc")
}
.size({width: 100, height: 50})

Badge({
  value: ' ',
  position: BadgePosition.Right,               // 设置 badge 居右显示
  style: {badgeSize: 10, badgeColor: Color.Red}// 设置 badge 的显示样式
}) {
  Text("Badge")
    .size({width: 100, height: 50})
    .fontSize(20)
    .backgroundColor("#aabbcc")
}
.size({width: 100, height: 50})

Badge({
  value: ' ',
  position: BadgePosition.RightTop,            // 设置 badge 居右上角显示
  style: {badgeSize: 10, badgeColor: Color.Red}// 设置 badge 的显示样式
}) {
  Text("Badge")
    .size({width: 100, height: 50})
    .fontSize(20)
    .backgroundColor("#aabbcc")
}
.size({width: 100, height: 50})

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

三、UI设计

(1)页面切换

首先需要创建一个TabContent组件,实现页面切换
#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

@Entry @Component struct TabsTest {

  private controller: TabsController = new TabsController();

  @State index: number = 0; // 选项卡下标,默认为第一个

  @Builder tabMessage() {   // 自定义消息标签
    Column() {
      Column() {
        Blank()
        Image(this.index == 0 ? 'pages/icon_message_selected.png' : 'pages/icon_message_normal.png')
          .size({width: 25, height: 25})
        Text('消息')
          .fontSize(16)
          .fontColor(this.index == 0 ? "#2a58d0" : "#6b6b6b")
        Blank()
      }
      .height('100%')
      .width("100%")
      .onClick(() => {
        this.index = 0;
        this.controller.changeIndex(this.index);
      })
    }
  }

  @Builder tabContract() {  // 自定义联系人标签
    Column() {
      Blank()
      Image(this.index == 1 ? 'pages/icon_contract_selected.png' : 'pages/icon_contract_normal.png')
        .size({width: 25, height: 25})
      Text('联系人')
        .fontSize(16)
        .fontColor(this.index == 1 ? "#2a58d0" : "#6b6b6b")
      Blank()
    }
    .height('100%')
    .width("100%")
    .onClick(() => {
      this.index = 1;
      this.controller.changeIndex(this.index);
    })
  }

  @Builder tabDynamic() {   // 自定义动态标签
    Column() {
      Blank()
      Image(this.index == 2 ? 'pages/icon_dynamic_selected.png' : 'pages/icon_dynamic_normal.png')
        .size({width: 25, height: 25})
      Text('动态')
        .fontSize(16)
        .fontColor(this.index == 2 ? "#2a58d0" : "#6b6b6b")
      Blank()
    }
    .height('100%')
    .width("100%")
    .onClick(() => {
      this.index = 2;
      this.controller.changeIndex(this.index);
    })
  }

  build() {
    Column() {
      Tabs({
        barPosition: BarPosition.End, // TabBar排列在下方
        controller: this.controller   // 绑定控制器
      }) {
        TabContent() {
          Column() {
            Text('消息')
              .fontSize(30)
          }
          .width('100%')
          .height('100%')
          .backgroundColor("#aabbcc")
        }
        .tabBar(this.tabMessage)      // 使用自定义TabBar

        TabContent() {
          Column() {
            Text('联系人')
              .fontSize(30)
          }
          .width('100%')
          .height('100%')
          .backgroundColor("#bbccaa")
        }
        .tabBar(this.tabContract)     // 使用自定义TabBar

        TabContent() {
          Column() {
            Text('动态')
              .fontSize(30)
          }
          .width('100%')
          .height('100%')
          .backgroundColor("#ccaabb")
        }
        .tabBar(this.tabDynamic)      // 使用自定义TabBar
      }
      .width('100%')
      .height('100%')
      .barHeight(60)
      .barMode(BarMode.Fixed)         // TabBar均分
      .onChange((index: number) => {  // 页面切换回调
        this.index = index;
      })
    }
    .width('100%')
    .height('100%')
  }
}

(2)图标修改

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区
在Tab组件中,图标需要选择两种风格,一个是没有点击到的,另一个是被选中的状态,我这里使用本色和红色来演示
#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区
#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

(3)角标添加

这里加入传统的角标颜色,小红点来实现,当前未接电话有14个
#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

  @Builder tabMessage() {   // 自定义消息标签
    Badge({
      count: 14,                       // 设置 badge 显示的数量
      maxCount: 100,                   // 设置 badge 显示的最大数量
      position: BadgePosition.RightTop,// 设置 badge 显示在右上角
      style: {badgeColor: Color.Red,fontSize:15,badgeSize:30}   // 设置 badge 的显示样式
       }) {

      Column() {
        Column() {
          Blank()
          Image(this.index == 0 ? 'pages/电话2.png' : 'pages/电话.png')
            .size({ width: 25, height: 25 })
          Text('电话')
            .fontSize(16)
            .fontColor(this.index == 0 ? "#2a58d0" : "#6b6b6b")
          Blank()
        }
        .height('100%')
        .width("100%")
        .onClick(() => {
          this.index = 0;
          this.controller.changeIndex(this.index);
        })
      }
    }
  }

四、成功展示

#盲盒+码##深入浅出学习eTs#(十六)主人来电话了-开源基础软件社区

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
4
收藏 3
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐