
回复
大家好!我是HarmonyOS的初学者,最近在学习ArkTS开发,今天想和大家分享一个超实用的个人资料卡片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
状态显示不同内容// 联系信息区域
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')
}
}
问题:刚开始写的时候,卡片总是偏左显示
解决:要给外层容器设置合适的宽度和边距
// 错误写法
Column() {
// 内容
}
.width('100%') // 这样会撑满整个屏幕
// 正确写法
Column() {
// 内容
}
.width('90%') // 留出边距
问题:设置的阴影看不到效果
解决:需要调整阴影的颜色透明度和偏移量
// 效果差的阴影
.shadow({ radius: 2, color: '#000000', offsetX: 0, offsetY: 0 })
// 效果好的阴影
.shadow({ radius: 12, color: '#00000030', offsetX: 0, offsetY: 4 })
问题:给Text组件添加onClick后点击没反应
解决:Text组件默认不可点击,需要设置合适的样式
// 点击区域小的写法
Text('按钮').onClick(() => {})
// 点击区域大的写法
Text('按钮')
.padding(12)
.backgroundColor('#F5F5F5')
.onClick(() => {})
学完这个基础版本后,你还可以尝试添加这些功能:
// 选择图片并设置为头像
async selectAvatar() {
// 调用系统相册选择图片
const image = await pickImage();
this.avatarImage = image;
}
@State isDarkMode: boolean = false;
// 切换主题
toggleTheme() {
this.isDarkMode = !this.isDarkMode;
}
// 保存用户设置
saveUserProfile() {
Preferences.set('userProfile', this.userData);
}
通过这个小小的个人资料卡片项目,我学到了:
如果你也是HarmonyOS的初学者,我建议:
希望这篇学习笔记对你有帮助!如果有什么问题或者建议,欢迎在评论区交流~