React Native鸿蒙跨平台剧本杀组队个人中心页面技术解读,采用函数式组件架构和useState进行状态管理,实现个人信息展示、称号管理和历史战绩查看等功能
TeamProfileLayout是一个基于React Native的个人中心组件,采用函数式组件架构和useState进行状态管理,实现个人信息展示、称号管理和历史战绩查看等功能。组件设计遵循跨端友好原则,使用原生基础组件、Base64图标资源和Flex布局,确保在React Native和鸿蒙系统中的一致性。通过模块化结构和轻量状态管理,组件实现了清晰的视觉分层和流畅的交互体验,为跨平台开发提
TeamProfileLayout 组件采用了现代 React 函数组件架构,结合 useState Hook 实现了精细化的状态管理。组件通过两个核心状态变量控制详情模态框的显示:detailVisible 管理模态框的可见性,detailTitle 存储模态框标题。这种状态分离设计使得组件逻辑清晰,易于维护和扩展。
在状态类型定义上,detailTitle 采用了 string | null 类型,明确表示其可能为空的状态,符合 TypeScript 的类型最佳实践。这种类型定义在跨端开发中尤为重要,确保了在不同平台上的类型一致性。
视觉设计
组件采用了分层布局结构,从外到内依次为:SafeAreaView -> 头部区域 -> ScrollView -> 内容区域。这种结构既保证了在不同设备上的显示兼容性,又提供了良好的用户滚动体验。
头部区域设计简洁明了,包含标题文本和图标组合,通过 flexDirection: 'row' 和 justifyContent: 'space-between' 实现了两端对齐的布局效果。个人信息卡片采用了居中对齐的设计,包含头像、姓名、签名和称号等信息,通过 flexDirection: 'column' 实现垂直排列。
样式设计上,组件使用了 StyleSheet.create 集中管理样式,避免了直接内联样式可能带来的性能问题。颜色方案采用了柔和的粉色系,营造出剧本杀游戏的氛围,同时保持了界面的清新感。样式命名规范清晰,如 card、avatar、badges 等,提高了代码的可读性。
用户体验
组件实现了丰富的交互功能,包括:
- 称号详情查看:点击"查看称号"或"称号说明"按钮,通过
onBadge函数打开详情模态框,显示对应称号的详细信息。 - 资料编辑:点击"编辑资料"按钮,通过
onEdit函数更新个人签名与称号,使用Alert.alert提供操作反馈。 - 称号管理:在详情模态框中,用户可以进行更换称号和收藏称号的操作,同样通过
Alert.alert提供反馈。 - 模态框交互:详情模态框支持点击"关闭"按钮关闭,通过
onCloseDetail函数实现。
这些交互设计遵循了移动应用的设计规范,提供了清晰的视觉反馈和操作引导。特别是 TouchableOpacity 组件的使用,为用户提供了明确的点击反馈,提升了用户体验。
在 React Native 与鸿蒙系统跨端开发中,该组件展现了多项兼容性设计:
-
组件选择:使用了
SafeAreaView确保在不同设备(包括带有刘海屏的设备)上的显示安全,这在鸿蒙系统的不同设备形态下同样重要。 -
样式适配:通过
StyleSheet定义样式,避免了直接内联样式可能带来的性能问题,同时确保了在不同平台上的一致表现。 -
交互反馈:使用
Alert.alert提供操作反馈,这是一个跨平台的 API,在 React Native 和鸿蒙系统中都能正常工作。 -
图片资源:采用
uri方式加载 Base64 编码的图标,这种方式在跨平台开发中更为灵活,避免了不同平台资源管理的差异。 -
模态框实现:使用了 React Native 的原生视图组件实现模态框功能,避免了使用可能在不同平台上表现不一致的第三方库。
-
条件渲染:使用
{detailVisible && (...)}这样的条件渲染方式,只在需要时渲染模态框,减少了不必要的渲染开销。 -
样式复用:通过样式对象的复用(如
badgeIcon多次使用),减少了样式定义的冗余,提高了代码的可维护性。 -
状态管理:采用了轻量级的
useStateHook 进行状态管理,对于这种中等复杂度的组件,避免了引入 Redux 等重型状态管理库的必要性。 -
事件处理:事件处理函数采用了函数声明的方式,避免了在每次渲染时创建新的函数实例,这在一定程度上优化了性能。
-
滚动优化:使用
ScrollView组件实现内容滚动,这是一个性能优化的选择,特别是在内容较长的情况下。
组件的代码结构清晰,逻辑分明,主要分为以下几个部分:
- 状态定义:集中在组件顶部,便于查看和管理。
- 事件处理函数:按照功能分组定义,包括编辑资料、查看称号、关闭详情等。
- JSX 结构:采用了缩进和注释,使布局结构一目了然。
- 样式定义:使用
StyleSheet.create集中管理样式,提高了代码的可读性和可维护性。
这种结构设计不仅便于开发者理解和维护代码,也为后续的功能扩展和跨平台适配提供了良好的基础。特别是图标资源的集中管理(通过 ICONS_BASE64 对象),使得资源替换和管理更加方便。
在将该组件适配到鸿蒙系统时,需要注意以下几点:
-
组件映射:将 React Native 的
SafeAreaView、ScrollView、TouchableOpacity等组件映射到鸿蒙系统的对应组件。例如,SafeAreaView可以映射到鸿蒙的SafeArea组件,ScrollView可以映射到ListContainer。 -
样式转换:将
StyleSheet中的样式转换为鸿蒙系统支持的样式格式。例如,React Native 的flexDirection: 'row'对应鸿蒙的flexDirection: FlexDirection.Row。 -
API 适配:确保
Alert.alert等 API 在鸿蒙系统中有对应的实现。例如,可以使用鸿蒙的promptAction或自定义弹窗组件。 -
状态管理:鸿蒙系统的状态管理机制可能与 React Native 有所不同,需要进行适当的调整。例如,可以使用鸿蒙的
@State装饰器替代useStateHook。 -
性能优化:根据鸿蒙系统的特性,进行针对性的性能优化,确保组件在鸿蒙设备上运行流畅。例如,合理使用鸿蒙的缓存机制和渲染优化策略。
TeamProfileLayout 组件展示了一个功能完整、结构清晰的 React Native 个人中心页面实现,涵盖了状态管理、布局设计、交互处理等多个方面的技术点。通过合理的组件架构和状态管理,以及对跨端兼容性的考虑,该组件不仅在 React Native 环境下运行良好,也为后续的鸿蒙系统适配奠定了基础。
本次实现的
TeamProfileLayout是剧本杀组队场景的个人信息核心展示页,聚焦玩家个人资料、称号徽章、历史战绩三大核心信息展示,同时承载资料编辑、称号管理、详情预览等高频交互能力,是泛娱乐组队场景中个人名片式页面的典型实现。该组件基于React Native纯原生基础组件开发,无第三方依赖,以Base64格式统一管理头像、徽章、编辑三类核心小图标,通过useState轻量实现称号详情模态层的显隐与动态标题传参,全程采用Flex弹性布局完成卡片式个人信息、流式徽章、战绩列表、双按钮操作栏等典型布局,整体设计贴合移动端个人中心的交互与视觉习惯。
从跨端视角来看,该组件严格遵循React Native鸿蒙跨端友好开发原则:Base64图标资源可跨端直接复用,Flex布局能无缝映射为ArkUI通用布局,原生基础组件可通过react-native-harmony桥接层一键转换,纯JS交互逻辑无需修改即可在鸿蒙端运行,模块化样式设计让鸿蒙端适配仅需轻量微调。作为个人中心类页面的典型案例,其开发思路可复用于桌游、电竞、团建等各类组队场景的个人信息页开发,以下从架构设计、核心功能实现、跨端友好开发细节、鸿蒙端实操适配要点四个维度,深度解读该代码的技术设计与跨端适配逻辑。
个人名片:
个人中心类页面的核心设计诉求是信息层级清晰、视觉聚焦、交互轻量化、布局贴合移动端个人名片习惯,同时需保证跨端适配时修改范围高度收敛。本次TeamProfileLayout组件遵循高内聚、模块化、视觉分层的设计原则,将页面拆分为头部导航、滚动内容区、模态详情层三大核心模块,所有视图渲染、样式设计、交互逻辑均收敛在单个函数式组件中,未做过度组件拆分。
这种单组件高内聚的实现方式,既保证了个人信息展示的连贯性——玩家可在一个滚动视图内完成个人资料、徽章、战绩的一站式浏览,又契合React Native鸿蒙跨端规范:所有修改均集中在组件内部,无需跨多个组件进行桥接与逻辑调整,大幅降低鸿蒙端改造成本,同时极简的组件结构让桥接层的解析与映射效率更高,保证页面在鸿蒙端的渲染与交互性能。
- 极简依赖选型:仅引入React核心库、
useState轻量Hook与RN原生基础组件(SafeAreaView/View/Text/TouchableOpacity/ScrollView/Image),以及跨端通用的Alert提示API,无任何第三方UI库、状态管理库或端侧特有依赖。这些基础组件与API均已在华为开源的react-native-harmony桥接层中实现与ArkUI的一一映射,无需开发自定义桥接模块即可完成基础适配。 - Base64资源统一管理:将头像(profile)、徽章(badge)、编辑(edit)三类场景高频小图标封装在
ICONS_BASE64常量对象中,以Base64格式替代传统本地图片资源。该方式从根本上解决了跨端资源适配的核心痛点——无需在iOS/Android/鸿蒙各端分别配置资源目录与路径,实现一次编码,多端复用,且RN与ArkUI的Image组件均原生支持Base64格式的uri加载,桥接层兼容无成本。 - 轻量状态管理:仅定义
detailVisible(模态层显隐)、detailTitle(模态层动态标题)两个状态,精准覆盖称号详情层的核心交互需求,无复杂的状态流转与数据共享。所有交互回调函数(onEdit/onBadge/onCloseDetail)均为组件内部纯函数,逻辑简洁且与平台无关,跨端时可直接复用。
核心功能:
本次实现的剧本杀组队个人中心,核心覆盖卡片式个人资料展示、流式称号徽章布局、历史战绩列表展示、轻量化交互操作、参数化称号详情预览五大核心能力,所有实现均基于RN原生基础组件与跨端通用的Flex布局,从布局、样式、交互三个维度践行跨端友好原则,核心逻辑可直接映射为ArkUI实现,仅需轻量样式微调即可贴合鸿蒙端设计规范。
卡片式个人资料展示:
个人资料卡片是页面的视觉核心,采用左侧大头像+右侧信息流的经典移动端个人名片布局,通过Flex弹性布局实现图文的精准对齐与自适应,视觉聚焦且信息层级清晰,是跨端通用的个人资料展示方案。
核心实现逻辑:
- 卡片容器:根容器
card设置白色背景、圆角、轻量阴影与内边距,打造卡片式视觉效果,贴合移动端个人资料的轻量化设计风格;通过flexDirection: row+alignItems: 'center'实现头像与信息流的横向排列与垂直居中,保证布局的规整性。 - 头像区域:设置64*64固定尺寸与50%圆角(
borderRadius: 32)实现圆形头像,浅粉色背景作为占位,marginRight与右侧信息流形成合理间距,固定尺寸保证跨端展示的一致性,避免因设备尺寸差异导致的头像变形。 - 信息流区域:根容器
cardText设置flex:1实现剩余宽度自适应,内部按「用户名→个人签名→称号徽章→操作按钮」的垂直顺序分层展示,每层通过marginTop设置合理间距,实现信息的自然分层,让玩家快速捕捉核心个人信息。 - 文字样式分层:用户名使用大字号粗体突出展示,个人签名使用小字号浅灰色作为辅助信息,称号徽章使用差异化色彩突出个性化标签,通过样式区分实现信息层级的视觉强化,契合移动端“核心信息突出,辅助信息弱化”的设计原则。
该布局为纯Flex实现,无任何平台特有代码,跨端时可直接映射为ArkUI的Flex布局,实现与RN端高度一致的个人名片展示效果。
流式称号徽章布局:
称号徽章是剧本杀组队场景的个性化核心,用于展示玩家的游戏标签(如推理达人、演技派),本次通过轻量Flex布局实现流式横向排列,贴合移动端个性化标签的展示习惯,布局紧凑且可扩展。
核心实现逻辑:
- 徽章容器:
badges容器设置flexDirection: row+alignItems: 'center',实现徽章图标与文字的横向流式排列,支持新增徽章时自动向右扩展,扩展性强。 - 徽章单元:每个徽章由「小图标+文字」组成,图标设置16*16小尺寸,
marginRight与文字形成间距,文字使用差异化的深粉色与粗体,突出徽章的个性化属性;多个徽章之间通过marginLeft设置间距,保证布局的整洁性。 - 徽章操作:徽章下方设置两个轻量化子弹按钮(
bulletBtn),通过TouchableOpacity绑定onBadge函数,点击可打开对应徽章的详情模态层,实现“展示-查看详情”的轻量化交互,按钮采用与徽章同色系的背景与文字色,保证视觉风格的统一性。
该流式布局无固定宽度限制,支持任意数量的徽章扩展,且为RN与ArkUI的通用实现,跨端时可直接复用,无需修改布局逻辑。
历史战绩列表:Flex实现的跨端通用双列对齐列表
历史战绩是组队场景的实力背书核心,本次通过Flex布局实现左侧战绩标题+右侧战绩元信息的双列对齐列表,布局简洁且信息展示高效,是跨端通用的列表展示方案。
核心实现逻辑:
- 战绩容器:
section容器设置差异化的浅粉色背景,与个人资料卡片形成视觉分层,让玩家快速识别不同信息模块;圆角与内边距保证与整体页面样式的一致性。 - 列表项布局:每个战绩项
row设置flexDirection: row+justifyContent: 'space-between',实现左侧战绩标题(如夜幕迷踪 · MVP)与右侧元信息(胜 · 2025-12-02)的两端对齐,贴合移动端列表的信息展示习惯。 - 样式区分:战绩标题使用粗体突出核心信息,元信息使用与徽章同色系的文字色,既补充战绩结果与时间,又与页面整体视觉风格呼应;
paddingVertical设置上下内边距,borderBottomWidth添加列表项分隔线,让列表布局更整洁,最后一项分隔线因父容器裁剪不影响视觉效果。
该列表布局无任何复杂逻辑,纯Flex属性实现,跨端时可直接映射为ArkUI的List与ListItem组件,或继续使用Flex布局,灵活度高。
交互操作:
个人中心的交互操作需轻量化、核心化,本次实现通过Flex等分布局打造双按钮快捷操作栏,承载“编辑资料”与“更换称号”两大核心操作,布局对称且交互高效,契合移动端个人中心的操作习惯。
核心实现逻辑:
- 操作栏布局:根容器
actionBar设置flexDirection: row+justifyContent: 'space-between',内部两个按钮均设置flex:1实现宽度等分,保证操作栏的对称布局;marginTop与上方战绩模块形成合理间距,实现视觉分层。 - 图文按钮设计:每个操作按钮为
TouchableOpacity交互组件,采用图标+文字的图文混排设计,通过flexDirection: row+justifyContent: 'center'+alignItems: 'center'实现图标与文字的水平垂直居中,圆角与上下内边距保证按钮的视觉质感。 - 样式差异化:通过
actionBtn(普通按钮)与actionBtnPrimary(主按钮)实现样式区分,仅修改背景色与文字色——主按钮使用与徽章同色系的浅粉色背景,突出核心操作(更换称号),贴合移动端“核心操作视觉强化”的设计原则,同时保持样式的统一性。 - 通用交互逻辑:两个按钮均绑定
onEdit函数,点击触发RN通用的Alert提示反馈操作结果,逻辑简洁且与平台无关。后续业务迭代中,可直接替换为接口请求、页面跳转等实际业务逻辑,跨端时无需修改核心触发逻辑。
详情预览:
称号详情预览是个性化标签的深度交互能力,本次通过useState轻量状态管理+动态参数传递,打造跨端通用的模态详情层,支持不同称号的动态详情展示,扩展性强且实现逻辑简洁。
核心实现逻辑:
- 动态参数传递:点击徽章下方的“查看称号”“称号说明”按钮时,调用
onBadge函数并传入对应称号的详情标题(如“推理达人 · 称号详情”),通过setDetailTitle更新模态层标题状态,实现不同称号的动态标题展示,无需为每个称号开发独立的详情层。 - 模态层显隐控制:通过
setDetailVisible修改布尔状态,控制模态层的显示与隐藏,触发逻辑简单且跨端通用,RN与ArkUI均通过状态控制视图显隐。 - 模态层布局规范:根容器
detailOverlay通过position: 'absolute'实现全屏遮罩,设置半透明背景、垂直水平居中,padding避免小屏设备上面板贴边;详情面板detailPanel设置width: 100% + maxWidth: 420,实现不同设备的自适应宽度,同时保证大屏设备上面板不会过宽,贴合移动端模态层的通用设计规范。 - 详情层内部结构:面板内部分为头部(动态标题+关闭按钮)、主体(称号详情信息)、底部(称号操作按钮) 三大模块,所有内部布局均为跨端通用的Flex实现,详情信息采用“图标+文字”的横向布局,与页面整体视觉风格保持一致,操作按钮延续主/次按钮的样式差异化设计,保证交互体验的统一性。
样式设计是React Native鸿蒙跨端适配的核心细节,本次实现遵循模块化样式、视觉分层、跨端通用规范三大原则,所有样式均基于RN内置的StyleSheet.create创建,采用驼峰命名法,无平台特有样式属性,让鸿蒙端适配仅需轻量微调,无需重构样式逻辑。
模块化
按页面的功能模块与视觉元素定义独立的样式类,如card(个人资料卡片)、badges(徽章容器)、row(战绩列表项)、actionBtn(操作按钮)、detailPanel(模态面板)等,每个样式类仅负责对应模块/元素的样式,实现样式与视图的一一对应。
这种设计让鸿蒙端样式微调时,修改范围高度收敛——例如需要调整鸿蒙端的按钮圆角,仅需修改actionBtn/detailBtn的borderRadius属性即可,无需修改其他模块的样式,大幅提升适配效率。同时,通过基础样式+差异化样式覆盖实现样式复用,如actionBtnPrimary基于actionBtn仅修改背景色与文字色,减少样式冗余。
视觉分层
通过背景色差异、间距、阴影、边框实现页面的视觉分层,让信息层级更清晰,同时所有分层样式均为跨端通用属性:
- 模块分层:个人资料卡片使用白色背景,战绩列表使用浅粉色背景,快捷入口使用差异化背景,通过背景色差异让不同信息模块快速区分,无视觉混淆;
- 元素分层:卡片、模态面板添加轻量阴影(
shadow系列属性),提升视觉立体感,RN桥接层可将该属性直接映射为ArkUI的shadow属性; - 信息分层:通过文字的字号、粗细、颜色区分核心信息(用户名、战绩标题)与辅助信息(个人签名、战绩时间),通过
margin/padding实现元素间的合理间距,避免信息拥挤。
样式规范
- 驼峰命名法:所有样式属性均采用RN标准的驼峰命名法(如
backgroundColor/borderRadius/paddingVertical),与ArkUI的样式命名规范完全一致,鸿蒙端迁移时无需修改任何样式属性名。 - 通用样式属性:所有使用的样式属性(
flex/alignItems/justifyContent/borderRadius/shadow/margin/padding)均为RN与ArkUI的通用属性,无iOS/Android/鸿蒙平台特有属性,桥接层可直接映射。 - 固定尺寸与自适应结合:头像、图标、按钮等交互元素使用固定尺寸,保证跨端点击的便捷性与展示的一致性;文字区域、卡片容器使用
flex:1实现宽度自适应,保证在不同尺寸设备上的布局规整,无错乱。
作为典型的个人中心类页面,TeamProfileLayout的实现全程遵循跨端友好原则,Base64资源可直接复用,纯JS逻辑无需修改,原生基础组件可无缝桥接,模块化样式设计让修改范围高度收敛。依托react-native-harmony桥接层,可实现鸿蒙端的零逻辑修改、轻量样式微调、快速适配,核心适配要点与实操方案如下,可复用于所有React Native个人中心、个人名片、信息展示类页面的鸿蒙跨端开发。
本次基于React Native实现的剧本杀组队个人中心,作为典型的个人名片式信息展示页,全程践行了跨端友好型开发原则,其实现与适配解析提炼出个人中心类页面React Native鸿蒙跨端开发的核心最佳实践,能有效降低此类页面的鸿蒙适配成本,实现低成本、高效率、高还原的跨端落地:
- Base64格式管理高频小图标:个人中心的头像、徽章、操作图标等高频小图标,优先使用Base64格式集中管理,规避端侧资源配置成本,实现一次编码多端复用,且RN与ArkUI的Image组件均原生支持,桥接兼容无成本;
- Flex布局实现全页面适配:采用Flex弹性布局实现个人资料卡片、徽章流式布局、战绩列表、操作栏、模态层等所有布局,通过
flex:1实现宽度自适应,固定尺寸保证交互元素一致性,拒绝硬编码像素值,保证跨端布局规整; - 高内聚单组件实现核心功能:将个人中心的所有模块、逻辑、样式收敛在单个函数式组件中,未做过度拆分,让鸿蒙端适配的修改范围高度收敛,所有调整均集中在组件内部;
- 轻量状态+参数化实现动态交互:使用
useState管理模态层等核心状态,通过参数传递实现动态标题、动态详情等能力,避免重复开发,纯JS逻辑与平台无关,跨端可直接复用; - 模块化样式+视觉分层设计:按功能模块定义独立样式类,通过基础样式+差异化覆盖实现样式复用,通过背景色、间距、阴影实现视觉分层,所有样式遵循驼峰命名法与跨端通用属性,让鸿蒙端适配仅需轻量微调;
- 极简依赖选型:仅使用RN原生基础组件与通用API,避免引入第三方库,依托
react-native-harmony桥接层的成熟映射方案,实现组件与API的无缝桥接,从依赖层面规避跨端成本。
真实演示案例代码:
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Alert, Image } from 'react-native';
const ICONS_BASE64 = {
profile: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
badge: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
edit: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
};
const TeamProfileLayout: React.FC = () => {
const [detailVisible, setDetailVisible] = useState(false);
const [detailTitle, setDetailTitle] = useState<string | null>(null);
const onEdit = () => Alert.alert('个人中心', '已更新个人签名与称号');
const onBadge = (title: string) => {
setDetailTitle(title);
setDetailVisible(true);
};
const onCloseDetail = () => {
setDetailVisible(false);
setDetailTitle(null);
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>剧本杀组队 · 个人中心</Text>
<View style={styles.headerIcons}>
<Image source={{ uri: ICONS_BASE64.profile }} style={styles.headerIconImg} />
<Text style={styles.headerEmoji}>🧑🎤</Text>
</View>
</View>
<ScrollView style={styles.content}>
<View style={styles.card}>
<Image source={{ uri: ICONS_BASE64.profile }} style={styles.avatar} />
<View style={styles.cardText}>
<Text style={styles.name}>糖糖</Text>
<Text style={styles.sign}>签名:今晚我就是主角</Text>
<View style={styles.badges}>
<Image source={{ uri: ICONS_BASE64.badge }} style={styles.badgeIcon} />
<Text style={styles.badgeText}>推理达人</Text>
<Image source={{ uri: ICONS_BASE64.badge }} style={[styles.badgeIcon, { marginLeft: 8 }]} />
<Text style={styles.badgeText}>演技派</Text>
</View>
<View style={{ flexDirection: 'row', marginTop: 8 }}>
<TouchableOpacity onPress={() => onBadge('推理达人 · 称号详情')}>
<Text style={styles.bulletBtn}>查看称号</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => onBadge('演技派 · 称号详情')}>
<Text style={[styles.bulletBtn, { marginLeft: 8 }]}>称号说明</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>历史战绩</Text>
<View style={styles.row}>
<Text style={styles.rowTitle}>夜幕迷踪 · MVP</Text>
<Text style={styles.rowMeta}>胜 · 2025-12-02</Text>
</View>
<View style={styles.row}>
<Text style={styles.rowTitle}>深海谜潮 · 线索王</Text>
<Text style={styles.rowMeta}>平 · 2025-11-20</Text>
</View>
<View style={styles.row}>
<Text style={styles.rowTitle}>晨曦疑云 · 控场主</Text>
<Text style={styles.rowMeta}>胜 · 2025-10-08</Text>
</View>
</View>
<View style={styles.actionBar}>
<TouchableOpacity style={styles.actionBtn} onPress={onEdit}>
<Image source={{ uri: ICONS_BASE64.edit }} style={styles.actionIcon} />
<Text style={styles.actionText}>编辑资料</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.actionBtn, styles.actionBtnPrimary]} onPress={onEdit}>
<Image source={{ uri: ICONS_BASE64.badge }} style={styles.actionIcon} />
<Text style={styles.actionTextPrimary}>更换称号</Text>
</TouchableOpacity>
</View>
</ScrollView>
{detailVisible && (
<View style={styles.detailOverlay}>
<View style={styles.detailPanel}>
<View style={styles.detailHeader}>
<Text style={styles.detailTitle}>{detailTitle}</Text>
<TouchableOpacity onPress={onCloseDetail}>
<Text style={styles.detailClose}>关闭</Text>
</TouchableOpacity>
</View>
<View style={styles.detailBody}>
<View style={styles.detailRow}>
<Image source={{ uri: ICONS_BASE64.badge }} style={styles.detailIcon} />
<Text style={styles.detailText}>获取条件:战绩达成或队友认可。</Text>
</View>
<View style={styles.detailRow}>
<Image source={{ uri: ICONS_BASE64.profile }} style={styles.detailIcon} />
<Text style={styles.detailText}>效果:展示于个人卡片与组队列表。</Text>
</View>
</View>
<View style={styles.detailFooter}>
<TouchableOpacity style={styles.detailBtn} onPress={() => Alert.alert('更换称号', '已更换当前称号')}>
<Text style={styles.detailBtnText}>更换称号</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.detailBtn, styles.detailBtnPrimary]} onPress={() => Alert.alert('收藏称号', '已收藏到称号库')}>
<Text style={styles.detailBtnTextPrimary}>收藏称号</Text>
</TouchableOpacity>
</View>
</View>
</View>
)}
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: '#fff7fb' },
header: { padding: 16, backgroundColor: '#ffffff', borderBottomWidth: 1, borderBottomColor: '#fecdd3', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
title: { fontSize: 18, fontWeight: 'bold', color: '#0f172a' },
headerIcons: { flexDirection: 'row', alignItems: 'center' },
headerEmoji: { fontSize: 18, marginLeft: 8 },
headerIconImg: { width: 24, height: 24 },
content: { padding: 16 },
card: { backgroundColor: '#ffffff', borderRadius: 12, padding: 12, flexDirection: 'row', alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 2 },
avatar: { width: 64, height: 64, borderRadius: 32, marginRight: 12, backgroundColor: '#ffe4e6' },
cardText: { flex: 1 },
name: { fontSize: 16, fontWeight: 'bold', color: '#0f172a' },
sign: { fontSize: 12, color: '#64748b', marginTop: 4 },
badges: { flexDirection: 'row', alignItems: 'center', marginTop: 8 },
badgeIcon: { width: 16, height: 16, marginRight: 6 },
badgeText: { fontSize: 12, color: '#9d174d', fontWeight: '600' },
bulletBtn: { fontSize: 11, color: '#9d174d', backgroundColor: '#fce7f3', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 10 },
section: { backgroundColor: '#fff1f2', borderRadius: 12, padding: 14, marginTop: 16 },
sectionTitle: { fontSize: 16, fontWeight: 'bold', color: '#0f172a', marginBottom: 10 },
row: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#f3f4f6' },
rowTitle: { fontSize: 13, color: '#0f172a', fontWeight: '600' },
rowMeta: { fontSize: 11, color: '#9d174d' },
actionBar: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 18 },
actionBtn: { flex: 1, backgroundColor: '#f1f5f9', borderRadius: 12, paddingVertical: 12, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', marginRight: 10 },
actionBtnPrimary: { backgroundColor: '#fce7f3', marginRight: 0 },
actionIcon: { width: 16, height: 16, marginRight: 6 },
actionText: { fontSize: 14, color: '#334155', fontWeight: '500' },
actionTextPrimary: { fontSize: 14, color: '#9d174d', fontWeight: '600' },
detailOverlay: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.25)', justifyContent: 'center', alignItems: 'center', padding: 16 },
detailPanel: { width: '100%', maxWidth: 420, backgroundColor: '#ffffff', borderRadius: 14, padding: 14, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.12, shadowRadius: 4 },
detailHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },
detailTitle: { fontSize: 16, fontWeight: '700', color: '#0f172a' },
detailClose: { fontSize: 12, color: '#9d174d', backgroundColor: '#fce7f3', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 10 },
detailBody: { marginTop: 10 },
detailRow: { flexDirection: 'row', alignItems: 'center', marginTop: 8 },
detailIcon: { width: 18, height: 18, marginRight: 6 },
detailText: { fontSize: 12, color: '#475569' },
detailFooter: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 12 },
detailBtn: { backgroundColor: '#f1f5f9', borderRadius: 10, paddingVertical: 8, paddingHorizontal: 12, marginRight: 8 },
detailBtnPrimary: { backgroundColor: '#fce7f3' },
detailBtnText: { fontSize: 12, color: '#334155', fontWeight: '600' },
detailBtnTextPrimary: { fontSize: 12, color: '#9d174d', fontWeight: '700' },
});
export default TeamProfileLayout;

打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:

TeamProfileLayout是一个基于React Native的个人中心组件,采用函数式组件架构和useState进行状态管理,实现个人信息展示、称号管理和历史战绩查看等功能。组件设计遵循跨端友好原则,使用原生基础组件、Base64图标资源和Flex布局,确保在React Native和鸿蒙系统中的一致性。通过模块化结构和轻量状态管理,组件实现了清晰的视觉分层和流畅的交互体验,为跨平台开发提供了可复用的解决方案。
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐




所有评论(0)