1# 使用Badge组件完成聊天未读消息数量显示功能
2
3## 场景介绍
4开发者在业务开发过程中,需要通过角标的形式对用户的通知信息进行提示,并展示具体数量,如聊天页面中,用户可以看到与其他聊天对象的未读消息数量。本文就从聊天页面未读消息数量展示场景出发,介绍OpenHarmony中如何使用Badge组件实现该场景。
5
6## 效果呈现
7
8如下动图所示:
9![效果图](./figures/badge.gif)
10
11
12## 环境要求
13本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
14- IDE: DevEco Studio 4.0 Release
15- SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release)
16
17## 实现原理
18
19本例涉及的关键特性以及实现方案如下:
20
21- 完成聊天列表子组件创建,其中头像部分放入容器组件Badge中。
22- 封装聊天列表子组件类,并引用@Observed装饰器,保证类中未读聊天信息数量数据状态可被观察。
23- 最后,通过ForEach组件完成聊天聊表的内容渲染。
24
25## 开发步骤
26
271. 聊天列表组件,包含三部分:聊天对象的头像,聊天对象昵称,用户聊天记录最后一条详情。其中未读聊天信息数量显示在头像的右上角。因此头像部分需要放入容器组件Badge中。Badge中需要设置消息数量,提示显示位置,最大消息数量,显示样式。
28    聊天列表组件代码如下:
29    ```ts
30    @Component
31    struct MyComposeTitleBar {
32      @ObjectLink simplifyChatInfo: SimplifyChatInfo;
33
34      build() {
35        Row() {
36          Badge({
37            count: this.simplifyChatInfo.notReadCount,
38            maxCount: 99,
39            position:BadgePosition.RightTop,
40            style: { badgeSize: 15, badgeColor: '#FA2A2D' }
41          }) {
42            Image($r('app.media.ic_user_portrait')).width(50).height(50)
43          }
44          .width(50)
45          .height(50)
46      .margin({ bottom: 4 })
47
48          Row() {
49            Column() {
50              Text(this.simplifyChatInfo.chaterNickName)
51                .fontSize(36)
52                .fontWeight(FontWeight.Bold)
53                .width("70%")
54                .textOverflow({ overflow: TextOverflow.Clip })
55                .maxLines(1)
56              Text(this.simplifyChatInfo.details)
57                .fontSize(24)
58                .fontWeight(FontWeight.Normal)
59                .width("90%")
60                .textOverflow({ overflow: TextOverflow.Ellipsis })
61                .maxLines(1)
62              Divider().color(Color.Gray).strokeWidth(1).lineCap(LineCapStyle.Round)
63            }.alignItems(HorizontalAlign.Start)
64          }.margin({left:15})
65      }.backgroundColor('#d7ffffff')
66    }
67    }
68    ```
69
70
713. 创建用于表征聊天列表数据的类,该类需要被@Observed修饰,是的类中数据可以被Badge组件观察。
72
73   聊天列表数据类代码块:
74
75   ```ts
76   @Observed
77   class SimplifyChatInfo {
78     public chaterNickName: string;
79     public details: string;
80     //未读消息数量
81     public notReadCount: number;
82
83     constructor(chaterNickName: string, details: string, notReadCount: number) {
84       this.chaterNickName = chaterNickName
85       this.details = details
86       this.notReadCount = notReadCount
87     }
88   }
89   ```
90
913. 最后通过ForEach完成数据渲染。
92
93   ```ts
94   List() {
95     ForEach(this.chatArr, (item: SimplifyChatInfo) => {
96       ListItem() {
97         MyComposeTitleBar({ simplifyChatInfo: item })
98       }
99     })
100   }
101   ```
102
103
104## 完整实例
105
106完整实例代码如下:
107
108```ts
109@Entry
110@Component
111export default struct HarmonyChat {
112  @State chatArr: Array<SimplifyChatInfo> = []
113  scroller: Scroller = new Scroller()
114
115  build() {
116    Row() {
117      Column() {
118        Text('聊天列表页').fontSize(30).fontWeight(FontWeight.Bold).height("20%")
119          .margin({
120            top: 16,
121            bottom: 16
122          })
123
124        Scroll(this.scroller) {
125          Column() {
126            List() {
127              ForEach(this.chatArr, (item: SimplifyChatInfo) => {
128                ListItem() {
129                  MyComposeTitleBar({ simplifyChatInfo: item })
130                }
131              })
132            }
133          }.height("80%")
134        }
135
136      }.width('100%')
137    }.alignItems(VerticalAlign.Center)
138    .backgroundColor("#f1f3f5")
139    .height('100%')
140  }
141
142  aboutToAppear() {
143    //模拟数据
144    for (let i = 0; i < 3; i++) {
145      let sci: SimplifyChatInfo = new SimplifyChatInfo(
146        "nickName" + 111 * i,
147        `你好!` + "nickName" + 111 * i + "!!!",
148        0
149      )
150      this.chatArr.push(sci)
151    }
152    setInterval(() => {
153      let date = new Date()
154      let second = date.getSeconds()
155      this.chatArr[second%3].notReadCount = this.chatArr[second%3].notReadCount + 1
156    }, 1000)
157  }
158}
159
160@Component
161struct MyComposeTitleBar {
162  @ObjectLink simplifyChatInfo: SimplifyChatInfo;
163
164  build() {
165    Row() {
166      Badge({
167        count: this.simplifyChatInfo.notReadCount,
168        maxCount: 99,
169        position:BadgePosition.RightTop,
170        style: { badgeSize: 20, badgeColor: '#FA2A2D',fontSize:15 }
171      }) {
172        Image($r('app.media.ic_user_portrait')).width(50).height(50)
173      }
174      .width(50)
175      .height(50)
176      .margin({ bottom: 4 })
177
178      Row() {
179        Column() {
180          Text(this.simplifyChatInfo.chaterNickName)
181            .fontSize(36)
182            .fontWeight(FontWeight.Bold)
183            .width("70%")
184            .textOverflow({ overflow: TextOverflow.Clip })
185            .maxLines(1)
186          Text(this.simplifyChatInfo.details)
187            .fontSize(24)
188            .fontWeight(FontWeight.Normal)
189            .width("90%")
190            .textOverflow({ overflow: TextOverflow.Ellipsis })
191            .maxLines(1)
192          Divider().color(Color.Gray).strokeWidth(1).lineCap(LineCapStyle.Round)
193        }.alignItems(HorizontalAlign.Start)
194      }.margin({left:15})
195    }.backgroundColor('#d7ffffff')
196  }
197}
198
199
200@Observed
201class SimplifyChatInfo {
202  public chaterNickName: string;
203  public details: string;
204  //未读消息数量
205  public notReadCount: number;
206
207  constructor(chaterNickName: string, details: string, notReadCount: number) {
208    this.chaterNickName = chaterNickName
209    this.details = details
210    this.notReadCount = notReadCount
211  }
212}
213```
214
215## 参考
216
217[Badge](../application-dev/reference/apis-arkui/arkui-ts/ts-container-badge.md)
218
219[@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化](../application-dev/quick-start/arkts-observed-and-objectlink.md)
220
221[ForEach:循环渲染](../application-dev/quick-start/arkts-rendering-control-foreach.md)
222
223
224
225