RN for OpenHarmony AnimeHub项目实战:关于页面开发

案例开源地址:https://atomgit.com/nutpi/Rn_openharmony_AnimeHub

关于页展示应用的基本信息,包括应用名称、版本号、功能介绍和技术栈。这篇来讲关于页的实现,重点是信息展示布局和品牌形象设计。

功能设计

关于页需要展示以下信息:

  • 应用标识 - Logo、名称、版本号
  • 功能介绍 - 应用是做什么的
  • 数据来源 - 数据从哪里来
  • 技术栈 - 使用了什么技术

关于页是应用的"名片",虽然用户不常访问,但它体现了应用的专业性和透明度。好的关于页应该简洁明了,让用户快速了解应用。

关于页还有法律合规的作用。展示数据来源和版权声明,可以避免潜在的法律问题。特别是使用第三方 API 时,明确说明数据来源是对原创者的尊重。
从用户心理角度看,关于页可以增加用户对应用的信任感。一个有完整关于页的应用,给人的感觉是"正规"、"专业"的,而不是"山寨"、"不靠谱"的。

组件导入

typescript 复制代码
import React from 'react';
import { View, ScrollView, StyleSheet, Text, Image, Linking } from 'react-native';
import { Colors, FontSize, Spacing, BorderRadius } from '../../theme';
import { Header, Icon } from '../../components/common';

导入说明:

  • ScrollView - 滚动容器,因为关于页内容可能超出一屏
  • Image - 图片组件,虽然当前用 Icon 代替,但保留了扩展性
  • Linking - 用于打开外部链接(虽然当前代码没用到,但保留了扩展性)
  • 其他是常规的组件和样式导入

Linking 是 React Native 提供的模块,可以打开 URL、拨打电话、发送邮件等。在关于页中,可能需要链接到官网、GitHub 仓库或反馈邮箱。虽然当前没用到,但导入了方便后续扩展。
导入但暂时不用的模块,在开发阶段是常见的。这表示开发者已经考虑到了这些功能,只是还没实现。当然,在正式发布前应该清理掉真正不需要的导入。

页面结构

typescript 复制代码
export const AboutScreen = ({ navigation }: any) => {
  return (
    <View style={styles.container}>
      <Header title="关于" showBack onBack={() => navigation.goBack()} />
      <ScrollView contentContainerStyle={styles.content}>

基础结构:

  • Header 显示标题和返回按钮
  • ScrollView 包裹内容
  • contentContainerStyle 设置内容容器样式

contentContainerStylestyle 的区别是 React Native 初学者常见的困惑点:

  • style 作用于 ScrollView 本身,控制 ScrollView 这个容器的样式
  • contentContainerStyle 作用于内部的内容容器,控制 ScrollView 里面内容的样式
    这里用 contentContainerStyle 设置内边距和居中对齐,是因为我们要控制的是内容的布局,而不是 ScrollView 本身。如果用 style 设置 padding,内容滚动时 padding 会固定不动,效果不对。
typescript 复制代码
<View style={styles.logoContainer}>
  <View style={styles.logo}>
    <Icon name="movie" size={48} color={Colors.primary} />
  </View>
  <Text style={styles.appName}>AnimeHub</Text>
  <Text style={styles.version}>版本 1.0.0</Text>
</View>

Logo 区域组成:

  • Logo 图标(用 Icon 组件代替图片)
  • 应用名称
  • 版本号

这里用 Icon 组件代替真实的 Logo 图片。在实际项目中,应该使用设计好的 Logo 图片。Icon 组件的好处是不需要额外的图片资源,适合原型开发和教程演示。
如果要用真实的 Logo 图片,代码会是这样:

typescript 复制代码
<Image 
  source={require('../../assets/logo.png')} 
  style={styles.logoImage} 
/>

版本号的格式 "1.0.0" 遵循语义化版本规范(Semantic Versioning):

  • 第一位(1)- 主版本号,有重大更新或不兼容的改动时增加
  • 第二位(0)- 次版本号,有新功能但向后兼容时增加
  • 第三位(0)- 修订号,有 bug 修复时增加
typescript 复制代码
logoContainer: {
  alignItems: 'center',
  marginBottom: Spacing.xxxl,
},
logo: {
  width: 100,
  height: 100,
  borderRadius: BorderRadius.xl,
  backgroundColor: Colors.primary + '20',
  alignItems: 'center',
  justifyContent: 'center',
  marginBottom: Spacing.md,
},

样式说明:

  • Logo 容器居中对齐,底部有较大间距
  • Logo 是 100x100 的圆角方形
  • 半透明主题色背景
  • 图标在容器内居中

Logo 的尺寸选择 100x100 是一个常见的大小,在手机屏幕上既醒目又不会太大。太小会显得不够重要,太大会占用太多空间。
borderRadius: BorderRadius.xl 让 Logo 有圆角。圆角的大小会影响视觉感受:小圆角显得硬朗,大圆角显得柔和。xl 级别的圆角让 Logo 看起来更友好。
Colors.primary + '20' 是在颜色值后面加透明度。假设 primary 是 '#6366F1',加上 '20' 后变成 '#6366F120',其中 20 是十六进制的透明度(约 12.5%)。这样背景是淡淡的主题色,不会太突兀。

typescript 复制代码
appName: {
  fontSize: FontSize.xxl,
  fontWeight: '700',
  color: Colors.text,
},
version: {
  fontSize: FontSize.sm,
  color: Colors.textSecondary,
  marginTop: Spacing.xs,
},

文字样式:

  • 应用名称用超大字号(xxl,可能是 24-28px),加粗(700)
  • 版本号用小字号(sm,可能是 12-14px),次要颜色(灰色)

应用名称是页面的视觉焦点,所以用最大的字号和最粗的字重。这是视觉层次的体现:重要的内容要突出,次要的内容要弱化。
版本号是辅助信息,用小字号和灰色,不抢夺注意力。用户通常不关心版本号,但在反馈问题时可能需要提供,所以还是要显示。
fontWeight: '700' 是加粗。在 CSS/React Native 中,字重从 100(最细)到 900(最粗),400 是正常,700 相当于 bold。

关于应用区块

typescript 复制代码
<View style={styles.section}>
  <Text style={styles.sectionTitle}>关于应用</Text>
  <Text style={styles.description}>
    AnimeHub 是一款动漫信息浏览应用,使用 Jikan API 获取 MyAnimeList 的数据。
    你可以浏览热门动漫、搜索感兴趣的作品、查看详细信息和评论。
  </Text>
</View>

内容说明:

  • 简要介绍应用的功能
  • 说明数据来源

应用介绍应该简洁明了,用一两句话说清楚应用是做什么的。用户不会在关于页花太多时间,所以信息要精炼。
这段介绍回答了三个问题:

  1. 这是什么应用?- 动漫信息浏览应用
  2. 数据从哪来?- Jikan API / MyAnimeList
  3. 能做什么?- 浏览、搜索、查看详情和评论
    好的应用介绍应该让用户在 5 秒内理解应用的价值。如果需要长篇大论才能解释清楚,说明应用定位不够清晰。

数据来源区块

typescript 复制代码
<View style={styles.section}>
  <Text style={styles.sectionTitle}>数据来源</Text>
  <Text style={styles.description}>
    本应用数据来自 Jikan API,这是一个非官方的 MyAnimeList API。
    所有动漫信息、图片和评论版权归原作者所有。
  </Text>
</View>

内容说明:

  • 说明数据来自 Jikan API
  • 声明版权归属

版权声明很重要。使用第三方 API 的数据时,应该明确说明数据来源和版权归属。这是对原创者的尊重,也是法律合规的要求。
"非官方的 MyAnimeList API" 这个说明很重要。Jikan API 是社区维护的,不是 MyAnimeList 官方提供的。明确这一点可以避免用户误解。
"版权归原作者所有" 是一个通用的免责声明。动漫的版权属于制作公司和原作者,我们只是展示信息,不拥有这些内容的版权。

技术栈区块

typescript 复制代码
<View style={styles.section}>
  <Text style={styles.sectionTitle}>技术栈</Text>
  <View style={styles.techList}>
    <View style={styles.techItem}>
      <Icon name="code" size={16} color={Colors.primary} />
      <Text style={styles.techText}>React Native</Text>
    </View>
    <View style={styles.techItem}>
      <Icon name="globe" size={16} color={Colors.primary} />
      <Text style={styles.techText}>Jikan API v4</Text>
    </View>
  </View>
</View>

技术栈展示:

  • React Native - 开发框架
  • Jikan API v4 - 数据接口

展示技术栈是开发者的习惯,也是对开源社区的致敬。用户可能不关心技术细节,但对于技术爱好者来说,这是有价值的信息。
每个技术项用图标 + 文字的形式展示:

  • code 图标代表代码/开发框架

  • globe 图标代表网络/API
    技术栈还可以添加更多项目,比如:

  • TypeScript - 编程语言

  • Zustand - 状态管理

  • React Navigation - 导航库

区块样式

typescript 复制代码
section: {
  width: '100%',
  marginBottom: Spacing.xl,
},
sectionTitle: {
  fontSize: FontSize.lg,
  fontWeight: '600',
  color: Colors.text,
  marginBottom: Spacing.sm,
},
description: {
  fontSize: FontSize.md,
  color: Colors.textSecondary,
  lineHeight: 22,
},

样式说明:

  • 区块宽度 100%,占满容器
  • 区块之间有间距(xl)
  • 标题用大字号(lg),加粗(600)
  • 描述文字用中等字号(md),次要颜色
  • lineHeight: 22 增加行高,提高可读性

width: '100%' 是必要的,因为父容器设置了 alignItems: 'center',子元素默认会收缩到内容宽度。设置 100% 让区块占满宽度。
行高(lineHeight)对于多行文本很重要。默认的行高可能太紧凑,文字挤在一起不好阅读。22px 的行高配合 14-16px 的字号,行距大约是 1.4-1.6 倍,是比较舒适的阅读体验。
fontWeight: '600' 是半粗体,比正常(400)粗,比粗体(700)细。用于标题可以突出但不会太重。

技术栈样式

typescript 复制代码
techList: {
  flexDirection: 'row',
  flexWrap: 'wrap',
  gap: Spacing.md,
},
techItem: {
  flexDirection: 'row',
  alignItems: 'center',
  gap: Spacing.sm,
  paddingHorizontal: Spacing.md,
  paddingVertical: Spacing.sm,
  backgroundColor: Colors.backgroundCard,
  borderRadius: BorderRadius.md,
},
techText: {
  fontSize: FontSize.sm,
  color: Colors.text,
},

样式说明:

  • 技术栈列表横向排列,自动换行
  • 每个技术项是一个小卡片
  • 卡片内有图标和文字,横向排列
  • 使用 gap 设置间距

flexWrap: 'wrap' 让子元素在一行放不下时自动换行。这样即使技术栈很多,也能正常显示,不会超出屏幕。
gap 是 Flexbox 的属性,用于设置子元素之间的间距。比用 margin 更方便,因为不需要处理第一个和最后一个元素的边距问题。
技术项设计成小卡片的形式,有背景色和圆角,看起来像"标签"。这种设计在现代应用中很常见,比纯文字列表更有视觉吸引力。

内容容器样式

typescript 复制代码
content: {
  padding: Spacing.xl,
  alignItems: 'center',
},

样式说明:

  • 四周有较大内边距(xl,可能是 24-32px)
  • 内容居中对齐

alignItems: 'center' 让所有子元素水平居中。这是关于页的常见布局,Logo 和文字都居中显示,看起来更正式、更有仪式感。
较大的内边距让内容不贴边,有"呼吸感"。关于页不需要塞很多内容,留白反而让页面更优雅。

可扩展的功能

关于页可以添加更多功能:

typescript 复制代码
// 打开官网
const openWebsite = () => {
  Linking.openURL('https://example.com');
};

// 发送反馈邮件
const sendFeedback = () => {
  Linking.openURL('mailto:feedback@example.com?subject=AnimeHub反馈');
};

// 打开 GitHub 仓库
const openGitHub = () => {
  Linking.openURL('https://github.com/example/animehub');
};

// 查看开源协议
const openLicense = () => {
  navigation.navigate('License');
};

可添加的功能:

  • 官网链接 - 让用户了解更多
  • 反馈邮箱 - 收集用户反馈
  • GitHub 仓库 - 开源项目必备
  • 开源协议 - 说明代码的使用许可
  • 隐私政策 - 应用商店上架要求
  • 用户协议 - 应用商店上架要求
  • 更新日志 - 让用户了解版本变化

这些功能在实际项目中可能是必需的。特别是隐私政策和用户协议,在应用商店上架时通常是必须提供的。苹果和谷歌都要求应用提供隐私政策链接。

Linking 的使用详解

typescript 复制代码
// 打开网页
Linking.openURL('https://example.com');

// 打开邮件,可以预填主题和内容
Linking.openURL('mailto:email@example.com?subject=主题&body=内容');

// 拨打电话
Linking.openURL('tel:+8612345678901');

// 发送短信
Linking.openURL('sms:+8612345678901');

// 打开地图(iOS)
Linking.openURL('maps://app?daddr=北京市');

// 打开应用商店
Linking.openURL('market://details?id=com.example.app'); // Android
Linking.openURL('itms-apps://itunes.apple.com/app/id123456789'); // iOS

Linking 支持的协议:

  • https:// - 打开网页,会调用系统浏览器
  • mailto: - 打开邮件应用,可以预填收件人、主题、内容
  • tel: - 打开电话应用,准备拨打指定号码
  • sms: - 打开短信应用
  • market:// - 打开 Android 应用商店
  • itms-apps:// - 打开 iOS App Store

Linking 是跨平台的,但某些协议只在特定平台有效。使用前最好用 Linking.canOpenURL() 检查是否支持:

typescript 复制代码
const supported = await Linking.canOpenURL(url);
if (supported) {
  await Linking.openURL(url);
} else {
  Alert.alert('无法打开链接');
}

在鸿蒙系统上,Linking 的行为可能有所不同,需要实际测试。但基本的 https 链接应该是支持的。

版本号的管理

当前版本号是硬编码的:

typescript 复制代码
<Text style={styles.version}>版本 1.0.0</Text>

更好的做法是从配置文件读取:

typescript 复制代码
// 方案一:从 package.json 读取
import { version } from '../../package.json';

<Text style={styles.version}>版本 {version}</Text>
typescript 复制代码
// 方案二:使用 react-native-device-info 库
import DeviceInfo from 'react-native-device-info';

const version = DeviceInfo.getVersion(); // 如 "1.0.0"
const buildNumber = DeviceInfo.getBuildNumber(); // 如 "1"

<Text style={styles.version}>版本 {version} ({buildNumber})</Text>

从 package.json 读取版本号可以保证关于页显示的版本和实际版本一致。每次发版只需要修改 package.json,不需要手动更新关于页。
react-native-device-info 是一个常用的库,可以获取设备和应用的各种信息,包括版本号、设备型号、系统版本等。如果需要更多设备信息,推荐使用这个库。
显示 build number 对于测试和问题排查很有帮助。同一个版本号可能有多个 build,通过 build number 可以精确定位。

设计原则

关于页的设计原则:

  • 简洁 - 信息精炼,不要堆砌,用户不会在这里花太多时间
  • 专业 - 体现应用的品质,Logo、排版、文案都要讲究
  • 透明 - 说明数据来源和版权,建立用户信任
  • 可访问 - 提供联系方式,让用户能够反馈问题

关于页虽然不是核心功能,但它是应用的"门面"之一。一个精心设计的关于页可以提升用户对应用的信任感。
很多开发者忽视关于页,随便写几行文字就完事。但用户在决定是否信任一个应用时,可能会看关于页。一个完善的关于页说明开发者是认真的。

与设置页的关系

关于页通常从设置页进入:

typescript 复制代码
// 设置页中
<SettingItem
  icon="info"
  title="关于"
  onPress={() => navigation.navigate('About')}
  showArrow
/>

导航路径:

个人中心 → 设置 → 关于

这是常见的导航结构。关于页是设置页的子页面,用户需要两次点击才能到达。这符合用户的心理预期,因为关于页不是常用功能。
也有应用把关于页放在更显眼的位置,比如个人中心的底部。这取决于应用的定位和设计风格。

关于页的法律意义

关于页不仅是展示信息,还有法律意义:

  • 版权声明 - 说明内容的版权归属,避免侵权纠纷
  • 隐私政策 - 说明如何收集和使用用户数据,是 GDPR 等法规的要求
  • 用户协议 - 规定用户使用应用的条款,保护开发者权益
  • 开源协议 - 如果使用了开源代码,需要遵守相应的协议

在中国,应用上架各大应用商店都需要提供隐私政策。在欧洲,GDPR 要求更严格。在美国,CCPA 也有类似要求。关于页是放置这些法律文件链接的合适位置。

小结

关于页是应用的信息展示页面,包含 Logo、应用名称、版本号、功能介绍、数据来源和技术栈。页面布局居中对齐,信息分区块展示,整体风格简洁专业。

Logo 区域是页面的视觉焦点,用大尺寸图标和粗体文字突出显示。描述文字用次要颜色和适当的行高,提高可读性。技术栈用小卡片的形式展示,横向排列,自动换行。

关于页还可以扩展更多功能,如官网链接、反馈邮箱、开源协议等。Linking 模块可以打开外部链接、邮件、电话等,是实现这些功能的关键。

版本号建议从配置文件读取,而不是硬编码,这样可以保证显示的版本和实际版本一致。关于页虽然不是核心功能,但体现了应用的专业性和开发者的态度。

下一篇会讲放送时间表页面,展示每周的动漫播出时间。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
乌鸦乌鸦你的小虎牙1 小时前
qt 5.12.8 配置报错(交叉编译环境)
开发语言·数据库·qt
一只大袋鼠2 小时前
Redis 安装+基于短信验证码登录功能的完整实现
java·开发语言·数据库·redis·缓存·学习笔记
Anastasiozzzz2 小时前
深入研究Redis的ZSet底层数据结构:从 Ziplist 的级联更新到 Listpack 的完美救场
数据结构·数据库·redis
菠萝蚊鸭2 小时前
x86 平台使用 buildx 基于源码构建 MySQL Wsrep 5.7.44 镜像
数据库·mysql·galera·wsrep
沙漏无语4 小时前
(二)TIDB搭建正式集群
linux·数据库·tidb
姚不倒5 小时前
三节点 TiDB 集群部署与负载均衡搭建实战
运维·数据库·分布式·负载均衡·tidb
隔壁小邓5 小时前
批量更新方式与对比
数据库
数据知道5 小时前
MongoDB复制集架构原理:Primary、Secondary 与 Arbiter 的角色分工
数据库·mongodb·架构
人道领域5 小时前
苍穹外卖:菜品新增功能全流程解析
数据库·后端·状态模式
修行者Java5 小时前
(七)从 “非结构化数据难存储” 到 “MongoDB 灵活赋能”——MongoDB 实战进阶指南
数据库·mongodb