React Native鸿蒙跨平台渲染时将样式按主题合并为局部变量(如 containerStyle、titleStyle 等),避免在 JSX 中散落的内联计算
React Native 相册应用实现了现代化跨端 UI 设计,采用函数式组件和 useState Hook 管理状态,确保在 iOS、Android 和鸿蒙平台的一致性表现。核心特性包括: 语义化色彩系统(PALETTE)支持主题化和情感化设计 精确像素栅格布局实现跨端视觉一致性 动态进度条采用百分比宽度计算和主题色绑定 相册分类导航提供即时交互反馈 分布式能力预留接口支持鸿蒙设备协同 技术亮点
这段 React Native 代码展示了一个家庭相册应用的用户界面实现,采用了现代化的声明式 UI 构建模式和状态管理机制。在鸿蒙跨端适配的技术背景下,该实现通过统一的状态驱动架构(useState Hook)和平台抽象组件(SafeAreaView、TouchableOpacity 等)确保了在不同操作系统间的一致性表现。
React Native 相册应用实现了现代化跨端 UI 设计,采用函数式组件和 useState Hook 管理状态,确保在 iOS、Android 和鸿蒙平台的一致性表现。核心特性包括:
- 语义化色彩系统(PALETTE)支持主题化和情感化设计
- 精确像素栅格布局实现跨端视觉一致性
- 动态进度条采用百分比宽度计算和主题色绑定
- 相册分类导航提供即时交互反馈
- 分布式能力预留接口支持鸿蒙设备协同
技术亮点:
- 样式与逻辑解耦,提升可维护性
- TouchableOpacity 组件保障跨平台触控体验
- 视图层完全基于 RN 原生组件,确保鸿蒙适配性
- 数据驱动 UI 更新机制屏蔽平台差异
该实现展示了 React Native 在鸿蒙生态中的可行性,通过统一的 JavaScript 代码库即可覆盖多端需求,为家庭相册类应用提供了可靠的跨端解决方案。
状态管理方面,通过 useState Hook 实现的 selectedAlbum 状态变量体现了函数式组件内部维持本地状态的最佳实践。当用户点击不同的相册项目时,组件能够实时响应并更新选中状态,同时通过条件样式绑定实现视觉反馈效果。这种数据驱动的 UI 更新机制在鸿蒙跨端开发中尤为重要,因为它能够屏蔽不同平台原生 UI 系统的差异性。
在视觉呈现层面,代码采用了栅格布局(grid)和卡片式设计(card),通过 TouchableOpacity 组件实现触摸交互反馈。进度条组件的设计巧妙地利用了 View 组件的 width 属性绑定,通过计算百分比值实现动态进度可视化效果。这种实现方式在鸿蒙设备上能够保持流畅的动画表现,体现了良好的性能优化意识。
对于图片资源的处理,虽然当前代码使用了 Base64 编码的占位图,但在实际鸿蒙跨端部署中,建议采用网络图片或本地资源引用的方式以提升加载性能。Alert 组件作为 React Native 提供的跨平台 API,在鸿蒙系统中能够保持一致的行为表现,这体现了 React Native 生态良好的平台兼容性。
这段代码以函数式组件呈现了一个完整的相册页:概览统计、进度条、操作入口、栅格相册、回忆列表与页脚,全部构建于 React Native 的内置能力之上,不依赖第三方库。对于鸿蒙(OpenHarmony/HarmonyOS)环境,只要存在稳定的 RN 渲染桥(将 RN 视图映射到 ArkUI,JS 在 Hermes/JSCore 执行),即可在 iOS、Android 与鸿蒙端获得一致的视觉与交互表现。整体设计以“语义色 + 轻栅格 + 低耦合交互”为核心,强调跨端落地的稳定性和工程可维护性。
样式合成
界面用 PALETTE 搭建语义化的主题色板,涵盖主色、强调色、语义色(success/warn/danger)以及文本层级(textMain/textSub)。渲染时将样式按主题合并为局部变量(如 containerStyle、titleStyle 等),避免在 JSX 中散落的内联计算,提高可读性与复用性。语义色的好处在跨端场景尤其明显:不同设备的色域和系统字体渲染会带来微差,用语义映射可保持风格的一致,并为后续暗色模式或品牌换肤留出空间。
数据流
组件以单页容器 App 为根,所有交互与状态由该容器统一管理:selectedAlbum 承载相册选中态;统计数据直接硬编码于 UI,强调演示属性。事件处理集中在 onAlbumPress/onAction 两个入口,使用 Alert 给出即时反馈。Alert 属于 RN 的原生弹窗抽象,跨端通过桥映射到各平台的系统弹窗,鸿蒙端对应 ArkUI 的对话框能力,确保交互语义一致。
进度条
进度条使用一个相对定位容器 progressWrap 包裹两层绝对定位视图:progressBar 作为背景、progressInner 表示当前进度。核心在于 progressInner 的宽度采用百分比字符串(如 45%),配合 overflow:‘hidden’ 与圆角裁切实现干净的视觉效果。这一模式在 RN→ArkUI 的桥接下稳定可靠;绝对/相对定位、圆角与裁切都属于基础能力,对跨端差异不敏感。
进度色采用主题主色(primary)而非固定值,既维持风格统一又能在达标/未达标时扩展为语义联动(例如切换为 success)。如果未来引入动效,建议用 Animated 的原生驱动(useNativeDriver:true)为宽度变化叠加平滑过渡,减轻 JS 线程负载,在鸿蒙端获得更稳的帧时间。
自适应
“相册栅格”采用精确像素栅格:(width - 162 - 123)/4 计算四列卡片宽度,将屏宽、容器内边距与列间距纳入统一公式。与百分比或 flex 平分相比,这种方法在不同平台与不同密度屏幕上表现更一致,避免因分配算法差异导致的断行或溢出。Dimensions.get(‘window’) 在 RN 中是稳定的数据源;在鸿蒙设备上同样能获得屏幕宽度,并通过桥进行正确的布局映射。
列表视图与操作通道
“回忆列表”遵循两列结构:左侧图标与文案,右侧操作按钮。按钮以边框色承载语义,文本颜色与边框同步,形成简洁的视觉联动。交互统一走 onAction,弹窗提示“查看”行为。这样的组织既便于埋点与权限控制,也方便后续引入导航(例如将 onAction 替换为路由跳转),不会破坏视图层。
在跨端适配上,TouchableOpacity 是一个稳妥选择:按压态与可点击语义在三端都一致。如果需要更细腻的触控反馈(涟漪/长按),可以改为 Pressable 并定制反馈,在鸿蒙端映射到 ArkUI 的手势系统同样可控。
RN ↔ ArkUI 的跨端映射重点
React Native 的基础组件(SafeAreaView、View、Text、Image、ScrollView、TouchableOpacity、Alert)都属于稳定抽象层。在鸿蒙端,它们通过 RN 渲染桥映射到 ArkUI 的安全区容器、布局、文本、图片、滚动与手势组件。JS 线程负责状态与逻辑,UI 线程负责渲染与触控,桥负责事件派发与属性同步。只要不依赖平台特化能力(如复杂阴影、专用字体渲染),这类页面可以做到“一处实现,多端一致”。
按需引入持久化
当前页面不使用动画,计算量小,性能开销极低。为未来的产品化演进,建议将主题抽象为 Design Token/Context,拆分卡片与栅格项为独立组件,赋予清晰的属性边界;将栅格宽度与进度色等“计算型样式”做微动效;对事件处理函数使用 useCallback 或将交互组件制成纯组件,减少重渲染。
数据层可按需引入持久化:在 RN 侧用 AsyncStorage 保存相册选中与统计;迁移到鸿蒙时替换为 Preferences/DataAbility,实现端上存储与媒体库读取。网络/云端备份则用统一的 API 层,跨端完全复用。
业务落地
这份“家庭相册”页已具备在鸿蒙端稳定运行的跨端基础。面向真实业务落地,推荐路径是“样式系统化 → 组件模块化 → 数据与导航接入 → 动效原生驱动”。主题与栅格的设计能在三端保持统一节奏;组件拆分让复用与测试更容易;数据与导航接入时不破坏视图层;动效采用 useNativeDriver 保证在鸿蒙设备上流畅。在不改变 React Native 抽象的前提下,既能快速迭代,又能保证跨端一致的体验与工程质量。
情感化色彩体系
相册应用建立了富有情感色彩的设计系统:
const PALETTE = {
bg: '#fff7fb',
card: '#ffffff',
primary: '#e11d48',
accent: '#4f46e5',
textMain: '#0b1021',
textSub: '#4b5563',
success: '#22c55e',
warn: '#f59e0b',
danger: '#ef4444',
muted: '#e5e7eb'
};
这种色彩系统在家庭应用中展现了重要的情感化设计价值。通过温暖的主色调、鲜明的强调色和柔和的背景色,营造了温馨的家庭氛围。在鸿蒙平台上,这种设计可以无缝对接鸿蒙的视觉语言系统,实现跨设备的统一情感化体验。
动态主题派生机制
应用实现了智能的主题样式派生:
const containerStyle = { ...styles.container, backgroundColor: t.bg };
const titleStyle = { ...styles.title, color: t.textMain };
const actionPrimaryStyle = { ...styles.action, backgroundColor: t.primary };
这种派生机制在主题管理中展现了强大的设计一致性保障。通过基础样式扩展、语义化颜色映射和动态主题应用,提供了灵活的视觉适配方案。在跨平台开发中,需要特别注意深色模式的适配和可访问性。鸿蒙平台的原生主题系统可以提供更系统的主题切换和更完善的视觉层次。
相册管理与交互设计
智能相册分类系统
组件采用了直观的相册分类导航:
const onAlbumPress = (name) => {
setSelectedAlbum(name);
Alert.alert('相册选择', `已选择:${name}`);
};
这种分类系统在相册应用中展现了重要的内容组织能力。通过语义化分类、即时反馈和视觉标记,提供了清晰的相册导航体验。在跨平台开发中,需要特别注意大量相册的性能优化。鸿蒙平台的分布式文件管理可以提供更高效的相册同步和更快的浏览体验。
情感化视觉编码
应用实现了丰富的视觉情感表达:
<TouchableOpacity style={selectedAlbum==='旅行' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#ef4444' }} />
<Text style={gridLabelStyle}>旅行</Text>
</TouchableOpacity>
这种视觉编码在家庭应用中展现了重要的情感连接能力。通过色彩情感映射、图标语义化和状态反馈,营造了温馨的回忆氛围。在鸿蒙平台上,这种设计可以利用鸿蒙的图形引擎实现更丰富的视觉表现和更细腻的情感表达。
鸿蒙跨端适配关键技术
分布式相册同步
鸿蒙的分布式特性为家庭相册带来创新体验:
// 伪代码:分布式相册同步
const DistributedAlbum = {
syncFamilyPhotos: (albumData) => {
if (Platform.OS === 'harmony') {
harmonyNative.syncPhotoAlbums(albumData);
}
},
getCrossDeviceAlbums: () => {
if (Platform.OS === 'harmony') {
return harmonyNative.getUnifiedAlbums();
}
return localAlbums;
}
};
智能照片管理
利用鸿蒙的原生媒体能力提升体验:
// 伪代码:智能管理
const IntelligentPhotoManagement = {
autoCategorizePhotos: () => {
if (Platform.OS === 'harmony') {
harmonyNative.analyzePhotoContent();
}
},
optimizePhotoStorage: () => {
if (Platform.OS === 'harmony') {
harmonyNative.compressAndOrganize();
}
}
};
AI回忆生成
鸿蒙平台为相册应用提供智能回忆能力:
// 伪代码:AI回忆
const AIRecollection = {
generateMemoryStories: () => {
if (Platform.OS === 'harmony') {
harmonyNative.createMemoryCollages();
}
},
suggestPhotoEnhancements: () => {
if (Platform.OS === 'harmony') {
harmonyNative.enhancePhotoQuality();
}
}
};
用户体验与家庭场景
家庭共享体验
应用设计了温馨的家庭共享功能:
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#ef4444' }} />
<View style={styles.memoryTextBox}>
<Text style={styles.memoryTitle}>川西之旅 · 第一天</Text>
<Text style={styles.memorySub}>2025-10-02 · 旅行 · 28 张</Text>
</View>
</View>
<TouchableOpacity style={styles.memoryBtn} onPress={() => onAction('查看:川西之旅 · 第一天')}>
<Text style={styles.memoryBtnText}>查看</Text>
</TouchableOpacity>
</View>
这种共享体验在家庭应用中展现了重要的情感连接价值。通过结构化的回忆展示、丰富的元数据和便捷的查看操作,提供了温馨的家庭共享体验。在鸿蒙平台上,这种设计可以对接鸿蒙的家庭服务,实现更丰富的家庭互动和更智能的回忆推荐。
多设备协同浏览
// 伪代码:多设备协同
const MultiDeviceViewing = {
enableCrossScreenViewing: () => {
if (Platform.OS === 'harmony') {
harmonyNative.syncViewingSession();
}
},
supportRemoteControl: () => {
if (Platform.OS === 'harmony') {
harmonyNative.allowDeviceControl();
}
}
};
架构演进方向
智能回忆 curation
// 伪代码:智能 curation
const SmartRecollection = {
curateBestMoments: () => {
if (Platform.OS === 'harmony') {
harmonyNative.selectHighlightPhotos();
}
},
createTimelineStories: () => {
if (Platform.OS === 'harmony') {
harmonyNative.generateTimeBasedStories();
}
}
};
沉浸式回忆体验
// 伪代码:沉浸体验
const ImmersiveRecollection = {
enableVRViewing: () => {
if (Platform.OS === 'harmony') {
harmonyNative.launchVRExperience();
}
},
supportSpatialAudio: () => {
if (Platform.OS === 'harmony') {
harmonyNative.addSpatialSoundscapes();
}
}
};
真实演示案例代码:
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Dimensions, Alert } from 'react-native';
const PALETTE = {
bg: '#fff7fb',
card: '#ffffff',
primary: '#e11d48',
accent: '#4f46e5',
textMain: '#0b1021',
textSub: '#4b5563',
success: '#22c55e',
warn: '#f59e0b',
danger: '#ef4444',
muted: '#e5e7eb'
};
const ICON_BASE64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9YpW2XcAAAAASUVORK5CYII=';
const App = () => {
const t = PALETTE;
const [selectedAlbum, setSelectedAlbum] = useState(null);
const onAlbumPress = (name) => {
setSelectedAlbum(name);
Alert.alert('相册选择', `已选择:${name}`);
};
const onAction = (title) => {
Alert.alert('操作提示', `${title}(样式演示)`);
};
const containerStyle = { ...styles.container, backgroundColor: t.bg };
const titleStyle = { ...styles.title, color: t.textMain };
const subtitleStyle = { ...styles.subtitle, color: t.textSub };
const cardStyle = { ...styles.card, backgroundColor: t.card };
const gridLabelStyle = { ...styles.gridLabel, color: t.textMain };
const statTextStyle = { ...styles.statText, color: t.textSub };
const statValueStyle = { ...styles.statValue, color: t.textMain };
const progressBarStyle = { ...styles.progressBar, backgroundColor: t.muted };
const progressInnerStyle = { ...styles.progressInner, width: '45%', backgroundColor: t.primary };
const actionPrimaryStyle = { ...styles.action, backgroundColor: t.primary };
const actionAccentStyle = { ...styles.action, backgroundColor: t.accent };
const actionWarnStyle = { ...styles.action, backgroundColor: t.warn };
const actionTextStyle = { ...styles.actionText };
const footerTextStyle = { ...styles.footerText, color: t.textSub };
return (
<SafeAreaView style={containerStyle}>
<ScrollView contentContainerStyle={styles.content}>
<View style={styles.header}>
<Text style={titleStyle}>家庭相册 · 回忆列表</Text>
<Text style={subtitleStyle}>霓虹玫红与靛紫风格 · 元素丰富 · 文案简洁</Text>
</View>
<View style={cardStyle}>
<Text style={styles.cardTitle}>相册概览</Text>
<View style={styles.statRow}>
<View style={styles.statItem}>
<Text style={statTextStyle}>总相册数</Text>
<Text style={statValueStyle}>8</Text>
</View>
<View style={styles.statItem}>
<Text style={statTextStyle}>照片数量</Text>
<Text style={statValueStyle}>326</Text>
</View>
<View style={styles.statItem}>
<Text style={statTextStyle}>最近更新</Text>
<Text style={statValueStyle}>2026-01-12</Text>
</View>
</View>
<View style={styles.progressWrap}>
<View style={progressBarStyle} />
<View style={progressInnerStyle} />
</View>
<View style={styles.actionsRow}>
<TouchableOpacity style={actionPrimaryStyle} onPress={() => onAction('新建相册')}>
<Text style={actionTextStyle}>新建相册</Text>
</TouchableOpacity>
<TouchableOpacity style={actionAccentStyle} onPress={() => onAction('导入照片')}>
<Text style={actionTextStyle}>导入照片</Text>
</TouchableOpacity>
<TouchableOpacity style={actionWarnStyle} onPress={() => onAction('导出备份')}>
<Text style={actionTextStyle}>导出备份</Text>
</TouchableOpacity>
</View>
</View>
<View style={cardStyle}>
<Text style={styles.cardTitle}>相册栅格</Text>
<View style={styles.grid}>
<TouchableOpacity style={selectedAlbum==='旅行' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('旅行')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#ef4444' }} />
<Text style={gridLabelStyle}>旅行</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='生日' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('生日')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#f59e0b' }} />
<Text style={gridLabelStyle}>生日</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='婚礼' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('婚礼')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#4f46e5' }} />
<Text style={gridLabelStyle}>婚礼</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='宝宝' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('宝宝')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#22c55e' }} />
<Text style={gridLabelStyle}>宝宝</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='节日' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('节日')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#06b6d4' }} />
<Text style={gridLabelStyle}>节日</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='毕业' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('毕业')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#a78bfa' }} />
<Text style={gridLabelStyle}>毕业</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='春游' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('春游')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#f472b6' }} />
<Text style={gridLabelStyle}>春游</Text>
</TouchableOpacity>
<TouchableOpacity style={selectedAlbum==='聚会' ? { ...styles.gridItem, borderColor: t.primary, backgroundColor: '#fff1f2' } : styles.gridItem} onPress={() => onAlbumPress('聚会')}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.iconImg, tintColor: '#fbbf24' }} />
<Text style={gridLabelStyle}>聚会</Text>
</TouchableOpacity>
</View>
</View>
<View style={cardStyle}>
<Text style={styles.cardTitle}>回忆列表</Text>
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#ef4444' }} />
<View style={styles.memoryTextBox}>
<Text style={{ ...styles.memoryTitle, color: t.textMain }}>川西之旅 · 第一天</Text>
<Text style={{ ...styles.memorySub, color: t.textSub }}>2025-10-02 · 旅行 · 28 张</Text>
</View>
</View>
<View style={styles.memoryRight}>
<TouchableOpacity style={{ ...styles.memoryBtn, borderColor: '#ef4444' }} onPress={() => onAction('查看:川西之旅 · 第一天')}>
<Text style={{ ...styles.memoryBtnText, color: '#ef4444' }}>查看</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#f59e0b' }} />
<View style={styles.memoryTextBox}>
<Text style={{ ...styles.memoryTitle, color: t.textMain }}>妈妈生日 · 家庭聚餐</Text>
<Text style={{ ...styles.memorySub, color: t.textSub }}>2025-06-18 · 生日 · 15 张</Text>
</View>
</View>
<View style={styles.memoryRight}>
<TouchableOpacity style={{ ...styles.memoryBtn, borderColor: '#f59e0b' }} onPress={() => onAction('查看:妈妈生日 · 家庭聚餐')}>
<Text style={{ ...styles.memoryBtnText, color: '#f59e0b' }}>查看</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#4f46e5' }} />
<View style={styles.memoryTextBox}>
<Text style={{ ...styles.memoryTitle, color: t.textMain }}>婚礼现场 · 倒计时</Text>
<Text style={{ ...styles.memorySub, color: t.textSub }}>2024-09-20 · 婚礼 · 42 张</Text>
</View>
</View>
<View style={styles.memoryRight}>
<TouchableOpacity style={{ ...styles.memoryBtn, borderColor: '#4f46e5' }} onPress={() => onAction('查看:婚礼现场 · 倒计时')}>
<Text style={{ ...styles.memoryBtnText, color: '#4f46e5' }}>查看</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#22c55e' }} />
<View style={styles.memoryTextBox}>
<Text style={{ ...styles.memoryTitle, color: t.textMain }}>宝宝满月 · 纪念</Text>
<Text style={{ ...styles.memorySub, color: t.textSub }}>2026-01-08 · 宝宝 · 18 张</Text>
</View>
</View>
<View style={styles.memoryRight}>
<TouchableOpacity style={{ ...styles.memoryBtn, borderColor: '#22c55e' }} onPress={() => onAction('查看:宝宝满月 · 纪念')}>
<Text style={{ ...styles.memoryBtnText, color: '#22c55e' }}>查看</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.memoryRow}>
<View style={styles.memoryLeft}>
<Image source={{ uri: ICON_BASE64 }} style={{ ...styles.memoryIcon, tintColor: '#06b6d4' }} />
<View style={styles.memoryTextBox}>
<Text style={{ ...styles.memoryTitle, color: t.textMain }}>新年合照 · 迎新</Text>
<Text style={{ ...styles.memorySub, color: t.textSub }}>2026-01-01 · 节日 · 20 张</Text>
</View>
</View>
<View style={styles.memoryRight}>
<TouchableOpacity style={{ ...styles.memoryBtn, borderColor: '#06b6d4' }} onPress={() => onAction('查看:新年合照 · 迎新')}>
<Text style={{ ...styles.memoryBtnText, color: '#06b6d4' }}>查看</Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.footer}>
<Text style={footerTextStyle}>© 家庭相册 · 霓虹玫红风格</Text>
</View>
</ScrollView>
</SafeAreaView>
);
};
const { width } = Dimensions.get('window');
const styles = StyleSheet.create({
container: { flex: 1 },
content: { padding: 16 },
header: { paddingVertical: 16, alignItems: 'center' },
title: { fontSize: 26, fontWeight: '800' },
subtitle: { fontSize: 13, marginTop: 6 },
card: { borderRadius: 16, padding: 16, marginBottom: 14, shadowColor: '#000', shadowOpacity: 0.06, shadowRadius: 8, shadowOffset: { width: 0, height: 4 } },
cardTitle: { fontSize: 18, fontWeight: '700', marginBottom: 10 },
statRow: { flexDirection: 'row' },
statItem: { flex: 1 },
statText: { fontSize: 12 },
statValue: { fontSize: 16, fontWeight: '700', marginTop: 4 },
progressWrap: { height: 10, borderRadius: 8, marginTop: 12, position: 'relative', overflow: 'hidden' },
progressBar: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 },
progressInner: { position: 'absolute', top: 0, left: 0, bottom: 0 },
actionsRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 },
action: { flex: 1, borderRadius: 12, paddingVertical: 10, alignItems: 'center', marginRight: 10 },
actionText: { color: '#ffffff', fontSize: 14, fontWeight: '600' },
grid: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' },
gridItem: { width: (width - 16 * 2 - 12 * 3) / 4, borderWidth: 1, borderColor: '#e2e8f0', borderRadius: 14, paddingVertical: 14, alignItems: 'center', marginBottom: 12, backgroundColor: '#ffffff' },
iconImg: { width: 28, height: 28, borderRadius: 14, marginBottom: 8 },
gridLabel: { fontSize: 12, fontWeight: '600' },
memoryRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#f1f5f9' },
memoryLeft: { flexDirection: 'row', alignItems: 'center' },
memoryIcon: { width: 30, height: 30, borderRadius: 15 },
memoryTextBox: { marginLeft: 10 },
memoryTitle: { fontSize: 14, fontWeight: '700' },
memorySub: { fontSize: 12, marginTop: 2 },
memoryRight: { alignItems: 'flex-end' },
memoryBtn: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 10, paddingVertical: 4 },
memoryBtnText: { fontSize: 12, fontWeight: '600' },
footer: { paddingVertical: 14, alignItems: 'center' },
footerText: { fontSize: 12 }
});
export default App;

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

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

最后运行效果图如下显示:
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐


所有评论(0)