鸿蒙开发小案例(名片管理))

1、页面效果


1.1 初始页面

在这里插入图片描述

1.2 点击名片展开

在这里插入图片描述

1.3 点击收藏

在这里插入图片描述

1.4 点击编辑按钮

在这里插入图片描述

2、实现代码


2.1 DataModel.ets

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

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

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)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

她似晚风般温柔789

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值