[HarmonyOS NEXT 实战案例三:SideBarContainer] 侧边栏容器实战:社交应用联系人列表 基础篇

2025-06-11 23:34:29
110次阅读
0个评论

[HarmonyOS NEXT 实战案例三:SideBarContainer] 侧边栏容器实战:社交应用联系人列表 基础篇

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

image.png

一、SideBarContainer组件回顾

1.1 SideBarContainer组件概述

SideBarContainer是HarmonyOS NEXT提供的一个双区域容器组件,专为实现侧边栏布局而设计。它通过子组件定义侧边栏和内容区:

  • 第一个子组件表示侧边栏
  • 第二个子组件表示内容区

这种布局模式非常适合社交应用的联系人列表与聊天窗口并列显示的场景,能够提供良好的用户体验。

1.2 SideBarContainer的显示模式

SideBarContainer支持三种显示模式,通过构造函数参数SideBarContainerType指定:

显示模式 说明 适用场景
Embed 侧边栏嵌入到组件内,和内容区并列显示 平板、桌面等大屏设备
Overlay 侧边栏浮在内容区上面 手机等小屏设备
Auto 根据容器宽度自动选择Embed或Overlay模式 需要适配多种屏幕尺寸的应用

在社交应用中,我们选择Embed模式,这样用户可以同时看到联系人列表和聊天内容,提高操作效率。

二、社交应用联系人列表实战

2.1 需求分析

社交应用的联系人侧边栏通常需要以下功能:

  • 左侧侧边栏显示联系人列表,包含头像、名称和未读消息数
  • 右侧内容区显示当前选中联系人的聊天内容
  • 支持搜索联系人
  • 点击联系人可以切换聊天对象
  • 显示未读消息数量,点击后清除未读状态

2.2 数据模型设计

首先,我们定义联系人数据模型:

// 类型定义
interface Contact {
    name: string
    avatar: Resource
    unread: number
}

这个接口包含三个属性:

  • name:联系人名称
  • avatar:头像资源
  • unread:未读消息数量

2.3 代码实现

下面是社交应用联系人侧边栏的完整代码实现:

// 社交应用联系人侧边栏 - 精简优化版

@Component
export struct SocialContacts {
    @State isSideBarShow: boolean = true
    @State currentChat: string = '群聊'
    @State contacts: Contact[] = [
        { name: '群聊', avatar: $r('app.media.big8'), unread: 3 },
        { name: '张三', avatar: $r('app.media.big7'), unread: 0 },
        { name: '李四', avatar: $r('app.media.big6'), unread: 5 },
        { name: '王五', avatar: $r('app.media.big5'), unread: 1 }
    ]

    build() {
        SideBarContainer(SideBarContainerType.Embed) {
            // 侧边栏 - 联系人列表(核心功能)
            Column() {
                Search({ placeholder: '搜索联系人' })
                    .width('90%')
                    .margin(10)

                List() {
                    ForEach(this.contacts, (item: Contact) => {
                        ListItem() {
                            ContactItem({
                                contact: item,
                                isActive: this.currentChat === item.name
                            })
                        }
                        .onClick(() => {
                            this.currentChat = item.name
                            item.unread = 0 // 点击后清除未读
                        })
                    })
                }
                .divider({ strokeWidth: 1, color: '#f0f0f0' })
                .width('100%')
                .layoutWeight(1)
            }
            .width('30%')
            .backgroundColor('#ffffff')

            // 主内容区 - 聊天窗口(简洁展示)
            Column() {
                ContactItem({
                    contact: this.contacts[0],
                    isActive: this.currentChat === this.contacts[0].name
                })
            }
        }
        .sideBarPosition(SideBarPosition.Start)
        .controlButton({ left: 10, top: 50 })
    }
}

// 子组件:联系人项
@Component
struct ContactItem {
    @Prop contact: Contact
    @Prop isActive: boolean

    build() {
        Row() {
            // 头像+未读标记
            Stack() {
                Image(this.contact.avatar)
                    .width(40)
                    .height(40)
                    .borderRadius(20)

                if (this.contact.unread > 0) {
                    Text(this.contact.unread.toString())
                        .width(20)
                        .height(20)
                        .borderRadius(10)
                        .backgroundColor('#ff0000')
                        .fontColor(Color.White)
                        .textAlign(TextAlign.Center)
                        .position({ x: '80%', y: '0%' })
                }
            }
            .margin(10)

            // 联系人信息
            Column() {
                Text(this.contact.name)
                    .fontSize(16)
                    .fontColor(this.isActive ? '#007aff' : '#000000')

                Text('最后消息...')
                    .fontSize(12)
                    .fontColor('#999999')
            }
            .layoutWeight(1)
        }
        .width('100%')
        .backgroundColor(this.isActive ? '#f5f5f5' : '#ffffff')
    }
}

三、代码详解

3.1 组件结构

我们使用@Component装饰器定义了两个自定义组件:

  1. SocialContacts:主组件,包含整个社交应用的侧边栏布局
  2. ContactItem:子组件,用于渲染单个联系人项

SocialContacts组件中,我们定义了三个状态变量:

  • isSideBarShow:控制侧边栏的显示和隐藏
  • currentChat:当前选中的聊天对象
  • contacts:联系人数组,包含示例数据

3.2 SideBarContainer配置

build方法中,我们使用SideBarContainer组件作为根容器,并设置其显示模式为Embed

SideBarContainer(SideBarContainerType.Embed) {
    // 侧边栏内容
    // 主内容区
}
.sideBarPosition(SideBarPosition.Start)
.controlButton({ left: 10, top: 50 })

我们通过链式调用设置了以下属性:

  • sideBarPosition(SideBarPosition.Start):设置侧边栏显示在左侧
  • controlButton({ left: 10, top: 50 }):设置控制按钮的位置

3.3 侧边栏内容

侧边栏内容是SideBarContainer的第一个子组件,我们使用Column组件作为容器,包含一个搜索框和一个联系人列表:

Column() {
    Search({ placeholder: '搜索联系人' })
        .width('90%')
        .margin(10)

    List() {
        ForEach(this.contacts, (item: Contact) => {
            ListItem() {
                ContactItem({
                    contact: item,
                    isActive: this.currentChat === item.name
                })
            }
            .onClick(() => {
                this.currentChat = item.name
                item.unread = 0 // 点击后清除未读
            })
        })
    }
    .divider({ strokeWidth: 1, color: '#f0f0f0' })
    .width('100%')
    .layoutWeight(1)
}
.width('30%')
.backgroundColor('#ffffff')

这里我们使用了以下组件和技术:

  • Search:搜索框组件,用于搜索联系人
  • List:列表容器,用于显示联系人列表
  • ForEach:遍历联系人数组,为每个联系人创建一个列表项
  • ContactItem:自定义组件,用于渲染单个联系人项
  • onClick:为每个列表项添加点击事件处理函数,用于切换当前聊天对象和清除未读消息

3.4 主内容区

主内容区是SideBarContainer的第二个子组件,在这个简化版本中,我们只显示当前选中的联系人信息:

Column() {
    ContactItem({
        contact: this.contacts[0],
        isActive: this.currentChat === this.contacts[0].name
    })
}

在实际应用中,这里应该显示完整的聊天界面,包括消息历史、输入框等。

3.5 联系人项组件

ContactItem是一个自定义组件,用于渲染单个联系人项,包含头像、名称、未读消息数和最后一条消息:

@Component
struct ContactItem {
    @Prop contact: Contact
    @Prop isActive: boolean

    build() {
        Row() {
            // 头像+未读标记
            Stack() {
                Image(this.contact.avatar)
                    .width(40)
                    .height(40)
                    .borderRadius(20)

                if (this.contact.unread > 0) {
                    Text(this.contact.unread.toString())
                        .width(20)
                        .height(20)
                        .borderRadius(10)
                        .backgroundColor('#ff0000')
                        .fontColor(Color.White)
                        .textAlign(TextAlign.Center)
                        .position({ x: '80%', y: '0%' })
                }
            }
            .margin(10)

            // 联系人信息
            Column() {
                Text(this.contact.name)
                    .fontSize(16)
                    .fontColor(this.isActive ? '#007aff' : '#000000')

                Text('最后消息...')
                    .fontSize(12)
                    .fontColor('#999999')
            }
            .layoutWeight(1)
        }
        .width('100%')
        .backgroundColor(this.isActive ? '#f5f5f5' : '#ffffff')
    }
}

这个组件使用了以下技术:

  • @Prop装饰器:定义组件的输入属性,包括联系人数据和是否处于活动状态
  • Stack组件:用于在头像上叠加显示未读消息数
  • 条件渲染:只有当未读消息数大于0时才显示未读消息标记
  • 动态样式:根据isActive属性动态设置文本颜色和背景色

四、布局技巧与最佳实践

4.1 侧边栏宽度设置

在社交应用中,侧边栏宽度需要合理设置,既要显示足够的联系人信息,又不能占用太多空间。在示例中,我们将侧边栏宽度设置为容器宽度的30%:

.width('30%')

这样可以根据屏幕大小自动调整侧边栏宽度,提供更好的适配性。

4.2 未读消息标记

未读消息标记是社交应用的重要功能,我们使用Stack组件在头像上叠加显示未读消息数:

Stack() {
    Image(this.contact.avatar)
        .width(40)
        .height(40)
        .borderRadius(20)

    if (this.contact.unread > 0) {
        Text(this.contact.unread.toString())
            .width(20)
            .height(20)
            .borderRadius(10)
            .backgroundColor('#ff0000')
            .fontColor(Color.White)
            .textAlign(TextAlign.Center)
            .position({ x: '80%', y: '0%' })
    }
}

这种设计既直观又美观,用户可以一目了然地看到哪些联系人有未读消息。

4.3 活动状态显示

当用户选中一个联系人时,我们需要通过视觉效果明确指示当前活动的联系人。在示例中,我们通过改变文本颜色和背景色来实现:

.fontColor(this.isActive ? '#007aff' : '#000000')
.backgroundColor(this.isActive ? '#f5f5f5' : '#ffffff')

这种设计可以帮助用户快速识别当前正在聊天的对象。

4.4 搜索功能

在联系人较多的情况下,搜索功能是必不可少的。我们在侧边栏顶部添加了一个搜索框:

Search({ placeholder: '搜索联系人' })
    .width('90%')
    .margin(10)

在实际应用中,需要实现搜索逻辑,根据用户输入过滤联系人列表。

五、总结

本教程详细介绍了如何使用HarmonyOS NEXT的SideBarContainer组件实现社交应用的联系人侧边栏布局。通过合理的组件结构和状态管理,我们实现了一个简洁而功能完备的联系人列表,包括搜索框、联系人项、未读消息标记和活动状态显示等功能。 SideBarContainer组件为开发者提供了一种简单而强大的方式来实现侧边栏布局,特别适合社交应用这种需要同时显示列表和详情的场景。通过合理使用这个组件,可以创建出用户体验良好的应用界面。 在下一篇教程中,我们将深入探讨如何为社交应用添加更多交互功能和状态管理,包括消息发送、接收、状态同步等功能,敬请期待!

收藏00

登录 后评论。没有帐号? 注册 一个。

全栈若城

  • 0回答
  • 4粉丝
  • 0关注