开源地址 github.com/7-bit-zhang…
导读:
话不多说直接上效果图
模块解析
首先可以分为两个大模块
1.最上方的头像appbar
2.搜索以及下面的list列表
为什么我会这样分呢,因为按照QQ上面的功能来讲滚动List列表的时候 搜索框会跟着一起滚动,那么我们就得把他看为一个整体
接下来我们看剩下的整体继续划分
接下来我们也可以分成两个模块
1.搜索和登录windows
2.消息列表
当我们理清楚了项目结构后就能愉快的进行开发了
代码实现
头像appbar
Row({ space: 10 }) {
Image($rawfile("bit7.jpg"))
.width(40)
.height(40)
.borderRadius(40)
.objectFit(ImageFit.Auto)
//.alignRules({ top: {anchor:"1", align: VerticalAlign.Top } })
Column({ space: 5 }) {
Text("7-bit")
Row({ space: 5 }) {
Column().width(10).height(10).borderRadius(20).backgroundColor("#14FA1B")
Text("手机在线 - WiFi >").fontSize(10)
}
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Image($rawfile("plus-sm.svg")).width(25).height(25)
}
搜索框
Row({ space: 5 }) {
Image($rawfile("Search_Magnifying_Glass.svg"))
.width(18)
.height(18)
.fillColor(Color.Grey)
Text("搜索").fontColor(Color.Grey).fontSize(15)
}
.width("100%")
.height(35)
.backgroundColor("#f5f5f5")
.borderRadius(6)
.justifyContent(FlexAlign.Center)
已登录windows 组件
Row({ space: 20 }) {
Image($rawfile("Monitor.svg"))
.width(20)
.height(20)
.fillColor(Color.Grey)
Text("已登录 Windows")
.fontSize(14)
.fontColor(Color.Grey)
.layoutWeight(1)
Image($rawfile("chevronright.svg"))
.height(30)
.fillColor(Color.Grey)
}
单个消息
Row({ space: 10 }) {
Image("图片地址")
.width(45).height(45).borderRadius(25)
Column({ space: 5 }) {
Text("群聊名称")
.fontSize(16)
Text("发送人:发送消息")
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.fontSize(14)
.fontColor(Color.Grey)
}.layoutWeight(1)
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Start)
Column({ space: 5 }) {
Text("发送日期")
.fontSize(12).fontColor(Color.Grey)
Badge({
count: 未读数量,
position: BadgePosition.Right,
style: { badgeSize: 16, badgeColor: '#FA2A2D' }
}) {
Text('')
}.height(20).margin({ left: 15 })
}
}.width("100%")
}
在这里我们就会发现一个问题,消息组件如何复用呢,我不能一直复制把,那么这里就得把实体类封装出来,接着把组件复用起来就能使我们的结构很清晰了
我们先创建一个Message.ets文件
将消息体给封装一下
export default class Message {
image: ResourceStr;
groupName: string;
sender: string;
msg: string;
time: string;
count: number;
constructor(image: ResourceStr, groupName: string, sender: string, msg: string, time: string, count: number) {
this.image = image;
this.groupName = groupName;
this.sender = sender;
this.msg = msg;
this.time = time;
this.count = count;
}
}
接下来继续封装复用组件
Row({ space: 10 }) {
Image(msg.image)
.width(45).height(45).borderRadius(25)
Column({ space: 5 }) {
Text(msg.groupName)
.fontSize(16)
Text(`${msg.sender} ${msg.msg}`)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.fontSize(14)
.fontColor(Color.Grey)
}.layoutWeight(1)
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Start)
Column({ space: 5 }) {
Text(msg.time)
.fontSize(12).fontColor(Color.Grey)
Badge({
count: msg.count,
position: BadgePosition.Right,
style: { badgeSize: 16, badgeColor: '#FA2A2D' }
}) {
Text('')
}.height(20).margin({ left: 15 })
}
}.width("100%")
最后上全部代码
import Message from '../entity/Message';
@Entry
@Component
struct Index {
srcList: Array<Message> = [
new Message($rawfile("flutter.png"), "HarmonyCandies", "7_bit | [Uint8List] | 我就是笨蛋", ":你们在干嘛",
"下午3:30",
100),
new Message($rawfile("harmony.png"), "HarmonyCandies", "道长 | 深圳 | PHP", ":可以开始卷了大家", "刚刚", 0),
new Message($rawfile("img.png"), "造物主动态桌面", "00后想买大房子", "我已经上了30个小时了", "下午4:18", 53),
new Message($rawfile("bit7.jpg"), "7_bit", "[文件]", ":等待接收", "上午11:30", 1),
new Message($rawfile("g.jpg"), "呱呱呱", "", "来上号了哇,别学习了!", "中午12:01", 0),
new Message($rawfile("e.jpg"), "八嘎の君", "", "很快乐,很幸福,感觉每天都很阳光", "下午4:18", 1),
new Message($rawfile("e.jpg"), "八嘎の君", "", "很快乐,很幸福,感觉每天都很阳光", "下午4:18", 1),
new Message($rawfile("e.jpg"), "八嘎の君", "", "很快乐,很幸福,感觉每天都很阳光", "下午4:18", 1),
new Message($rawfile("e.jpg"), "八嘎の君", "", "很快乐,很幸福,感觉每天都很阳光", "下午4:18", 1),
new Message($rawfile("e.jpg"), "八嘎の君", "", "很快乐,很幸福,感觉每天都很阳光", "下午4:18", 1)
];
build() {
Column({ space: 10 }) {
this._buildAppbar()
List({ space: 10 }) {
ListItem() {
this._buildSearch()
}
ListItem() {
this._buildTable()
}
ListItem() {
this._buildMessageList(this.srcList)
}
}.layoutWeight(1).scrollBar(BarState.Off)
}.width("100%").height("100%")
.padding(15).backgroundColor(Color.White)
}
@Builder
_buildAppbar() {
Row({ space: 10 }) {
Image($rawfile("bit7.jpg"))
.width(40)
.height(40)
.borderRadius(40)
.objectFit(ImageFit.Auto)
//.alignRules({ top: {anchor:"1", align: VerticalAlign.Top } })
Column({ space: 5 }) {
Text("7-bit")
Row({ space: 5 }) {
Column().width(10).height(10).borderRadius(20).backgroundColor("#14FA1B")
Text("手机在线 - WiFi >").fontSize(10)
}
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
Image($rawfile("plus-sm.svg")).width(25).height(25)
}
}
@Builder
_buildSearch() {
Row({ space: 5 }) {
Image($rawfile("Search_Magnifying_Glass.svg"))
.width(18)
.height(18)
.fillColor(Color.Grey)
Text("搜索").fontColor(Color.Grey).fontSize(15)
}
.width("100%")
.height(35)
.backgroundColor("#f5f5f5")
.borderRadius(6)
.justifyContent(FlexAlign.Center)
}
@Builder
_buildTable() {
Row({ space: 20 }) {
Image($rawfile("Monitor.svg"))
.width(20)
.height(20)
.fillColor(Color.Grey)
Text("已登录 Windows")
.fontSize(14)
.fontColor(Color.Grey)
.layoutWeight(1)
Image($rawfile("chevronright.svg"))
.height(30)
.fillColor(Color.Grey)
}
}
@Builder
_buildMessageList(msgList: Array<Message>) {
List({ space: 20 }) {
ForEach(msgList, (msg: Message, index: number) => {
this._buildMessageItem(msg);
})
}.layoutWeight(1)
.scrollBar(BarState.Off)
}
@Builder
_buildMessageItem(msg: Message) {
Row({ space: 10 }) {
Image(msg.image)
.width(45).height(45).borderRadius(25)
Column({ space: 5 }) {
Text(msg.groupName)
.fontSize(16)
Text(`${msg.sender} ${msg.msg}`)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.maxLines(1)
.fontSize(14)
.fontColor(Color.Grey)
}.layoutWeight(1)
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Start)
Column({ space: 5 }) {
Text(msg.time)
.fontSize(12).fontColor(Color.Grey)
Badge({
count: msg.count,
position: BadgePosition.Right,
style: { badgeSize: 16, badgeColor: '#FA2A2D' }
}) {
Text('')
}.height(20).margin({ left: 15 })
}
}.width("100%")
}
}
export default class Message {
image: ResourceStr;
groupName: string;
sender: string;
msg: string;
time: string;
count: number;
constructor(image: ResourceStr, groupName: string, sender: string, msg: string, time: string, count: number) {
this.image = image;
this.groupName = groupName;
this.sender = sender;
this.msg = msg;
this.time = time;
this.count = count;
}
}