React Native鸿蒙跨平台采用ScrollView的horizontal属性实现横向滚动实现特色游戏轮播和分类导航

在跨端应用开发领域,React Native(RN)凭借"一次编写,多端运行"的核心优势,成为连接前端与原生应用的重要桥梁,而鸿蒙系统作为新兴的分布式操作系统,其对RN跨端开发的兼容与适配,更是为开发者提供了更广阔的应用场景------尤其是在移动应用开发中,游戏类APP的跨端需求尤为突出,既要保证多设备适配的流畅性,也要兼顾交互体验的一致性。本文将以一份完整的React Native游戏库APP代码为例,从跨端架构设计、核心功能实现、鸿蒙适配要点三个维度,进行全方位的技术解读,助力开发者快速掌握RN在鸿蒙跨端游戏类应用开发中的实践技巧。

这份代码实现了一个功能完善的万能游戏库APP,支持游戏分类导航、特色游戏推荐、游戏列表展示、分类筛选、基础交互反馈等核心功能,整体架构遵循RN组件化开发规范,采用函数式组件+React Hooks的主流开发模式,同时兼顾了鸿蒙系统的跨端适配特性,涵盖了RN鸿蒙跨端开发中常见的组件使用、布局适配、状态管理、列表渲染等核心技术点,是一份非常适合入门RN鸿蒙跨端游戏类应用开发的实践案例。

一、跨端架构:

React Native的跨端能力核心在于"虚拟DOM映射原生组件",而鸿蒙系统通过兼容RN的核心API,实现了RN代码在鸿蒙设备上的无缝运行------开发者无需大量修改RN代码,只需关注少数鸿蒙特有的适配细节,即可完成应用从iOS/Android到鸿蒙系统的迁移。这份游戏库APP代码,全程基于RN官方核心API开发,未引入任何平台特定的原生模块,完美契合鸿蒙跨端适配的核心需求,也体现了"跨端优先"的开发思路。

首先看代码入口的依赖引入部分,代码开篇引入了React的核心钩子(useState),以及RN官方提供的基础组件(SafeAreaView、View、Text、StyleSheet等),这些组件是RN跨端开发的基础,也是鸿蒙系统重点兼容的对象。其中,SafeAreaView、Dimensions、FlatList、ScrollView 四个组件是本次游戏库APP的核心,也是鸿蒙适配中的关键细节,需要重点解读:

SafeAreaView用于适配不同设备的安全区域,避免内容被状态栏、导航栏遮挡,在鸿蒙系统中,RN的SafeAreaView会自动映射到鸿蒙的SafeArea组件,无需额外开发适配代码,只需保持组件使用规范即可------这对于游戏类APP尤为重要,确保游戏列表、导航栏等核心内容在鸿蒙手机、平板等多形态设备上均能正常显示,不出现遮挡问题。

Dimensions组件用于获取设备屏幕尺寸,代码中通过const { width, height } = Dimensions.get('window')获取屏幕宽高,进而实现组件的自适应布局。鸿蒙系统支持多种形态的设备(手机、平板等),屏幕尺寸差异较大,这种动态获取屏幕尺寸的方式,能够确保组件在不同鸿蒙设备上的显示一致性。例如,游戏卡片的宽度设置为(width - 48) / 2,确保在不同宽度的鸿蒙设备上,均能实现两列均匀布局,避免出现卡片过宽、过窄或换行异常的问题。

FlatList和ScrollView是RN跨端开发中常用的列表与滚动组件,也是游戏库APP的核心组件------FlatList用于渲染游戏列表,支持分页、复用,提升列表渲染性能;ScrollView用于实现特色游戏轮播、分类导航的横向滚动,以及整体内容的纵向滚动。在鸿蒙系统中,这两个组件的核心属性(horizontal、showsHorizontalScrollIndicator、numColumns等)均可正常使用,滚动交互会自动适配鸿蒙设备的触摸事件,开发者无需关注不同平台的触摸事件差异,RN会自动完成映射,确保在鸿蒙设备上的滚动流畅性,避免出现卡顿、滚动异常等问题。

此外,代码中引入的Alert组件(用于实现交互反馈)、TouchableOpacity组件(用于实现可点击交互),也是RN跨端开发中常用的交互组件,鸿蒙系统对这些组件的适配已相当成熟,开发者可直接使用,无需担心原生交互差异。值得注意的是,代码中定义的ICONS_BASE64图标库(Base64格式图标),在鸿蒙系统中可正常渲染,避免了因图片路径、格式兼容问题导致的图标显示异常,这也是RN鸿蒙跨端开发中推荐的图标使用方式------Base64格式图标无需额外请求,加载更快,且兼容性更强,适配鸿蒙多设备场景。

二、组件化:

这份游戏库APP的核心功能围绕"游戏展示与分类"展开,整体采用React组件化开发模式,将APP拆分为头部导航、搜索栏、特色游戏轮播、分类导航、游戏列表、活动横幅、底部导航等多个独立组件,每个组件职责单一,既便于维护和复用,也符合跨端开发中"组件复用"的核心需求。同时,通过React Hooks(useState)实现状态管理,确保组件之间的状态通信简洁高效,这也是RN鸿蒙跨端开发中推荐的状态管理方式------无需引入复杂的第三方状态管理库(如Redux),降低跨端适配成本,同时提升代码的可读性和可维护性。

2.1 状态管理:

代码中通过useState钩子定义了APP的核心状态,包括游戏列表(games)、特色游戏列表(featuredGames)、游戏分类(categories)、选中的分类(selectedCategory),这些状态覆盖了APP的所有交互逻辑------游戏列表用于存储所有游戏数据,特色游戏列表用于展示推荐游戏,分类用于实现游戏筛选,选中的分类用于控制筛选结果的切换。

在鸿蒙系统中,React Hooks的运行机制与RN原生环境完全一致,无需任何修改即可正常工作,这也是RN跨端开发的一大优势------状态管理逻辑可在多端复用,无需针对鸿蒙系统单独编写状态管理代码。例如,分类筛选的逻辑实现:通过selectedCategory状态记录当前选中的分类,当用户点击分类按钮时,通过setSelectedCategory更新状态,进而通过filteredGames计算属性筛选出对应分类的游戏,最终通过FlatList渲染筛选结果。这段逻辑在iOS、Android、鸿蒙系统中完全通用,状态更新时的组件重渲染机制也完全一致,确保筛选功能在鸿蒙设备上的正常运行。

此外,代码中定义的Game类型接口(type Game),用于规范游戏数据的格式,这也是TS在RN跨端开发中的最佳实践------通过类型定义,避免数据格式异常导致的组件渲染错误,同时提升代码的可读性和可维护性。在鸿蒙系统中,TS的类型检查机制完全兼容,无需额外修改,可直接复用,这也是RN鸿蒙跨端开发中推荐使用TS的核心原因之一。

2.2 交互:

游戏库APP的UI设计遵循移动端设计规范,同时兼顾鸿蒙系统的交互特性,核心UI组件的实现均考虑了跨端适配,确保在鸿蒙设备上的显示和交互体验与iOS/Android一致。

首先是游戏卡片的实现,通过renderGameCard函数定义游戏卡片组件,复用FlatList的renderItem属性,实现游戏列表的批量渲染。游戏卡片中包含图标、标题、评分、描述、玩家人数、分类标签等元素,布局采用相对定位和flex布局结合的方式------例如,NEW标签采用绝对定位(top: -6, right: -6),确保在图标右上角显示,分类标签采用flex布局,实现与玩家人数的左右分布。这些布局逻辑在鸿蒙系统中与RN原生环境完全一致,View组件的样式(borderRadius、shadowColor、shadowOffset等)也会自动适配鸿蒙设备的UI渲染规范,确保游戏卡片的阴影、圆角显示正常,提升UI质感。

其次是特色游戏轮播和分类导航的实现,均采用ScrollView的horizontal属性实现横向滚动,通过showsHorizontalScrollIndicator={false}隐藏滚动条,提升UI美观度。特色游戏卡片的宽度设置为width * 0.6,确保在不同宽度的鸿蒙设备上,均能占据屏幕60%的宽度,实现轮播效果的一致性;分类导航的每个分类项采用flexDirection: 'row'实现图标与文字的横向排列,选中状态通过样式切换(selectedCategory === category.id && styles.selectedCategory)实现背景色和文字颜色的变化,这种交互逻辑完全基于RN的组件渲染机制,在鸿蒙系统中可无缝复用,点击反馈(TouchableOpacity的透明度变化)会自动适配鸿蒙设备的交互规范,无需额外修改。

再者是交互反馈的实现,通过Alert.alert函数实现点击游戏卡片、搜索按钮时的弹窗反馈,这种方式虽然简单,但在跨端开发中可确保多端兼容------在鸿蒙系统中,Alert组件会自动映射到鸿蒙的原生弹窗组件,弹窗的样式、交互逻辑与鸿蒙系统的原生弹窗保持一致,提升用户体验。例如,点击游戏卡片时,弹窗显示"游戏详情,正在启动XX游戏",点击搜索按钮时,弹窗显示"搜索,打开搜索功能",这些交互反馈在鸿蒙设备上正常显示,无需额外开发原生弹窗组件。

2.3 样式:

StyleSheet是RN跨端开发中用于定义组件样式的核心API,通过StyleSheet.create定义所有组件的样式,支持flex布局、相对单位、阴影、圆角等多种样式属性,鸿蒙系统对StyleSheet的支持度非常高,代码中定义的所有样式均可在鸿蒙设备上正常渲染,无需额外编写鸿蒙特有的样式代码。

需要重点关注的是鸿蒙设备的屏幕密度适配------鸿蒙设备的屏幕密度与传统iOS/Android设备可能存在差异,代码中通过Dimensions组件动态获取屏幕宽高,结合相对单位(如百分比、flex布局),避免使用固定像素值,确保样式的自适应。例如,底部导航的paddingVertical设置为12,采用相对像素值,适配不同屏幕密度的鸿蒙设备;游戏卡片的marginBottom设置为16,确保卡片之间的间距一致,避免出现间距过大或过小的问题。

此外,代码中使用的颜色值(如#f8fafc、#1e293b、#3b82f6等),在鸿蒙系统中正常显示,无需担心颜色失真的问题;字体大小(如fontSize: 16、fontSize: 14等)采用相对像素值,适配鸿蒙设备的字体缩放功能,确保在用户调整字体大小时,APP的文字显示正常,不出现排版错乱的问题。


虽然RN代码可大部分复用,但鸿蒙系统作为新兴系统,仍有部分细节需要针对性适配,这份游戏库APP代码在开发过程中已考虑到鸿蒙跨端的核心适配要点,主要集中在屏幕适配、列表渲染性能、图标适配、交互规范四个方面,也是开发者在实际RN鸿蒙跨端游戏类应用开发中需要重点关注的内容。

3.1 屏幕适配:

鸿蒙系统支持多种形态的设备(手机、平板、智慧屏等),屏幕尺寸和比例差异较大,因此自适应布局是鸿蒙跨端适配的核心。这份游戏库APP代码中,通过以下三种方式实现自适应布局,完全适配鸿蒙多设备场景:

一是通过Dimensions组件动态获取屏幕宽高,所有与屏幕尺寸相关的组件宽度、高度均通过动态计算得到,避免使用固定像素值。例如,游戏卡片的宽度((width - 48) / 2)、特色游戏卡片的宽度(width * 0.6),确保在不同宽度的鸿蒙设备上,组件布局均匀,不出现排版异常。

二是采用flex布局,通过flex: 1、flexDirection、justifyContent、alignItems等属性,实现组件的弹性布局。例如,APP的整体布局中,content组件的flex: 1,确保内容区域始终占据屏幕剩余空间,底部导航固定在屏幕底部;游戏卡片的gameInfo组件的flex: 1,确保游戏信息区域填充卡片剩余空间,避免因内容长度不一致导致的卡片高度异常。

三是避免使用绝对定位的固定坐标,所有绝对定位的组件均采用相对定位结合动态计算的方式,确保在不同屏幕尺寸的鸿蒙设备上,组件位置正确。例如,NEW标签的定位(top: -6, right: -6),基于游戏图标的位置,而非屏幕的固定坐标,确保在不同尺寸的游戏图标上,均能正确显示在右上角。

3.2 列表渲染性能:FlatList的鸿蒙适配优化

游戏类APP的核心是列表渲染,游戏列表的数据量可能较大,因此列表渲染性能是鸿蒙跨端适配的重点。这份代码中使用FlatList组件渲染游戏列表,相比ScrollView的列表渲染,FlatList支持组件复用,能够有效提升列表渲染性能,避免出现卡顿问题------这在鸿蒙设备上尤为重要,尤其是在低配鸿蒙设备上,组件复用能够减少内存占用,提升APP的流畅性。

此外,代码中设置了keyExtractor={item => item.id},为每个列表项设置唯一的key,确保FlatList能够正确识别列表项的变化,避免不必要的组件重渲染;通过numColumns={2}实现两列布局,结合columnWrapperStyle={styles.columnWrapper}实现两列的均匀分布,这些属性在鸿蒙系统中均能正常生效,确保列表渲染的一致性和流畅性。

3.3 图标适配:

图标适配是RN鸿蒙跨端开发中容易出现问题的环节,传统的图片图标(如png、jpg格式)可能存在路径错误、格式不兼容、加载失败等问题,尤其是在鸿蒙多设备场景中,不同设备的图片渲染机制可能存在差异。这份代码中定义了ICONS_BASE64图标库,采用Base64格式存储图标,有效解决了图标适配的问题。

Base64格式的图标无需额外请求服务器,加载速度更快,且兼容性更强,在鸿蒙系统中可正常渲染,避免了因图片路径、格式兼容问题导致的图标显示异常。同时,代码中游戏图标的实现采用文本图标(如♠️、🃏、帅等),这种方式无需加载图片,完全基于文本渲染,兼容性更强,在鸿蒙设备上的显示效果与iOS/Android设备完全一致,进一步提升了跨端适配的一致性。

3.4 交互:

鸿蒙系统有其自身的原生交互规范,虽然RN的交互组件可大部分复用,但仍有部分细节需要针对性适配,确保APP的交互体验与鸿蒙系统的原生交互保持一致。这份代码中主要做了以下两点适配:

一是模态框的适配,通过Alert组件实现弹窗反馈,在鸿蒙系统中,Alert组件会自动映射到鸿蒙的原生弹窗组件,弹窗的样式、按钮布局、交互逻辑与鸿蒙系统的原生弹窗保持一致,避免出现弹窗样式突兀、交互异常的问题;二是触摸反馈的适配,通过TouchableOpacity组件实现可点击交互,该组件的点击反馈(透明度变化)会自动适配鸿蒙设备的触摸反馈规范,点击时的透明度变化与鸿蒙原生组件保持一致,提升用户体验。


通过对这份游戏库APP代码的技术解读,我们可以总结出RN鸿蒙跨端游戏类应用开发的核心思路:以RN官方API为基础,遵循组件化、自适应布局原则,采用函数式组件+React Hooks的开发模式,减少原生依赖,重点关注屏幕适配、列表渲染性能、图标适配、交互规范等细节,即可实现RN代码在鸿蒙系统上的无缝复用,开发出兼容多端的游戏类应用。这份代码虽然简单,但涵盖了RN鸿蒙跨端游戏类应用开发的核心技术点,包括组件使用、状态管理、布局适配、交互逻辑、样式适配等,是一份非常适合入门的实践案例。

结合实际开发经验,给开发者以下几点RN鸿蒙跨端游戏类应用开发的实践建议:

  1. 优先使用RN官方API和组件,尤其是FlatList、ScrollView、SafeAreaView等核心组件,避免引入第三方原生模块,降低跨端适配成本------第三方原生模块往往存在鸿蒙适配不完善的问题,容易导致APP在鸿蒙设备上崩溃或运行异常。

  2. 布局采用"Dimensions动态计算+flex布局"的组合方式,避免使用固定像素值和固定坐标,适配鸿蒙多形态设备,确保APP在不同尺寸、不同屏幕密度的鸿蒙设备上均能正常显示,排版一致。

  3. 列表渲染优先使用FlatList组件,而非ScrollView,利用FlatList的组件复用特性,提升列表渲染性能,避免出现卡顿问题------游戏类APP的列表数据量通常较大,性能优化是提升用户体验的关键,也是鸿蒙跨端适配的重点。

  4. 图标优先使用Base64格式或文本图标,避免使用传统图片图标,减少图标适配问题,确保图标在鸿蒙设备上正常显示,加载更快;若必须使用图片图标,建议统一图片格式(如png),并做好路径适配。

  5. 关注鸿蒙系统的原生交互规范,针对性优化交互细节,例如弹窗、触摸反馈等,确保APP的交互体验与鸿蒙系统的原生交互保持一致,提升用户认可度。

随着鸿蒙系统的不断发展,RN对鸿蒙的适配也会越来越完善,未来,RN鸿蒙跨端开发将成为前端开发者的重要技能之一,尤其是在游戏类、工具类等移动应用开发中,具有广阔的应用前景。希望本文的解读能够帮助开发者快速掌握RN鸿蒙跨端游戏类应用开发的核心技巧,少走弯路,高效开发出兼容多端的优质游戏类应用。


CardGameAp 组件采用了现代 React 函数组件架构,结合 useState Hook 实现了状态管理。应用通过多个状态变量存储不同类型的数据:games 存储游戏列表,featuredGames 存储特色推荐游戏,categories 存储游戏分类,selectedCategory 存储当前选中的分类。

这种状态管理方式使得组件逻辑清晰,易于维护和扩展。特别是 gamesfeaturedGames 使用了相同的 Game 类型定义,确保了数据结构的一致性。selectedCategory 状态用于控制游戏列表的过滤,实现了分类筛选功能。

数据结构

应用使用了 TypeScript 的 Game 接口明确数据结构,包含游戏的各项属性如标题、描述、玩家数量、分类、图标、评分和是否为新游戏。这种类型定义在跨端开发中尤为重要,确保了在不同平台上的数据结构一致性,减少了类型错误的可能性。

数据初始化时,使用了 useState Hook 直接赋值,适合静态数据或初始数据的场景。这种方式简化了代码结构,避免了不必要的状态更新逻辑。

布局

应用采用了现代化的移动应用布局设计,主要包含头部、搜索栏、特色游戏轮播、分类导航和游戏列表等部分。布局设计上,使用了 SafeAreaView 确保在不同设备上的显示兼容性,使用 ScrollView 确保在内容较长时可以滚动查看。

视觉设计上,使用了简洁明了的风格,通过不同的样式区分不同的功能区域和状态。游戏卡片的设计美观大方,包含游戏图标、标题、描述、评分、玩家数量和分类等信息,提供了丰富的视觉信息。特色游戏轮播和分类导航的水平滚动设计,为用户提供了便捷的浏览方式。

交互

应用实现了丰富的交互功能,包括:

  1. 搜索功能 :点击头部的搜索图标,通过 Alert.alert 提供操作反馈。
  2. 游戏详情 :点击游戏卡片,通过 Alert.alert 提供游戏启动反馈。
  3. 分类筛选 :点击分类导航项,切换 selectedCategory 状态,实现游戏列表的过滤。
  4. 特色游戏 :点击特色游戏卡片,通过 Alert.alert 提供游戏启动反馈。

这些交互功能的实现遵循了 React 的最佳实践,通过状态更新驱动 UI 变化,确保了交互的一致性和可靠性。特别是分类筛选功能,通过 filteredGames 变量根据 selectedCategory 状态过滤游戏列表,为用户提供了直观的筛选体验。


该万能游戏库应用展示了一个功能完整、设计优雅的 React Native 应用实现,涵盖了状态管理、数据结构、布局设计、交互处理等多个方面的技术点。通过合理的组件架构和状态管理,以及对跨端兼容性的考虑,该应用不仅在 React Native 环境下运行良好,也为后续的鸿蒙系统适配奠定了基础。


真实演示案例代码:

js 复制代码
// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Dimensions, Alert, FlatList } from 'react-native';

// Base64 图标库
const ICONS_BASE64 = {
  solitaire: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  poker: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  mahjong: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  chess: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  dice: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  back: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  star: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  crown: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};

const { width, height } = Dimensions.get('window');

// 游戏类型
type Game = {
  id: string;
  title: string;
  description: string;
  players: string;
  category: string;
  icon: string;
  rating: number;
  isNew: boolean;
};

const CardGameApp = () => {
  const [games] = useState<Game[]>([
    { id: '1', title: '纸牌接龙', description: '经典的单人纸牌游戏,考验逻辑思维', players: '1人', category: '纸牌', icon: '♠️', rating: 4.8, isNew: true },
    { id: '2', title: '俄罗斯方块', description: '消除方块的经典游戏', players: '1-2人', category: '益智', icon: '🟦', rating: 4.7, isNew: false },
    { id: '3', title: '斗地主', description: '流行的三人纸牌游戏', players: '3人', category: '纸牌', icon: '🃏', rating: 4.9, isNew: true },
    { id: '4', title: '中国象棋', description: '传统策略棋类游戏', players: '2人', category: '棋类', icon: '帅', rating: 4.6, isNew: false },
    { id: '5', title: '五子棋', description: '简单而富有深度的策略游戏', players: '2人', category: '棋类', icon: '⚫', rating: 4.5, isNew: false },
    { id: '6', title: '扫雷', description: '考验逻辑推理的经典游戏', players: '1人', category: '益智', icon: '💣', rating: 4.4, isNew: false },
    { id: '7', title: '麻将', description: '中国传统麻将游戏', players: '4人', category: '牌类', icon: '🀄', rating: 4.7, isNew: true },
    { id: '8', title: '连连看', description: '匹配相同图案的游戏', players: '1-4人', category: '益智', icon: '🎯', rating: 4.3, isNew: false },
  ]);
  
  const [featuredGames] = useState<Game[]>([
    { id: '1', title: '纸牌接龙', description: '经典的单人纸牌游戏,考验逻辑思维', players: '1人', category: '纸牌', icon: '♠️', rating: 4.8, isNew: true },
    { id: '3', title: '斗地主', description: '流行的三人纸牌游戏', players: '3人', category: '纸牌', icon: '🃏', rating: 4.9, isNew: true },
    { id: '4', title: '中国象棋', description: '传统策略棋类游戏', players: '2人', category: '棋类', icon: '帅', rating: 4.6, isNew: false },
  ]);
  
  const [categories] = useState([
    { id: 'all', name: '全部', icon: '🎲' },
    { id: 'card', name: '纸牌', icon: '♠️' },
    { id: 'chess', name: '棋类', icon: '♔' },
    { id: 'puzzle', name: '益智', icon: '🧠' },
    { id: 'dice', name: '骰子', icon: '🎲' },
  ]);
  
  const [selectedCategory, setSelectedCategory] = useState<string>('all');

  const filteredGames = selectedCategory === 'all' 
    ? games 
    : games.filter(game => game.category === selectedCategory);

  const renderGameCard = ({ item }: { item: Game }) => (
    <TouchableOpacity 
      style={styles.gameCard}
      onPress={() => Alert.alert('游戏详情', `正在启动 ${item.title}`)}
    >
      <View style={styles.gameIconContainer}>
        <Text style={styles.gameIcon}>{item.icon}</Text>
        {item.isNew && <Text style={styles.newTag}>NEW</Text>}
      </View>
      <View style={styles.gameInfo}>
        <View style={styles.gameHeader}>
          <Text style={styles.gameTitle}>{item.title}</Text>
          <View style={styles.ratingContainer}>
            <Text style={styles.ratingText}>{item.rating}</Text>
            <Text style={styles.starIcon}>⭐</Text>
          </View>
        </View>
        <Text style={styles.gameDescription}>{item.description}</Text>
        <View style={styles.gameFooter}>
          <Text style={styles.playerCount}>{item.players}</Text>
          <Text style={styles.categoryTag}>{item.category}</Text>
        </View>
      </View>
    </TouchableOpacity>
  );

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>万能游戏库</Text>
        <TouchableOpacity onPress={() => Alert.alert('搜索', '打开搜索功能')}>
          <Text style={styles.headerIcon}>🔍</Text>
        </TouchableOpacity>
      </View>

      <ScrollView style={styles.content}>
        {/* 搜索栏 */}
        <View style={styles.searchContainer}>
          <Text style={styles.searchIcon}>🔍</Text>
          <Text style={styles.searchPlaceholder}>搜索游戏或关键词</Text>
        </View>

        {/* 特色游戏轮播 */}
        <Text style={styles.sectionTitle}>特色推荐</Text>
        <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.featuredContainer}>
          {featuredGames.map(game => (
            <TouchableOpacity 
              key={`featured-${game.id}`} 
              style={styles.featuredCard}
              onPress={() => Alert.alert('特色游戏', `正在启动 ${game.title}`)}
            >
              <View style={styles.featuredIcon}>
                <Text style={styles.featuredIconText}>{game.icon}</Text>
              </View>
              <Text style={styles.featuredTitle}>{game.title}</Text>
              <Text style={styles.featuredRating}>⭐ {game.rating}</Text>
            </TouchableOpacity>
          ))}
        </ScrollView>

        {/* 分类导航 */}
        <Text style={styles.sectionTitle}>游戏分类</Text>
        <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.categoryContainer}>
          {categories.map(category => (
            <TouchableOpacity
              key={category.id}
              style={[
                styles.categoryItem,
                selectedCategory === category.id && styles.selectedCategory
              ]}
              onPress={() => setSelectedCategory(category.id)}
            >
              <Text style={[
                styles.categoryIcon,
                selectedCategory === category.id && styles.selectedCategoryIcon
              ]}>
                {category.icon}
              </Text>
              <Text style={[
                styles.categoryText,
                selectedCategory === category.id && styles.selectedCategoryText
              ]}>
                {category.name}
              </Text>
            </TouchableOpacity>
          ))}
        </ScrollView>

        {/* 游戏列表标题 */}
        <View style={styles.listHeader}>
          <Text style={styles.listTitle}>游戏列表</Text>
          <Text style={styles.gameCount}>({filteredGames.length}款游戏)</Text>
        </View>

        {/* 游戏列表 */}
        <FlatList
          data={filteredGames}
          renderItem={renderGameCard}
          keyExtractor={item => item.id}
          showsVerticalScrollIndicator={false}
          numColumns={2}
          columnWrapperStyle={styles.columnWrapper}
        />

        {/* 活动横幅 */}
        <View style={styles.promoBanner}>
          <Text style={styles.promoTitle}>每日挑战活动</Text>
          <Text style={styles.promoDescription}>参与每日挑战,赢取游戏币和道具奖励</Text>
          <TouchableOpacity style={styles.promoButton}>
            <Text style={styles.promoButtonText}>立即参与</Text>
          </TouchableOpacity>
        </View>
      </ScrollView>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🎮</Text>
          <Text style={styles.navText}>游戏</Text>
        </TouchableOpacity>
        
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🏆</Text>
          <Text style={styles.navText}>排行</Text>
        </TouchableOpacity>
        
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🎁</Text>
          <Text style={styles.navText}>商城</Text>
        </TouchableOpacity>
        
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>👤</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 20,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  headerIcon: {
    fontSize: 20,
    color: '#64748b',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  searchContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#ffffff',
    borderRadius: 20,
    paddingVertical: 12,
    paddingHorizontal: 16,
    marginBottom: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  searchIcon: {
    fontSize: 18,
    color: '#94a3b8',
    marginRight: 12,
  },
  searchPlaceholder: {
    fontSize: 14,
    color: '#94a3b8',
    flex: 1,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
    marginVertical: 12,
  },
  featuredContainer: {
    marginBottom: 16,
  },
  featuredCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginRight: 12,
    width: width * 0.6,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  featuredIcon: {
    width: 50,
    height: 50,
    borderRadius: 25,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 12,
  },
  featuredIconText: {
    fontSize: 24,
  },
  featuredTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  featuredRating: {
    fontSize: 14,
    color: '#64748b',
    flexDirection: 'row',
    alignItems: 'center',
  },
  categoryContainer: {
    marginBottom: 20,
  },
  categoryItem: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#f1f5f9',
    borderRadius: 20,
    paddingVertical: 10,
    paddingHorizontal: 16,
    marginRight: 12,
  },
  selectedCategory: {
    backgroundColor: '#3b82f6',
  },
  categoryIcon: {
    fontSize: 18,
    marginRight: 6,
    color: '#64748b',
  },
  selectedCategoryIcon: {
    color: '#ffffff',
  },
  categoryText: {
    fontSize: 14,
    color: '#64748b',
  },
  selectedCategoryText: {
    color: '#ffffff',
  },
  listHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 12,
  },
  listTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  gameCount: {
    fontSize: 14,
    color: '#64748b',
  },
  columnWrapper: {
    justifyContent: 'space-between',
  },
  gameCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
    width: (width - 48) / 2,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  gameIconContainer: {
    position: 'relative',
    marginBottom: 12,
  },
  gameIcon: {
    fontSize: 40,
    textAlign: 'center',
  },
  newTag: {
    position: 'absolute',
    top: -6,
    right: -6,
    backgroundColor: '#ef4444',
    color: '#ffffff',
    fontSize: 10,
    fontWeight: 'bold',
    paddingHorizontal: 6,
    paddingVertical: 2,
    borderRadius: 10,
  },
  gameInfo: {
    flex: 1,
  },
  gameHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
  },
  gameTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
    flex: 1,
  },
  ratingContainer: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  ratingText: {
    fontSize: 12,
    color: '#64748b',
    marginRight: 2,
  },
  starIcon: {
    fontSize: 14,
  },
  gameDescription: {
    fontSize: 12,
    color: '#64748b',
    lineHeight: 16,
    marginBottom: 12,
  },
  gameFooter: {
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  playerCount: {
    fontSize: 12,
    color: '#94a3b8',
  },
  categoryTag: {
    fontSize: 12,
    color: '#ffffff',
    backgroundColor: '#3b82f6',
    paddingHorizontal: 6,
    paddingVertical: 2,
    borderRadius: 6,
  },
  promoBanner: {
    backgroundColor: '#dbeafe',
    borderRadius: 12,
    padding: 16,
    marginTop: 16,
    marginBottom: 20,
  },
  promoTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  promoDescription: {
    fontSize: 14,
    color: '#64748b',
    marginBottom: 12,
  },
  promoButton: {
    backgroundColor: '#3b82f6',
    paddingVertical: 10,
    borderRadius: 6,
    alignItems: 'center',
  },
  promoButtonText: {
    color: '#ffffff',
    fontWeight: 'bold',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
  },
  navItem: {
    alignItems: 'center',
    flex: 1,
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
});

export default CardGameApp;

打包

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

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

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

本文以React Native游戏库APP开发为例,探讨RN在鸿蒙系统的跨端适配实践。文章从跨端架构、组件化设计和鸿蒙适配三个维度展开分析:

  • 1)架构层面采用RN官方API实现代码复用,重点解析SafeAreaView、Dimensions等核心组件的鸿蒙兼容性;
  • 2)组件化开发中运用函数式组件和Hooks进行状态管理,确保多端逻辑一致性;
  • 3)针对鸿蒙系统特性,提出屏幕适配、列表优化等关键适配方案。案例展示了RN在鸿蒙游戏类应用开发中的完整技术路径,为开发者提供可复用的跨端实践方案。

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

相关推荐
2501_9400417413 小时前
探索非主流游戏机制的AI生成指南
人工智能·游戏
来恩100314 小时前
jQuery选择器
前端·javascript·jquery
前端繁华如梦14 小时前
树上挂苹果还是挂玻璃球?Three.js 程序化果实的完整实现指南
前端·javascript
CDwenhuohuo14 小时前
优惠券组件直接用 uview plus
前端·javascript·vue.js
川冰ICE15 小时前
TypeScript装饰器与元编程实战
前端·javascript·typescript
AI砖家15 小时前
Vue3组件传参大全,各种传参方式的对比
前端·javascript·vue.js
希望永不加班15 小时前
var局部变量类型推断的利弊
java·服务器·前端·javascript·html
threelab15 小时前
Three.js 3D 地图可视化 | 三维可视化 / AI 提示词
前端·javascript·人工智能·3d·着色器
樱桃花下的小猫16 小时前
游戏云服务器定时任务设置教程
服务器·游戏·新手友好·云鸢互联·零门槛一键开服
失眠的咕噜16 小时前
PDA 安卓设备上传多张图片
android·前端·javascript