HarmonyOS学习笔记:手把手教你打造个人资料卡片 原创

大师兄6668
发布于 2025-10-18 22:38
浏览
0收藏

HarmonyOS学习笔记:手把手教你打造个人资料卡片

HarmonyOS学习笔记:手把手教你打造个人资料卡片-鸿蒙开发者社区

大家好!我是HarmonyOS的初学者,最近在学习ArkTS开发,今天想和大家分享一个超实用的个人资料卡片demo。这个项目虽然不大,但涵盖了HarmonyOS开发的很多核心概念,特别适合新手入门!

为什么要学习这个demo?

作为一个刚接触HarmonyOS的小白,我发现这个 个人资料卡片项目真的很适合练习:

  • 代码量适中:不会太复杂,容易理解
  • 功能完整:包含了布局、交互、状态管理等
  • 视觉效果棒:学完就能做出漂亮的界面
  • 实战性强:很多应用都需要类似的个人资料页面

项目效果预览

先来看看我们最终要实现的效果:
HarmonyOS学习笔记:手把手教你打造个人资料卡片-鸿蒙开发者社区

一步步跟我写代码

第一步:搭建基础框架

@Entry
@Component
struct CardPage {
  // 这里我们先定义一些基础数据
  @State userName: string = '大师兄';
  @State userTitle: string = '会编程的产品经理';
  
  build() {
    Column() {
      // 页面标题
      Text('个人资料卡片')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
  }
}

小白理解

  • @Entry 表示这是应用的入口页面
  • @Component 告诉系统这是一个组件
  • @State 是用来管理状态数据的,数据变化时界面会自动更新

第二步:添加用户基本信息

  @State userBio: string = '正在学习HarmonyOS应用开发,热爱新技术探索和分享。拥有10年产品经理经验。';
@State isExpanded: boolean = false;

// 切换简介展开状态的函数
toggleBio() {
  this.isExpanded = !this.isExpanded;
}

知识点解析

  • userBio 存储用户的详细简介
  • isExpanded 控制简介是否展开
  • toggleBio() 是一个自定义函数,用来切换展开状态

第三步:设计卡片布局结构

Stack({ alignContent: Alignment.Top }) {
  // 背景卡片
  Column() {
    // 这里会放头像、姓名、简介等内容
  }
  .width('90%')
  .backgroundColor(Color.White)
  .borderRadius(16)
  .shadow({ radius: 12, color: '#00000030', offsetX: 0, offsetY: 4 })
}

布局技巧

  • Stack 用来实现层次效果,比如阴影在卡片下面
  • Column 是垂直排列的容器
  • borderRadius 设置圆角,让卡片更美观
  • shadow 添加阴影,提升立体感

第四步:创建头像区域

          // 头像区域
          Stack() {
            // 头像图片
            Image($r('app.media.avatar'))
              .width(100)
              .height(100)
              .borderRadius(50)
              .shadow({ radius: 8, color: '#00000020', offsetX: 2, offsetY: 2 })
          }
          .margin({ top: 20 })

这种就是真实的使用img图片来进行渲染头像,本项目中用的也是这样。但是很多情况下我们也会用文字来模拟头像,代码如下:

// 头像区域
Stack() {
  // 头像背景圆形
  Circle({ width: 100, height: 100 })
    .fill('#4A90E2')
    .shadow({ radius: 8, color: '#00000020', offsetX: 2, offsetY: 2 })
  
  // 头像文字(用姓名前两个字模拟头像)
  Text(this.userName.substring(0, 2))
    .fontSize(24)
    .fontColor(Color.White)
    .fontWeight(FontWeight.Bold)
}
.margin({ top: 20 })

设计思路

  • Circle 组件创建圆形背景
  • 用姓名前两个字作为头像内容(实际项目中可以用真实图片)
  • 蓝色背景配白色文字,视觉效果很清爽

第五步:添加姓名和职位信息

// 姓名和职位区域
Column() {
  Text(this.userName)
    .fontSize(20)
    .fontWeight(FontWeight.Bold)
    .fontColor('#333333')
    .margin({ bottom: 8 })

  Text(this.userTitle)
    .fontSize(14)
    .fontColor('#666666')
    .margin({ bottom: 16 })
}
.alignItems(HorizontalAlign.Center)

样式选择

  • 姓名用大号粗体,突出重要性
  • 职位用灰色小字,层次分明
  • alignItems(HorizontalAlign.Center) 让内容居中显示

第六步:实现可展开的简介功能

这是整个demo最有趣的部分!我们来实现点击展开/收起简介的功能:

// 简介区域
Column() {
  Text(this.isExpanded ? this.userBio : (this.userBio.substring(0, 30) + '...'))
    .fontSize(12)
    .fontColor('#888888')
    .textAlign(TextAlign.Center)
    .maxLines(this.isExpanded ? 0 : 2)
    .onClick(() => {
      this.toggleBio();
    })

  // 展开/收起按钮
  Text(this.isExpanded ? '收起' : '查看更多')
    .fontSize(12)
    .fontColor('#4A90E2')
    .margin({ top: 8 })
    .onClick(() => {
      this.toggleBio();
    })
}
.width('80%')

交互逻辑

  • 根据 isExpanded 状态显示不同内容
  • 未展开时显示前30个字+省略号
  • 展开时显示全部内容
  • 点击文字或按钮都能切换状态

第七步:创建联系按钮区域

// 联系信息区域
Row() {
  // 邮箱按钮
  Column() {
    Text('📧')
      .fontSize(20)
      .margin({ bottom: 4 })
    Text('邮箱')
      .fontSize(10)
      .fontColor('#666666')
  }
  .padding(12)
  .backgroundColor('#F5F5F5')
  .borderRadius(8)
  .onClick(() => {
    console.info('点击邮箱');
  })

  // 同样的方式创建电话和消息按钮...
}
.justifyContent(FlexAlign.SpaceAround)

布局技巧

  • Row 水平排列三个按钮
  • justifyContent(FlexAlign.SpaceAround) 让按钮均匀分布
  • 每个按钮都有圆角和点击效果

完整代码回顾

现在让我们看看完整的代码是什么样的:

@Entry
@Component
struct CardPage {
  @State userName: string = '大师兄';
  @State userTitle: string = '会编程的产品经理';
  @State userBio: string = '正在学习HarmonyOS应用开发,热爱新技术探索和分享。拥有10年产品经理经验。';
  @State isExpanded: boolean = false;

  // 切换简介展开状态
  toggleBio() {
    this.isExpanded = !this.isExpanded;
  }

  build() {
    Column() {
      // 页面标题
      Text('个人资料卡片')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ bottom: 20 })

      // 主卡片容器 - 使用Stack实现层次效果
      Stack({ alignContent: Alignment.Top }) {
        // 背景卡片
        Column() {
          // 头像区域
          Stack() {
            // 头像图片
            Image($r('app.media.avatar'))
              .width(100)
              .height(100)
              .borderRadius(50)
              .shadow({ radius: 8, color: '#00000020', offsetX: 2, offsetY: 2 })
          }
          .margin({ top: 20 })

          // 姓名和职位区域
          Column() {
            Text(this.userName)
              .fontSize(20)
              .fontWeight(FontWeight.Bold)
              .fontColor('#333333')
              .margin({ bottom: 8 })

            Text(this.userTitle)
              .fontSize(14)
              .fontColor('#666666')
              .margin({ bottom: 16 })
          }
          .alignItems(HorizontalAlign.Center)

          // 简介区域
          Column() {
            Text(this.isExpanded ? this.userBio : (this.userBio.substring(0, 30) + '...'))
              .fontSize(12)
              .fontColor('#888888')
              .textAlign(TextAlign.Center)
              .maxLines(this.isExpanded ? 0 : 2)
              .onClick(() => {
                this.toggleBio();
              })

            // 展开/收起按钮
            Text(this.isExpanded ? '查看更多' : '收起')
              .fontSize(12)
              .fontColor('#4A90E2')
              .margin({ top: 8 })
              .onClick(() => {
                this.toggleBio();
              })
          }
          .width('80%')
          .margin({ top: 10, bottom: 20 })

          // 联系信息区域 - 使用Row布局
          Row() {
            // 邮箱按钮
            Column() {
              Text('📧')
                .fontSize(20)
                .margin({ bottom: 4 })
              Text('邮箱')
                .fontSize(10)
                .fontColor('#666666')
            }
            .padding(12)
            .backgroundColor('#F5F5F5')
            .borderRadius(8)
            .onClick(() => {
              console.info('点击邮箱');
            })

            // 电话按钮
            Column() {
              Text('📞')
                .fontSize(20)
                .margin({ bottom: 4 })
              Text('电话')
                .fontSize(10)
                .fontColor('#666666')
            }
            .padding(12)
            .backgroundColor('#F5F5F5')
            .borderRadius(8)
            .margin({ left: 16, right: 16 })
            .onClick(() => {
              console.info('点击电话');
            })

            // 消息按钮
            Column() {
              Text('💬')
                .fontSize(20)
                .margin({ bottom: 4 })
              Text('消息')
                .fontSize(10)
                .fontColor('#666666')
            }
            .padding(12)
            .backgroundColor('#F5F5F5')
            .borderRadius(8)
            .onClick(() => {
              console.info('点击消息');
            })
          }
          .justifyContent(FlexAlign.SpaceAround)
          .margin({ bottom: 20 })
        }
        .width('90%')
        .backgroundColor(Color.White)
        .borderRadius(16)
        .shadow({ radius: 12, color: '#00000030', offsetX: 0, offsetY: 4 })
        .padding({ left: 20, right: 20 })
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .backgroundColor('#F8F9FA')
  }
}

我在学习过程中踩过的坑

坑1:布局不居中问题

问题:刚开始写的时候,卡片总是偏左显示
解决:要给外层容器设置合适的宽度和边距

// 错误写法
Column() {
  // 内容
}
.width('100%')  // 这样会撑满整个屏幕

// 正确写法
Column() {
  // 内容
}
.width('90%')   // 留出边距

坑2:阴影效果不明显

问题:设置的阴影看不到效果
解决:需要调整阴影的颜色透明度和偏移量

// 效果差的阴影
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: 0 })

// 效果好的阴影
.shadow({ radius: 12, color: '#00000030', offsetX: 0, offsetY: 4 })

坑3:点击事件不生效

问题:给Text组件添加onClick后点击没反应
解决:Text组件默认不可点击,需要设置合适的样式

// 点击区域小的写法
Text('按钮').onClick(() => {})

// 点击区域大的写法  
Text('按钮')
  .padding(12)
  .backgroundColor('#F5F5F5')
  .onClick(() => {})

可以继续扩展的功能

学完这个基础版本后,你还可以尝试添加这些功能:

1. 头像上传功能

// 选择图片并设置为头像
async selectAvatar() {
  // 调用系统相册选择图片
  const image = await pickImage();
  this.avatarImage = image;
}

2. 主题切换

@State isDarkMode: boolean = false;

// 切换主题
toggleTheme() {
  this.isDarkMode = !this.isDarkMode;
}

3. 数据持久化

// 保存用户设置
saveUserProfile() {
  Preferences.set('userProfile', this.userData);
}

学习收获总结

通过这个小小的个人资料卡片项目,我学到了:

  1. 布局基础:理解了Column、Row、Stack的区别和用法
  2. 状态管理:掌握了@State装饰器和数据驱动UI更新的原理
  3. 交互设计:学会了如何实现点击事件和状态切换
  4. 样式美化:了解了阴影、圆角、颜色搭配等视觉技巧

给其他小白的建议

如果你也是HarmonyOS的初学者,我建议:

  1. 从简单开始:不要一开始就做太复杂的项目
  2. 多动手实践:看十遍不如写一遍
  3. 善用官方文档:HarmonyOS的文档真的很详细
  4. 加入社区:遇到问题可以和其他开发者交流

希望这篇学习笔记对你有帮助!如果有什么问题或者建议,欢迎在评论区交流~

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2025-10-18 22:38:42修改
收藏
回复
举报
回复
    相关推荐