鸿蒙开发小案例(名片管理)
- 1、页面效果
-
- [1.1 初始页面](#1.1 初始页面)
- [1.2 点击名片展开](#1.2 点击名片展开)
- [1.3 点击收藏](#1.3 点击收藏)
- [1.4 点击编辑按钮](#1.4 点击编辑按钮)
- 2、实现代码
-
- [2.1 DataModel.ets](#2.1 DataModel.ets)
- [2.2 RandomUtil.ets](#2.2 RandomUtil.ets)
- [2.3 ContactList.ets](#2.3 ContactList.ets)
1、页面效果
1.1 初始页面
1.2 点击名片展开
1.3 点击收藏
1.4 点击编辑按钮
2、实现代码
2.1 DataModel.ets
java
let nextId = 1;
@Observed
export class Person {
id: number;
name: string;
phone: string;
isStar: boolean = false;
constructor(name, phone) {
this.id = nextId++;
this.name = name;
this.phone = phone;
}
}
2.2 RandomUtil.ets
java
const names = [
'张伟',
'王芳',
'李娜',
'刘强',
'陈军',
'杨洋',
'赵丽',
'黄勇',
'周雪',
'吴宇',
'徐鹏',
'马丽',
'孙建',
'朱敏',
'郭涛',
'曹梅',
'田亮',
'林静',
'范磊'
];
//随机抽取一个姓名
export function getRandomName() {
let randomIndex = Math.floor(Math.random() * names.length);
return names[randomIndex];
}
//随机生成一个年龄
export function getRandomAge() {
return 10 + Math.floor(Math.random() * 30);
}
//随机生成一个手机号码
export function getRandomPhone() {
const prefixArray = ['130', '131', '132', '133', '134', '135', '136', '137', '138', '139'];
let phone = prefixArray[Math.floor(Math.random() * prefixArray.length)];
// 生成后8位随机数字
for (let i = 0; i < 8; i++) {
phone += Math.floor(Math.random() * 10);
}
return phone;
}
2.3 ContactList.ets
java
import { getRandomName, getRandomPhone } from '../../../../utils/RandomUtil';
import { Person } from './model/DataModel';
@Entry
@Component
struct ContactsPage {
// 初始化列表数据
@State persons: Person[] = [new Person(getRandomName(), getRandomPhone()), new Person(getRandomName(), getRandomPhone())];
// 点击名片展开的 id
@State isOpenId: number = -1;
// 是否选中
@State isShowCheck: boolean = false;
// 选中的名片 ID
@State selectIdList: number[] = [];
build() {
Column() {
//标题
Row({ space: 10 }) {
Text('联系人').titleStyle()
Blank()
/**
* 通过 isShowCheck 控制 选择和取消 按钮的切换
*/
Button(this.isShowCheck ? '取消' : '选择')
.buttonStyle(Color.Gray)
.onClick(() => {
this.isShowCheck = !this.isShowCheck
})
Button('+')
.buttonStyle(Color.Gray)
/**
* 点击新增 新增联系人
*/
.onClick(() => {
this.persons.push(new Person(getRandomName(), getRandomPhone()))
})
}
.width('100%')
.height(60)
//列表
List({ space: 10 }) {
ForEach(this.persons, (person: Person) => {
ListItem() {
// 联系人组件
ContactItem({
person: person,
isOpenId: $isOpenId,
isShowCheck: this.isShowCheck,
selectIdList: $selectIdList })
}
})
}
.width('100%')
.layoutWeight(1)
//按钮
if (this.isShowCheck) {
Button('删除')
.buttonStyle(Color.Red)
.margin({ top: 10 })
.onClick(() => {
this.persons = this.persons.filter(person => !this.selectIdList.includes(person.id));
})
}
}
.width('100%')
.height('100%')
.backgroundColor('#EFEFEF')
.padding(10)
}
}
@Component
struct ContactItem {
@ObjectLink person: Person; // 双向绑定父组件的 person 对象
@State isShowPhone: boolean = false; // 定义是否展示 phone
@Link @Watch("numberChanger") isOpenId: number; // 监听点击打开的名片 实现只能打开一个 再打开会关闭其他名片
@Prop isShowCheck: boolean; // 接收父组件的值是否选中
@Link selectIdList: number[] // 绑定父组件的选中 ID 列表
/**
* 监听函数
* 监听当前选中的名片 id 是否为点击的名片 id
*/
numberChanger() {
this.person.id == this.isOpenId ? this.isShowPhone = true : this.isShowPhone = false;
}
build() {
Column() {
Row({ space: 10 }) {
if (this.isShowCheck) {
Toggle({
type: ToggleType.Checkbox
})
/**
* 删除函数
* 当被选中时 将名片 id 添加到 绑定父组件的selectIdList中
* 当未选中时 移除绑定父组件的selectIdList中的 名片 id
*/
.onChange((value) => {
value ? this.selectIdList.push(this.person.id) : this.selectIdList.slice(this.selectIdList.indexOf(this.person.id), 1)
})
}
//头像
Image($r('app.media.img_user_avatar'))
.width(40)
.height(40)
//姓名
Text(this.person.name)
.fontSize(20)
.fontWeight(500)
Blank()
//收藏
/**
* 双向绑定父组件的 person 对象中的 person.isStar 判断是否收藏
*/
Image(this.person.isStar ? $r('app.media.ic_star_filled') : $r('app.media.ic_star_empty'))
.width(30)
.height(30)
.onClick(() => {
this.person.isStar = !this.person.isStar;
})
}.justifyContent(FlexAlign.SpaceBetween)
.padding(10)
.width("100%")
/**
* 点击
* 1、改变展示名片 手机号
* 2、记录正在展示的名片 id 用于给 numberChanger() 监听函数判断是否是当前名片展开 如果是则关闭其他名片
*/
.onClick(() => {
this.isShowPhone = !this.isShowPhone;
this.isOpenId = this.person.id;
})
if (this.isShowPhone) {
Divider()
Row() {
Text(this.person.name)
.fontSize(20)
Text(this.person.phone)
.fontSize(20)
.margin({ left: 20 })
}
.backgroundColor(Color.White)
.width('100%')
.height(70)
.padding(10)
.borderRadius(10)
}
}
.backgroundColor(Color.White)
.padding(10)
.borderRadius(10)
}
}
/**
* 一些 css 样式
*/
@Extend(Text) function titleStyle() {
.fontSize(30)
.fontWeight(500)
}
@Extend(Button) function buttonStyle(color: ResourceColor) {
.height(30)
.backgroundColor(color)
}