demo 地址: https://github.com/iotjin/JhHarmonyDemo
组件对应代码实现地址
代码不定时更新,请前往github查看最新代码
HarmonyOS NEXT - 仿微信主界面(首页 通讯录 发现 我的)
序
本demo基于 HarmonyOS 5.0.0(12) 仿写微信主界面效果(首页 通讯录 发现 我的)
发现和我的页面通过封装的组件实现参考demo或者 HarmonyOS NEXT - 表单录入组件封装(TextInput)
效果图
![]() | ![]() |
---|---|
![]() | ![]() |
首页
首页通过
List
组件实现 ,List组件官方文档
侧滑通过List
组件的swipeAction
实现。 对应官方文档
右上角的弹框通过promptAction.openCustomDialog
实现自定义弹窗。对应官方文档
完整代码
page
/// WxHomePage.ets
///
/// Created by iotjin on 2024/11/07.
/// description: 微信首页
import { promptAction, router } from '@kit.ArkUI'
import { BaseNavigation, JhProgressHUD, KColors } from 'JhCommon'
import { WxHomeItemType } from '../models/WxHomeModel'
import { WxHomeCell } from '../widgets/WxHomeCell'
@Entry
@Preview
@Component
export struct WxHomePage {
@State dataArr: WxHomeItemType[] = []
scroller: ListScroller = new ListScroller()
aboutToAppear() {
this.dataArr = this.getData()
// console.log('data', JSON.stringify(this.dataArr))
}
build() {
Column() {
BaseNavigation({
title: '微信',
leftItem: {},
rightImgPath: $rawfile("images/ic_nav_add.png"),
rightItemCallBack: () => {
console.log('点击了右侧图标')
this.onClickRightItem()
},
})
Scroll() {
Column() {
this.body()
}
.backgroundColor(KColors.wxBgColor)
}
.layoutWeight(1)
}
}
@Builder
body() {
List({ scroller: this.scroller }) {
ForEach(this.dataArr, (item: WxHomeItemType, index: number) => {
ListItem() {
WxHomeCell({
model: item,
onClickCell: () => {
this.clickCell(item)
},
})
}
.swipeAction({
end: {
builder: () => {
this.itemSwipeEnd(item.type)
},
actionAreaDistance: 0, // 设置组件长距离滑动删除距离阈值。 默认56
onAction: () => {
animateTo({ duration: 1000 }, () => {
})
},
}
})
})
}
.layoutWeight(1)
.divider({
strokeWidth: 0.5,
startMargin: 70,
endMargin: 0,
color: KColors.kLineColor
})
}
@Builder
itemSwipeEnd(type: string) {
if (type == '0') {
Row()
}
if (type == '1') {
Row() {
Text('删除')
.fontSize(14)
.fontWeight(400)
.fontColor(Color.White)
}
.width('25%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Red)
.onClick(() => {
JhProgressHUD.showToast('删除')
this.scroller.closeAllSwipeActions()
})
}
if (type == '2') {
Row() {
Row() {
Text('标为未读')
.fontSize(14)
.fontColor(Color.White)
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#74736D')
.onClick(() => {
JhProgressHUD.showToast('标为未读')
this.scroller.closeAllSwipeActions()
})
Row() {
Text('删除')
.fontSize(14)
.fontWeight(400)
.fontColor(Color.White)
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Red)
.onClick(() => {
JhProgressHUD.showToast('删除')
this.scroller.closeAllSwipeActions()
})
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Red)
.onClick(() => {
JhProgressHUD.showToast('删除')
this.scroller.closeAllSwipeActions()
})
}
if (type == '3') {
Row() {
Row() {
Text('不再关注')
.fontSize(14)
.fontColor(Color.White)
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#74736D')
.onClick(() => {
JhProgressHUD.showToast('不再关注')
this.scroller.closeAllSwipeActions()
})
Row() {
Text('删除')
.fontSize(14)
.fontWeight(400)
.fontColor(Color.White)
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Red)
.onClick(() => {
JhProgressHUD.showToast('删除')
this.scroller.closeAllSwipeActions()
})
}
.width('50%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.Red)
.onClick(() => {
JhProgressHUD.showToast('删除')
this.scroller.closeAllSwipeActions()
})
}
}
/* openCustomDialog API12+
创建并弹出dialogContent对应的自定义弹窗,使用Promise异步回调。
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-arkui-uicontext-V5#opencustomdialog12
*/
/* promptAction.openCustomDialog API11+
打开自定义弹窗
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-promptaction-V5#promptactionopencustomdialog11
*/
private customDialogId: number = 0
onClickRightItem() {
promptAction.openCustomDialog({
builder: () => {
this.customDialogComponent()
},
width: '160vp',
height: this.popData.length * 50 + 6,
offset: { dx: -10, dy: 56 },
alignment: DialogAlignment.TopEnd,
// backgroundColor: '#2D2D2D',
backgroundColor: Color.Transparent,
cornerRadius: 5,
}).then((dialogId: number) => {
this.customDialogId = dialogId
})
}
@Builder
customDialogComponent() {
Column() {
Row() {
Image($rawfile('images/popMenus/ic_menu_up_arrow.png')).height(6)
Blank().width(10)
}
.width('100%')
.justifyContent(FlexAlign.End)
List() {
ForEach(this.popData, (item: ESObject, index: number) => {
ListItem() {
Row() {
Blank().width(15)
Image(item['icon']).width(22)
Blank().width(15)
Text(item['text'])
.fontColor(Color.White)
.fontSize(16)
}
.width('100%')
.height(50)
.alignItems(VerticalAlign.Center)
}
.onClick(() => {
promptAction.closeCustomDialog(this.customDialogId)
this.clickPopCell(item['text'])
})
})
}
.enableScrollInteraction(false)
.layoutWeight(1)
.divider({
strokeWidth: 1,
startMargin: 50,
endMargin: 0,
color: '#E6E6E6',
})
.backgroundColor('#2D2D2D')
.borderRadius(5)
}
}
clickCell(item: WxHomeItemType) {
console.log('点击cell', JSON.stringify(item))
if (item.title == 'Demo 列表') {
router.pushUrl({ url: 'pages/demos/DemoListPage' })
} else if (item.title == '微信运动') {
router.pushUrl({ url: 'pages/one/pages/WxMotionPage' })
} else if (item.title == '订阅号消息') {
router.pushUrl({ url: 'pages/one/pages/WxSubscriptionNumberListPage' })
} else if (item.title == 'QQ邮箱提醒') {
router.pushUrl({ url: 'pages/one/pages/WxQQMessagePage' })
} else {
router.pushUrl({ url: 'pages/demos/DemoListPage' })
}
}
clickPopCell(text: string) {
console.log('点击', JSON.stringify(text))
if (text == '添加朋友') {
router.pushUrl({ url: 'pages/two/pages/WxAddFriendPage' })
}
}
getData() {
let dataArr: WxHomeItemType[] = [
{
'title': 'Demo 列表',
'subtitle': '点击跳转demo列表',
'img': 'images/ic_demo1.png',
'time': '',
'isNew': false,
'type': '0',
},
{
'title': '微信运动',
'subtitle': '[应用消息]',
'img': 'wechat/home/wechat_motion.png',
'time': '22:23',
'isNew': true,
'type': '1',
},
{
'title': '订阅号消息',
'subtitle': '新闻联播开始啦',
'img': 'wechat/home/ic_subscription_number.png',
'time': '19:00',
'isNew': true,
'type': '1',
},
{
'title': 'QQ邮箱提醒',
'subtitle': '您有一封新的邮件,请前往查收',
'img': 'wechat/home/Ic_email.png',
'time': '17:30',
'isNew': false,
'type': '3',
},
{
'title': '张三',
'subtitle': '欢迎欢迎',
'img': 'images/picture/touxiang_1.jpeg',
'time': '17:30',
'isNew': false,
'type': '2',
},
{
'title': '李四',
'subtitle': 'hello',
'img': 'images/picture/touxiang_2.jpeg',
'time': '17:30',
'isNew': false,
'type': '2',
},
{
'title': '王五',
'subtitle': '[图片]',
'img': 'images/picture/touxiang_3.jpeg',
'time': '17:30',
'isNew': false,
'type': '2',
},
{
'title': '赵六',
'subtitle': '[动画表情]',
'img': 'images/picture/touxiang_4.jpeg',
'time': '17:30',
'isNew': false,
'type': '2',
},
{
'title': '微信团队',
'subtitle': '安全登录提醒',
'img': 'wechat/home/ic_about.png',
'time': '2020/8/8',
'isNew': false,
'type': '1',
},
];
return dataArr;
}
popData: ESObject = [
{
'text': '发起群聊',
'icon': $rawfile('images/popMenus/ic_chat.png'),
},
{
'text': '添加朋友',
'icon': $rawfile('images/popMenus/ic_add.png'),
},
{
'text': '扫一扫',
'icon': $rawfile('images/popMenus/ic_scan.png'),
},
{
'text': '收付款',
'icon': $rawfile('images/popMenus/ic_pay.png'),
},
];
}
view
import { WxHomeModel } from "../models/WxHomeModel";
@Preview
@Component
export struct WxHomeCell {
model: WxHomeModel = new WxHomeModel();
public onClickCell?: (model: WxHomeModel) => void // 点击cell
build() {
Row() {
Row() {
// Image($rawfile(this.model.img))
// .width(55).height(55)
// .borderRadius(5)
// .clip(true)
Badge({ value: '', position: { x: 55 - 5, y: -5 }, style: { badgeSize: this.model.isNew ? 10 : 0, badgeColor: '#FA2A2D' } }) {
Image($rawfile(this.model.img))
.width(55)
.height(55)
.borderRadius(5)
.clip(true)
}
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.width(70)
.height(70)
Column() {
Blank().height(8)
Row() {
Flex() {
Text(this.model.title)
.flexGrow(70)
.fontSize(18)
Text(this.model.time)
.flexGrow(30)
.fontSize(13)
.fontColor(Color.Gray)
.textAlign(TextAlign.End)
Blank().width(10)
}
}
.justifyContent(FlexAlign.Start)
Blank().height(8)
Text(this.model.subtitle)
.fontSize(15)
.fontColor(Color.Gray)
}
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Start)
.layoutWeight(1)
}
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Top)
.width('100%')
.height(70)
.backgroundColor(Color.White)
.onClick(() => this.onClickCell?.(this.model))
}
}
model
export class WxHomeModel {
title?: string
subtitle?: string
img?: string
time?: string
isNew?: boolean
type?: string // 0,1,2,3
}
// type 0 没有侧滑
// type 1 删除
// type 2 标为未读和删除
// type 3 不在关注和删除
export interface WxHomeItemType {
title?: string
subtitle?: string
img?: string
time?: string
isNew?: boolean
type?: string
}
通讯录
通讯录通过
List
组件分组列表实现 ,List组件官方文档
侧滑通过List
组件的swipeAction
实现。 对应官方文档
右侧的索引通过AlphabetIndexer
组件实现, 对应官方文档
初始数据是对象数组,因为通讯录的页面是分组的结构,并且List组件的分组需要转成每组下面是对应组的数组,因此要对原始数据根据key分组处理
- 页面
- 初始数据结构:
[
{
"id": 0,
"name": "张芳",
"phone": "13564303126",
"sex": "0",
"region": "商丘市",
"province": "山东省",
"city": "黔南布依族苗族自治州",
"area": "阿拉山口市",
"label": "label0",
"color": "#f2e979",
"img": "http://dummyimage.com/100x100/f2e979&text=hi",
"avatarUrl": "https://gitee.com/iotjh/Picture/raw/master/lufei.png",
"isStar": false
},
...
]
- List 分组需要的数据结构类似于
分组的算法(数组按指定key分组)
// 数组按指定key分组
function groupListByKey<T>(array: T[], key: string): ESObject[] {
const result: ESObject[] = [];
const groupMap: Map<string, T[]> = new Map();
// 遍历数组,将每个元素按照key分组
array.forEach((item: ESObject) => {
const groupValue = String(item[key]);
if (!groupMap[groupValue]) {
groupMap[groupValue] = [];
}
groupMap[groupValue].push(item);
});
Object.keys(groupMap).forEach((key) => {
result.push({ groupName: key, data: groupMap[key] });
});
return result;
}
完整代码
page
/// WxContactsPage.ets
///
/// Created by iotjin on 2024/11/20.
/// description: 微信通讯录
import { router } from '@kit.ArkUI'
import { pinyin } from 'pinyin-pro';
import { BaseNavigation, JhProgressHUD, KColors } from 'JhCommon'
import { WxContactsModel } from '../models/WxContactsModel'
import { WxContactsCell } from '../widgets/WxContactsCell'
import data from '../../../pages/res/wx_contacts.json'
@Entry
@Preview
@Component
export struct WxContactsPage {
@State dataArr: ESObject[] = []
// @State tagIndexList: string[] = ['🔍', '★', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
// 'H', 'I', 'J', 'K', 'L', 'M', 'N',
// 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
// 'V', 'W', 'X', 'Y', 'Z', '#']
@State tagIndexList: string[] = []
// scroller: Scroller = new Scroller()
scroller: ListScroller = new ListScroller()
searchController: SearchController = new SearchController()
@State selectedIndex: number = 0
@State isShowTagPopup: boolean = false
@State contactsCount: string = ''
aboutToAppear() {
this.dataArr = this.loadData()
// console.log('data', JSON.stringify(this.dataArr))
let tempList: string[] = [];
for (let i = 0; i < this.dataArr.length; i++) {
const item: ESObject = this.dataArr[i];
tempList.push(item['groupName'])
}
this.tagIndexList = tempList;
}
build() {
Column() {
BaseNavigation({
isGradient: true,
title: '通讯录',
leftItem: {},
rightImgPath: $rawfile("images/ic_addFriend.png"),
rightItemCallBack: () => {
this.searchController.stopEditing()
router.pushUrl({ url: 'pages/two/pages/WxAddFriendPage' })
},
})
this.body()
}
}
@Builder
body() {
Stack({ alignContent: Alignment.End }) {
List({ space: 0, initialIndex: 0, scroller: this.scroller }) {
ForEach(this.dataArr, (groupItem: ESObject, index: number) => {
ListItemGroup({ header: this.itemHeader(groupItem.groupName) }) {
ForEach(groupItem.data, (cellItem: string, index2: number) => {
ListItem() {
WxContactsCell({
index: index,
model: cellItem as WxContactsModel,
searchController: this.searchController,
onClickCell: (model: WxContactsModel) => {
console.log('点击cell', JSON.stringify(cellItem))
this.searchController.stopEditing()
router.pushUrl({ url: 'pages/two/pages/WxUserInfoPage', params: { data: cellItem } })
},
onClickTopCell: (model: ESObject) => {
this.searchController.stopEditing()
this.clickCell(model['title'])
},
})
}
.swipeAction({
end: {
builder: () => {
if (index != 0) {
this.itemSwipeEnd()
}
},
actionAreaDistance: 0, // 设置组件长距离滑动删除距离阈值。 默认56
onAction: () => {
animateTo({ duration: 1000 }, () => {
})
},
}
})
}, (item: string) => item)
}
// 每行之间的分界线
.divider({
strokeWidth: 0.6,
startMargin: 65,
endMargin: 0,
color: KColors.kFormLineColor,
})
})
ListItem() {
this.footer()
}
}
.layoutWeight(1)
.sticky(StickyStyle.Header | StickyStyle.Footer)
.scrollBar(BarState.Off)
.onScrollIndex((firstIndex: number, lastIndex: number) => {
// console.log('firstIndex', JSON.stringify(firstIndex))
this.selectedIndex = firstIndex
})
AlphabetIndexer({ arrayValue: this.tagIndexList, selected: 0 })
.color(Color.Black)// 文字颜色
.selectedColor(Color.White)// 选中项文字颜色
.popupColor(Color.White)// 提示弹窗文字颜色
.selectedBackgroundColor(KColors.kThemeColor)// 选中项背景颜色
.popupBackground('#C9C9C9')// 提示弹窗背景色
.usingPopup(this.isShowTagPopup)// 是否使用提示弹窗
.selectedFont({ size: 16, weight: FontWeight.Bolder })// 选中项字体样式
.popupFont({ size: 30, weight: FontWeight.Bolder })// 弹出框内容的字体样式
.font({ size: 14 })// 字母索引条默认字体样式
.itemSize(22)// 字母索引条字母区域大小
.alignStyle(IndexerAlign.END)// 字母索引条弹框的对齐样式,支持弹窗显示在索引条右侧和左侧.默认值: IndexerAlign.END
.popupPosition({ x: 60, y: 48 })
.itemBorderRadius(11)//索引项背板圆角半径
.popupBackgroundBlurStyle(BlurStyle.NONE)// 设置提示弹窗的背景模糊材质
.selected(this.selectedIndex)
.onSelect((index: number) => {
// console.log('index', index)
console.log(this.tagIndexList[index] + ' Selected!')
// const findIndex = this.dataArr.findIndex((item: ESObject) => item['groupName'] == this.tagIndexList[index]);
// console.log('findIndex', JSON.stringify(findIndex))
this.scroller.scrollToIndex(index)
this.isShowTagPopup = true;
setTimeout(() => {
this.isShowTagPopup = false;
}, 3000)
})
.onPopupSelect((index: number) => {
console.info('onPopupSelected:' + index)
})
}
.layoutWeight(1)
}
@Builder
itemHeader(text: string) {
if (text == '🔍') {
Row()
} else {
Row() {
Text(text == '★' ? '★ 星标朋友' : text)
.padding({ left: 15 })
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(this.isFloat(text) ? KColors.wxPayColor : '#777777')
}
.width("100%")
.height(30)
.backgroundColor(KColors.wxBgColor)
}
}
isFloat(text: string) {
return this.tagIndexList[this.selectedIndex] == text
}
@Builder
itemSwipeEnd() {
Row() {
Text('备注')
.fontSize(14)
.fontColor(Color.White)
}
.width('25%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#74736D')
.onClick(() => {
JhProgressHUD.showToast('点击备注')
this.scroller.closeAllSwipeActions()
})
}
@Builder
footer() {
Row() {
Text(`${this.getData().length} 位朋友及联系人`)
.fontSize(16)
.fontColor(Color.Gray)
}
.width('100%')
.height(50)
.justifyContent(FlexAlign.Center)
.backgroundColor(KColors.wxBgColor)
}
clickCell(text: string) {
console.log('点击', JSON.stringify(text))
if (text == '新的朋友') {
router.pushUrl({ url: 'pages/two/pages/WxNewFriendPage' })
}
if (text == '群聊') {
router.pushUrl({ url: 'pages/two/pages/WxGroupChatPage' })
}
}
loadData() {
// 原始数据
const dataArr: ESObject[] = this.getData()
// 处理数据
let tempList: ESObject[] = [];
for (let i = 0; i < dataArr.length; i++) {
const item: ESObject = dataArr[i]
const pinyinStr = pinyin(item.name, { toneType: 'none' })
const tag = pinyinStr.substring(0, 1).toUpperCase();
item.namePinyin = pinyinStr;
if (item.isStar == true) {
item.tagIndex = '★';
} else if (new RegExp('[A-Z]').test(tag)) {
item.tagIndex = tag;
} else {
item.tagIndex = '#';
}
tempList.push(item);
}
// 根据A-Z排序
tempList.sort((a: ESObject, b: ESObject) => {
if (a['tagIndex'] === b['tagIndex']) {
return a['name'].localeCompare(b['name']) as number
}
if (a['tagIndex'] === "#") {
return 1
}
if (b['tagIndex'] === "#") {
return -1
}
return a['tagIndex'].localeCompare(b['tagIndex']) as number
});
// 把星标移到最前
tempList.forEach((item: ESObject, index) => {
if (item.isStar == true) {
tempList.unshift(...tempList.splice(index, 1));
}
});
// 添加 header
tempList.unshift({
name: "header",
tagIndex: "🔍"
});
// 改成分组数据
const newArr: ESObject[] = groupListByKey(tempList, 'tagIndex');
return newArr
}
getData() {
let dataArr: ESObject[] = data['data']
return dataArr;
}
}
// 数组按指定key分组
function groupListByKey<T>(array: T[], key: string): ESObject[] {
const result: ESObject[] = [];
const groupMap: Map<string, T[]> = new Map();
// 遍历数组,将每个元素按照key分组
array.forEach((item: ESObject) => {
const groupValue = String(item[key]);
if (!groupMap[groupValue]) {
groupMap[groupValue] = [];
}
groupMap[groupValue].push(item);
});
Object.keys(groupMap).forEach((key) => {
result.push({ groupName: key, data: groupMap[key] });
});
return result;
}
view
import { JhSetCell, KColors } from "JhCommon";
import { WxContactsModel } from "../models/WxContactsModel";
const _cellHeight = 50
const _imgWH = 40
const _lRSpace = 15
@Preview
@Component
export struct WxContactsCell {
index: number = 0;
model: WxContactsModel = new WxContactsModel();
searchController: SearchController = new SearchController()
public onClickCell?: (model: WxContactsModel) => void // 点击cell
public onClickTopCell?: (model: ESObject) => void // 点击cell
build() {
if (this.index == 0) {
this.header()
} else {
Row() {
Row() {
// Image(this.model.avatarUrl)
// .width(_imgWH).height(_imgWH)
// .borderRadius(5)
// .clip(true)
Row() {
Text(this.model.name?.substring(0, 1))
.fontColor(Color.White)
.fontSize(20)
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.width(_imgWH)
.height(_imgWH)
.borderRadius(5)
.backgroundColor(this.model.color)
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.width(_imgWH + _lRSpace * 2)
.height(_cellHeight)
Column() {
Text(this.model.name)
.fontSize(15)
.fontColor(Color.Black)
}
.alignItems(HorizontalAlign.Start)
.justifyContent(FlexAlign.Center)
.height('100%')
.layoutWeight(1)
}
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Top)
.width('100%')
.height(_cellHeight)
.backgroundColor(Color.White)
.onClick(() => this.onClickCell?.(this.model))
}
}
@Builder
header() {
Column() {
Row() {
Search({ value: '', placeholder: '搜索', controller: this.searchController })
.id('WxContactsPageSearch_ID')
.borderRadius(5)
.margin(10)
.onSubmit((value: string) => {
console.log('搜索框 onSubmit 文字:', JSON.stringify(value))
})
.onChange((value: string) => {
console.log('搜索框 onChange 文字:', JSON.stringify(value))
})
}
.backgroundColor(KColors.kBgColor)
ForEach(this.topData, (item: ESObject, index: number) => {
// JhSetCell({
// leftIcon: item['imgUrl'],
// leftImgWH: 40,
// title: item['title'],
// titleWidth: 300,
// lineLeftEdge: 65,
// hiddenArrow: true,
// cellHeight: _cellHeight,
// })
JhSetCell({
leftWidget: (): void => this.leftBuilder(item),
leftImgWH: 40,
title: item['title'],
titleWidth: 300,
lineLeftEdge: 65,
hiddenArrow: true,
cellHeight: _cellHeight,
clickCallBack: () => {
this.onClickTopCell?.(item)
},
})
})
}
}
@Builder
leftBuilder(item: ESObject) {
Image(item['imgUrl'])
.width(_imgWH).height(_imgWH)
.borderRadius(5)
.clip(true)
}
topData: ESObject = [
{
'title': '新的朋友',
'imgUrl': $rawfile('wechat/contacts/ic_new_friend.png'),
},
{
'title': '群聊',
'imgUrl': $rawfile('wechat/contacts/ic_group_chat.png'),
},
{
'title': '标签',
'imgUrl': $rawfile('wechat/contacts/ic_tag.png'),
},
{
'title': '公众号',
'imgUrl': $rawfile('wechat/contacts/ic_public_account.png'),
},
];
}
model
export class WxContactsModel {
id?: number
name?: string
phone?: string
sex?: string
region?: string
province?: string
city?: string
area?: string
label?: string
color?: string
img?: string
avatarUrl?: string
isStar?: boolean
// 新增
namePinyin?: string
tagIndex?: string
}
发现和我的页面通过封装的组件实现参考demo或者 HarmonyOS NEXT - 表单录入组件封装(TextInput)
发现 代码
/// WxDiscoverPage.ets
///
/// Created by iotjin on 2024/11/05.
/// description: 发现
import { BaseNavigation, JhProgressHUD, JhSetCell, KColors } from 'JhCommon'
import { router } from '@kit.ArkUI';
const _cellH = 55.0;
const _leftSpace = 50.0;
const _rowSpace = 6.0;
@Entry
@Preview
@Component
export struct WxDiscoverPage {
build() {
Column() {
BaseNavigation({ title: '发现', bgColor: Color.Transparent, leftItem: {} })
Scroll() {
Column() {
this.body()
}
}
}
.backgroundColor(KColors.wxBgColor)
}
@Builder
body() {
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_social_circle.png"),
title: '朋友圈',
hiddenLine: true,
rightWidget: (): void => this.rightBuilder(),
clickCallBack: () => {
this.clickCell('朋友圈')
},
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_video_number.png"),
title: '视频号',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('视频号'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/discover/ic_quick_scan.png"),
title: '扫一扫',
clickCallBack: (): void => this.clickCell('扫一扫'),
})
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/discover/ic_shake_phone.png"),
title: '摇一摇',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('摇一摇'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/discover/ic_feeds.png"),
title: '看一看',
clickCallBack: (): void => this.clickCell('看一看'),
})
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_quick_search.png"),
title: '搜一搜',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('搜一搜'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_people_nearby.png"),
title: '附近的人',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('附近的人'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/discover/ic_shopping.png"),
title: '购物',
clickCallBack: (): void => this.clickCell('购物'),
})
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_game_entry.png"),
title: '游戏',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('游戏'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/discover/ic_mini_program.png"),
title: '小程序',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('小程序'),
})
Blank().height(15)
}
@Builder
rightBuilder() {
// Image('https://gitee.com/iotjh/Picture/raw/master/lufei.png').height(30).width(30)
Row() {
Badge({ value: '', position: BadgePosition.RightTop, style: { badgeSize: 6, badgeColor: '#FA2A2D' } }) {
Image($rawfile('images/lufei.png'))
.width(30).height(30)
.margin({ top: 2.5, left: 2.5 })
}
.width(35).height(35)
// .backgroundColor(Color.Green)
}
}
// 点击cell
clickCell(title: string) {
console.log('点击cell', title)
if (title === '朋友圈') {
router.pushUrl({ url: 'pages/three/pages/WxFriendsCirclePage' })
} else {
JhProgressHUD.showText(`点击 ${title}`)
}
}
}
我的 代码
/// WxMinePage.ets
///
/// Created by iotjin on 2024/11/06.
/// description: 微信我的
import { BaseNavigation, JhAESPreferencesUtils, JhSetCell, KColors, kUserDefault_UserInfo } from 'JhCommon'
import { UserModel } from '../../model/UserModel';
import { router } from '@kit.ArkUI';
const _cellH = 55.0;
const _leftSpace = 50.0;
const _rowSpace = 6.0;
@Entry
@Preview
@Component
export struct WxMinePage {
userInfo?: UserModel;
aboutToAppear() {
let useInfo = JhAESPreferencesUtils.getModel(kUserDefault_UserInfo)
console.log('useInfo: ', JSON.stringify(useInfo))
this.userInfo = useInfo as UserModel
console.log('this.userInfo', JSON.stringify(this.userInfo))
}
build() {
Stack({ alignContent: Alignment.TopEnd }) {
this.body()
BaseNavigation({
title: '',
bgColor: Color.Transparent,
leftItem: {},
rightImgPath: $rawfile("images/ic_set_black.png"),
rightItemCallBack: () => {
this.clickCell('设置')
},
})
.hitTestBehavior(HitTestMode.Transparent)
}
.backgroundColor(KColors.wxBgColor)
}
@Builder
body() {
List() {
this.header()
ListItem() {
Column() {
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/mine/ic_wallet.png"),
title: '服务',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('服务'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/mine/ic_collections.png"),
title: '收藏',
})
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/mine/ic_album.png"),
title: '相册',
})
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/mine/ic_cards_wallet.png"),
title: '卡包',
})
JhSetCell({
cellHeight: _cellH,
lineLeftEdge: _leftSpace,
leftIcon: $rawfile("wechat/mine/ic_emotions.png"),
title: '表情',
hiddenLine: true,
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("wechat/mine/ic_settings.png"),
title: '设置',
hiddenLine: true,
clickCallBack: (): void => this.clickCell('设置'),
})
Blank().height(_rowSpace)
JhSetCell({
cellHeight: _cellH,
leftIcon: $rawfile("images/ic_about.png"),
title: '检查更新',
text: '有新版本',
textStyle: { fontSize: 14, fontColor: Color.Red },
hiddenLine: true,
clickCallBack: (): void => this.clickCell('showUpdateDialog'),
})
Blank().height(50)
}
}
}.backgroundColor(Color.Transparent)
}
@Builder
header() {
Row() {
// Image('https://gitee.com/iotjh/Picture/raw/master/lufei.png').width(75).height(75).borderRadius(10)
Image(this.userInfo?.avatarUrl).width(75).height(75).borderRadius(10)
.onClick(() => {
console.log('点击头像== ${this.userInfo?.avatarUrl}')
this.clickCell('个人信息')
})
Column() {
Text(this.userInfo?.userName)
.fontSize(28)
.fontWeight(FontWeight.Medium)
.textAlign(TextAlign.Start)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.width('100%')// .backgroundColor(Color.Pink)
.onClick(() => {
console.log('点击昵称== $\{model.userName}')
this.clickCell('个人信息')
})
Row() {
Text('微信号:abc').fontSize(17).fontColor(Color.Gray)
Blank()
// .backgroundColor(Color.Orange)
Image($rawfile('wechat/mine/ic_setting_myQR.png')).width(18).height(18).margin({ right: 20 })
Image($rawfile('JhForm/ic_arrow_right.svg')).width(25).height(25)
}
.margin({ top: 10 })
.width('100%')
// .backgroundColor(Color.Yellow)
.onClick(() => {
this.clickCell('个人信息')
})
}
.layoutWeight(1)
.padding({ left: 16 })
// .backgroundColor(Color.Red)
}
.backgroundColor(Color.White)
.padding({
left: 15,
right: 15,
top: 40,
bottom: 30
})
}
// 点击cell
clickCell(title: string) {
console.log('点击cell', title)
if (title === '服务') {
router.pushUrl({ url: 'pages/four/pages/WxPayPage' })
}
if (title === '个人信息') {
router.pushUrl({ url: 'pages/four/pages/WxPersonInfoPage' })
}
if (title === '设置') {
router.pushUrl({ url: 'pages/four/pages/SetPage' })
}
}
}