这个狗狗照片上传页面采用了清晰的组件化架构,通过状态管理实现了完整的图片上传和管理功能。核心组件 ImageUploadPage 作为主容器,负责状态管理和界面渲染,提供了拍照上传、相册选择、照片管理等功能。

状态管理

const [uploadedImages, setUploadedImages] = useState<string[]>([
  'https://picsum.photos/300/300?random=1',
  'https://picsum.photos/300/300?random=2',
  'https://picsum.photos/300/300?random=3',
]);
const [isUploading, setIsUploading] = useState(false);

使用 useState Hook 管理两个状态:

  1. uploadedImages:已上传的图片 URL 数组,初始值为 3 张示例图片
  2. isUploading:上传状态,用于控制上传按钮的可用性和显示上传进度

这种状态管理方式简洁明了,适合处理图片上传和管理的场景。

图片上传

const handleCameraUpload = () => {
  Alert.alert(
    '拍照上传',
    '即将打开相机拍摄狗狗照片',
    [
      { text: '取消', style: 'cancel' },
      { 
        text: '确定', 
        onPress: () => {
          setIsUploading(true);
          setTimeout(() => {
            const newImage = `https://picsum.photos/300/300?random=${Math.floor(Math.random() * 100)}`;
            setUploadedImages([newImage, ...uploadedImages]);
            setIsUploading(false);
            Alert.alert('上传成功', '狗狗照片已成功上传!');
          }, 1500);
        }
      }
    ]
  );
};

图片上传功能通过 Alert.alert 显示确认对话框,用户确认后模拟上传过程,更新 uploadedImages 状态并显示上传成功的提示。这种实现方式提供了清晰的用户反馈,确保用户了解上传的进度和结果。

图片管理功能

const handleImagePress = (uri: string) => {
  Alert.alert(
    '操作选项',
    '选择对这张照片的操作',
    [
      { text: '取消', style: 'cancel' },
      { 
        text: '查看详情', 
        onPress: () => Alert.alert('查看', '正在查看这张狗狗照片')
      },
      { 
        text: '删除照片', 
        style: 'destructive',
        onPress: () => {
          setUploadedImages(uploadedImages.filter(img => img !== uri));
          Alert.alert('删除成功', '狗狗照片已删除');
        }
      }
    ]
  );
};

图片管理功能通过 Alert.alert 显示操作选项对话框,用户可以选择查看详情或删除照片。删除照片时,通过 filter 方法从 uploadedImages 状态中过滤掉指定的图片 URL,并显示删除成功的提示。

上传进度

{isUploading && (
  <View style={styles.uploadProgress}>
    <Text style={styles.progressText}>正在上传...</Text>
    <View style={styles.progressBar}>
      <View style={styles.progressFill} />
    </View>
  </View>
)}

上传进度通过条件渲染实现,当 isUploadingtrue 时,显示上传进度指示器,包括"正在上传…"文本和进度条。这种实现方式提供了直观的上传进度反馈,增强了用户体验。


页面布局

<SafeAreaView style={styles.container}>
  {/* 头部 */}
  <View style={styles.header}>
    <Text style={styles.title}>狗狗照片上传</Text>
    <Text style={styles.subtitle}>分享您爱犬的美好瞬间</Text>
  </View>

  {/* 上传选项卡 */}
  <View style={styles.uploadOptions}>
    {/* 上传按钮 */}
  </View>

  {/* 上传进度指示器 */}
  {/* 上传进度内容 */}

  {/* 上传统计 */}
  <View style={styles.statsContainer}>
    {/* 统计信息 */}
  </View>

  {/* 已上传的照片列表 */}
  <ScrollView style={styles.content}>
    {/* 照片网格 */}
  </ScrollView>

  {/* 底部导航 */}
  <View style={styles.bottomNav}>
    {/* 导航按钮 */}
  </View>
</SafeAreaView>

页面布局采用了分层设计:

  • 头部:包含标题和副标题
  • 上传选项卡:包含拍照上传和从相册选择按钮
  • 上传进度指示器:显示上传状态
  • 上传统计:显示已上传照片数、本月活跃和点赞数
  • 照片列表:以网格形式展示已上传的照片
  • 底部导航栏:提供导航功能

这种布局设计清晰明了,用户可以直观地理解和使用页面的功能。

照片布局

<View style={styles.gridContainer}>
  {uploadedImages.map((uri, index) => (
    <TouchableOpacity 
      key={`${uri}-${index}`} 
      style={styles.imageCard}
      onPress={() => handleImagePress(uri)}
    >
      <Image source={{ uri }} style={styles.uploadedImage} />
      <View style={styles.imageOverlay}>
        <Text style={styles.overlayIcon}>{ICONS.heart}</Text>
        <Text style={styles.overlayCount}>12</Text>
      </View>
    </TouchableOpacity>
  ))}
</View>

照片网格使用 map 方法遍历 uploadedImages 数组,为每张照片渲染一个 TouchableOpacity 组件。照片卡片包含图片本身和一个覆盖层,显示心形图标和点赞数。这种布局方式在照片展示类应用中非常常见,能够清晰地展示照片并提供基本的交互功能。

这个狗狗照片上传页面展示了 React Native 跨端开发的核心技术要点,通过合理的组件设计、清晰的状态管理、直观的用户界面和完整的功能实现,为用户提供了一个功能齐全、体验良好的照片上传和管理工具。在鸿蒙系统适配方面,通过组件映射、样式适配和功能重实现,可以快速实现跨端迁移,保持功能和视觉效果的一致性。


全程采用React Native原生组件与React核心特性开发,无任何第三方依赖或平台专属代码,遵循鸿蒙跨端友好组件化思维状态驱动视图原生交互体验的设计原则,借助React Native for HarmonyOS桥接层可无缝编译为鸿蒙原生组件,Android、iOS、鸿蒙三端共用一套核心逻辑,实现原生级的媒体操作与视觉体验。本文将从鸿蒙跨端友好的技术基底状态驱动的媒体上传体系跨端兼容的布局与视觉设计精细化的交互反馈与操作体系鸿蒙跨端落地与生产级拓展等维度,深度解读该实现的技术细节,为各类跨端媒体上传、相册管理、图片分享类页面开发提供可直接复用的工程化方案。

本项目的技术选型围绕照片上传页面的产品特性鸿蒙跨端兼容性两大核心原则,全程使用React Native原生核心组件与API完成开发,未引入任何第三方媒体操作库或平台专属特性,所有实现均遵循“跨端通用、原生渲染、轻量高效”的设计思路,为鸿蒙跨端落地奠定极简工程基础,同时贴合照片上传页面“操作清晰、状态反馈及时、布局规整、交互原生”的产品诉求,核心技术基底设计如下:

1. 原生组件:

选用SafeAreaViewViewTextTouchableOpacityScrollViewImageAlertPlatform等React Native核心原生组件/API,这类能力均完成React Native for HarmonyOS的深度桥接,底层会被编译为对应平台的原生组件(鸿蒙Component、Android View、iOS UIView),基于原生渲染引擎执行,彻底规避WebView渲染的性能损耗,同时完美支撑媒体上传场景的核心诉求:

  • Image组件:远程URI图片加载、固定宽高渲染、圆角裁剪在鸿蒙平台原生支持,狗狗照片无拉伸、无加载异常,且桥接鸿蒙的图片缓存策略,重复展示的照片无需重新加载,同时overflow: hidden属性可实现照片的圆角裁剪,与鸿蒙原生图片展示效果一致;
  • TouchableOpacity:触摸反馈桥接为鸿蒙原生的按压效果(淡入淡出),拍照/相册上传按钮、照片卡片的点击体验与鸿蒙原生应用完全一致,无交互延迟,贴合媒体操作的即时性诉求;
  • Alert:弹窗提示桥接为鸿蒙AlertDialog原生弹窗,拍照/相册确认、照片操作选项、上传/删除结果提示的弹窗层级、动画均为鸿蒙原生效果,支持多按钮弹窗按钮样式定制(如destructive红色危险样式、cancel取消样式),满足上传流程的交互确认诉求;
  • ScrollView:惯性滚动、滚动条样式在鸿蒙平台自动适配,当上传照片数量过多时,照片网格的滚动体验流畅无卡顿,且支持鸿蒙折叠屏、平板的大屏滚动适配,自动适配不同屏幕的可视区域;
  • SafeAreaView:自动桥接鸿蒙的安全区域适配能力,兼容鸿蒙设备的刘海屏、底部导航栏,保证上传按钮、照片网格等核心操作区域不被系统控件遮挡;
  • Platform:虽本项目暂未做平台差异化处理,但预留了平台判断入口,后续可基于该API实现鸿蒙/Android/iOS的轻微样式/逻辑差异化,且PlatformAPI在鸿蒙平台可正常获取设备信息,无兼容成本;
  • 所有组件的使用方式均为React Native标准用法,无任何鸿蒙平台专属配置,前端开发者基于现有React Native技术积累即可开发,跨端学习成本为零。

2. 核心能力:纯React/JS通用能力,鸿蒙无兼容成本

依托React Native原生能力实现所有照片上传业务功能,核心能力均为JavaScript/React通用特性,在鸿蒙平台的JS引擎中可直接执行,无需任何适配修改,完美支撑照片上传“状态实时更新、数据动态维护、流程逻辑可控”的核心诉求:

  • 状态管理:采用useState轻量管理已上传照片列表上传中状态两大核心状态,遵循React状态不可变原则,状态更新驱动视图的局部重渲染,与鸿蒙ArkUI的@State状态管理理念高度同源;
  • 数据操作:采用JavaScript数组的mapfilter扩展运算符等通用方法实现照片列表的渲染、删除,保证状态更新的不可变性,所有数组操作在鸿蒙平台的JS引擎中可直接执行,计算效率无损耗;
  • 异步模拟:通过setTimeout模拟照片上传的异步请求过程,贴合生产环境中“调用原生相机/相册API→上传后端服务器”的异步流程,setTimeout为JS通用API,在鸿蒙平台无任何兼容成本;
  • 样式渲染:基于StyleSheet.create()实现模块化样式管理,支持Flex弹性布局、圆角、阴影、定位、透明度、背景色渐变(rgba)等所有通用样式属性,在鸿蒙平台桥接为ArkUI的原生样式,保证三端视觉一致性。

3. 数据层:

采用两个核心状态实现照片上传全流程的数据管理,无复杂数据层设计,状态职责边界清晰,与媒体操作流程完全解耦,为后续对接真实原生媒体API、后端上传接口预留了极简的拓展入口:

  • uploadedImages:数组类型,存储已上传照片的远程URI,初始值为3张模拟照片,作为照片网格的核心渲染数据,支持新增(上传成功后头部插入)、删除(过滤指定URI)等操作,符合媒体相册的基础数据管理诉求;
  • isUploading:布尔类型,标记当前是否处于上传中状态,用于上传按钮禁用上传进度指示器展示,实现上传流程的状态互斥,避免用户重复触发上传操作。

这种轻量状态设计让数据层与业务逻辑层、视图层完全解耦,在生产环境中,仅需将setTimeout模拟的异步流程替换为「鸿蒙原生相机/相册API调用」+「后端上传接口请求」,即可快速对接真实的媒体上传系统,无需修改任何视图渲染与交互逻辑,工程拓展性极强。


照片上传页面的核心产品诉求是上传流程的可控性状态反馈的即时性,本项目采用React的useState实现已上传照片列表上传中状态两大核心状态的轻量管理,遵循状态不可变原则,通过状态更新驱动视图的实时重渲染,同时设计了拍照/相册双渠道上传上传状态互斥照片增删管理操作结果反馈等核心逻辑,所有状态管理与流程控制均为React/JavaScript通用能力,在鸿蒙平台无任何兼容成本,打造了“用户操作→状态更新→视图反馈→操作结果提示”全链路可控的媒体上传体系,核心设计要点如下:

1. 核心状态:

定义两个核心useState钩子,分别管理已上传照片列表与上传中状态,实现状态的精细化管理,职责边界清晰,避免单一状态过于臃肿,同时保证状态更新的精准性与上传流程的互斥性,核心状态设计:

// 已上传照片URI列表,初始值为3张模拟照片
const [uploadedImages, setUploadedImages] = useState<string[]>([
  'https://picsum.photos/300/300?random=1',
  'https://picsum.photos/300/300?random=2',
  'https://picsum.photos/300/300?random=3',
]);
// 上传中状态,标记是否正在执行上传操作,初始值为false
const [isUploading, setIsUploading] = useState(false);

双状态分离的设计方式让状态的更新与维护更精准,同时实现了上传流程的状态互斥

  • isUploadingtrue时,自动禁用拍照/相册上传按钮,避免用户在上传过程中重复触发操作,导致照片重复上传或状态混乱;
  • uploadedImages状态变化时,仅触发照片网格、已上传数量统计的重渲染,不影响其他模块;
  • isUploading状态变化时,仅触发上传按钮禁用状态、上传进度指示器的展示/隐藏,遵循React的最小重渲染原则,提升页面性能。

这种状态设计在鸿蒙平台无任何兼容问题,setUploadedImagessetIsUploading的状态更新逻辑会被桥接为ArkUI的状态更新,触发视图的高效重渲染,与鸿蒙原生应用的状态更新机制一致。

2. 图片上传:

实现拍照上传从相册选择双渠道的上传逻辑,两个渠道遵循统一的业务流程:「弹窗确认→标记上传中→模拟异步上传→更新照片列表→取消上传中→上传成功提示」,核心逻辑高度复用,仅弹窗提示文案略有差异,严格遵循React状态不可变原则,不直接修改原状态值,仅通过setState方法实现状态的浅拷贝更新,保证状态的可追踪性与稳定性,核心流程拆解:

(1)弹窗确认:

通过Alert实现带确认/取消按钮的原生弹窗,拍照上传弹窗提示“即将打开相机拍摄狗狗照片”,相册上传弹窗提示“请选择一张狗狗照片”,用户点击“确定”后才执行后续上传流程,点击“取消”则终止操作,符合媒体操作的用户体验规范。其中弹窗的style属性支持cancel(取消样式)与默认样式,在鸿蒙平台桥接为原生弹窗的按钮样式,视觉与交互均为原生效果。

(2)状态标记:

用户确认上传后,立即将isUploading设置为true,触发两个核心视图变化:

  • 拍照/相册上传按钮的disabled属性生效,按钮变为不可点击状态,避免重复上传;
  • 上传进度指示器从隐藏变为展示,告知用户当前正在执行上传操作,提供即时的状态反馈。
(3)异步模拟:

通过setTimeout模拟1.5秒的异步上传过程,贴合生产环境中「调用原生相机/相册API获取照片本地路径→调用后端上传接口将照片上传至服务器→获取服务器返回的照片远程URI」的异步流程,核心模拟代码:

const newImage = `https://picsum.photos/300/300?random=${Math.floor(Math.random() * 100)}`;

生成随机的照片远程URI,模拟后端返回的上传结果,后续生产环境仅需替换该部分代码为真实的原生媒体API与后端接口请求,即可快速对接真实业务,无需修改其他流程逻辑。

(4)状态更新:

上传模拟完成后,通过数组扩展运算符创建新的照片列表,将新上传的照片URI插入到列表头部([newImage, ...uploadedImages]),并通过setUploadedImages更新状态,核心代码:

setUploadedImages([newImage, ...uploadedImages]);

采用浅拷贝的方式更新数组,严格遵循React状态不可变原则,避免直接修改原数组导致的状态混乱,该操作在鸿蒙平台的JS引擎中可直接执行,无任何兼容成本。

本次解析的狗狗照片上传页实战项目,是一套基于React Native组件化与状态驱动思想开发的跨端媒体上传类页面工程化实现,核心依托React原生的useState双状态管理,实现了拍照/相册双渠道上传、上传状态全流程反馈、照片增删管理、照片网格展示等核心功能,同时打造了“头部标题-双渠道上传入口-上传进度-数据统计-照片网格-底部导航”的标准化媒体上传页面架构。项目全程基于React Native跨平台原生API开发,遵循鸿蒙跨端友好的开发原则,所有实现均无平台专属特性,依托React Native for HarmonyOS可实现鸿蒙跨端的无缝落地,零业务代码修改。

该项目的技术价值不仅在于完成了狗狗照片上传页的核心开发,更在于为跨端媒体上传、相册管理、图片分享、文件上传等常见页面提供了可复用的工程化开发范式:

  1. 采用**useState双状态分离管理**,实现媒体数据与操作状态的精细化管理,状态更新驱动视图实时重渲染,与鸿蒙ArkUI的状态管理理念高度同源,保证了跨端状态逻辑的一致性;
  2. 基于React Native原生组件与API,构建了全流程的媒体上传与照片管理逻辑,无任何第三方依赖,项目轻量高效,且所有能力均完成鸿蒙桥接,跨端落地成本为零;
  3. 依托Flex弹性布局+自适应网格,实现了所有模块的跨端自适应布局,结合标准化的色彩体系、文字层级、卡片式设计,打造了清新友好、跨端视觉高度统一的页面风格;
  4. 设计了精细化的交互反馈与标准化的操作体系,从上传流程的全链路状态反馈到照片操作的精细化处理,所有交互均贴合移动端用户习惯,且在鸿蒙平台桥接为原生交互效果,提升了跨端用户体验;
  5. 预留丰富的生产级拓展入口,可快速接入真实的原生媒体API、后端文件上传接口,同时支持照片大图预览、批量操作、鸿蒙原子化服务、分布式相册同步等专属能力的适配,工程拓展性强。

真实演示案例代码:



// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Dimensions, Alert, Platform } from 'react-native';

// 图标库
const ICONS = {
  home: '🏠',
  upload: '⬆️',
  camera: '📷',
  gallery: '🖼️',
  dog: '🐕',
  heart: '❤️',
  share: '🔗',
  user: '👤',
};

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

const ImageUploadPage: React.FC = () => {
  const [uploadedImages, setUploadedImages] = useState<string[]>([
    'https://picsum.photos/300/300?random=1',
    'https://picsum.photos/300/300?random=2',
    'https://picsum.photos/300/300?random=3',
  ]);
  const [isUploading, setIsUploading] = useState(false);

  const handleImageUpload = () => {
    setIsUploading(true);
    // 模拟上传过程
    setTimeout(() => {
      const newImage = `https://picsum.photos/300/300?random=${Math.floor(Math.random() * 100)}`;
      setUploadedImages([newImage, ...uploadedImages]);
      setIsUploading(false);
      Alert.alert('上传成功', '狗狗照片已成功上传!');
    }, 1500);
  };

  const handleCameraUpload = () => {
    Alert.alert(
      '拍照上传',
      '即将打开相机拍摄狗狗照片',
      [
        { text: '取消', style: 'cancel' },
        { 
          text: '确定', 
          onPress: () => {
            setIsUploading(true);
            setTimeout(() => {
              const newImage = `https://picsum.photos/300/300?random=${Math.floor(Math.random() * 100)}`;
              setUploadedImages([newImage, ...uploadedImages]);
              setIsUploading(false);
              Alert.alert('上传成功', '狗狗照片已成功上传!');
            }, 1500);
          }
        }
      ]
    );
  };

  const handleGalleryUpload = () => {
    Alert.alert(
      '从相册选择',
      '请选择一张狗狗照片',
      [
        { text: '取消', style: 'cancel' },
        { 
          text: '确定', 
          onPress: () => {
            setIsUploading(true);
            setTimeout(() => {
              const newImage = `https://picsum.photos/300/300?random=${Math.floor(Math.random() * 100)}`;
              setUploadedImages([newImage, ...uploadedImages]);
              setIsUploading(false);
              Alert.alert('上传成功', '狗狗照片已成功上传!');
            }, 1500);
          }
        }
      ]
    );
  };

  const handleImagePress = (uri: string) => {
    Alert.alert(
      '操作选项',
      '选择对这张照片的操作',
      [
        { text: '取消', style: 'cancel' },
        { 
          text: '查看详情', 
          onPress: () => Alert.alert('查看', '正在查看这张狗狗照片')
        },
        { 
          text: '删除照片', 
          style: 'destructive',
          onPress: () => {
            setUploadedImages(uploadedImages.filter(img => img !== uri));
            Alert.alert('删除成功', '狗狗照片已删除');
          }
        }
      ]
    );
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>狗狗照片上传</Text>
        <Text style={styles.subtitle}>分享您爱犬的美好瞬间</Text>
      </View>

      {/* 上传选项卡 */}
      <View style={styles.uploadOptions}>
        <TouchableOpacity 
          style={styles.uploadButton} 
          onPress={handleCameraUpload}
          disabled={isUploading}
        >
          <Text style={styles.uploadIcon}>{ICONS.camera}</Text>
          <Text style={styles.uploadText}>拍照上传</Text>
        </TouchableOpacity>
        
        <TouchableOpacity 
          style={styles.uploadButton} 
          onPress={handleGalleryUpload}
          disabled={isUploading}
        >
          <Text style={styles.uploadIcon}>{ICONS.gallery}</Text>
          <Text style={styles.uploadText}>从相册选择</Text>
        </TouchableOpacity>
      </View>

      {/* 上传进度指示器 */}
      {isUploading && (
        <View style={styles.uploadProgress}>
          <Text style={styles.progressText}>正在上传...</Text>
          <View style={styles.progressBar}>
            <View style={styles.progressFill} />
          </View>
        </View>
      )}

      {/* 上传统计 */}
      <View style={styles.statsContainer}>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>{uploadedImages.length}</Text>
          <Text style={styles.statLabel}>已上传</Text>
        </View>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>12</Text>
          <Text style={styles.statLabel}>本月活跃</Text>
        </View>
        <View style={styles.statItem}>
          <Text style={styles.statNumber}>24</Text>
          <Text style={styles.statLabel}>点赞数</Text>
        </View>
      </View>

      {/* 已上传的照片列表 */}
      <ScrollView style={styles.content}>
        <Text style={styles.sectionTitle}>我的狗狗相册</Text>
        <Text style={styles.sectionSubtitle}>{uploadedImages.length} 张照片</Text>
        
        <View style={styles.gridContainer}>
          {uploadedImages.map((uri, index) => (
            <TouchableOpacity 
              key={`${uri}-${index}`} 
              style={styles.imageCard}
              onPress={() => handleImagePress(uri)}
            >
              <Image source={{ uri }} style={styles.uploadedImage} />
              <View style={styles.imageOverlay}>
                <Text style={styles.overlayIcon}>{ICONS.heart}</Text>
                <Text style={styles.overlayCount}>12</Text>
              </View>
            </TouchableOpacity>
          ))}
        </View>
      </ScrollView>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={styles.navItem}>
          <Text style={[styles.navIcon, styles.activeNavIcon]}>{ICONS.home}</Text>
          <Text style={[styles.navText, styles.activeNavText]}>首页</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.upload}</Text>
          <Text style={styles.navText}>上传</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.dog}</Text>
          <Text style={styles.navText}>狗狗</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.user}</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  header: {
    padding: 20,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  subtitle: {
    fontSize: 14,
    color: '#64748b',
  },
  uploadOptions: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 20,
    backgroundColor: '#ffffff',
    margin: 16,
    borderRadius: 12,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  uploadButton: {
    alignItems: 'center',
    padding: 16,
    backgroundColor: '#f1f5f9',
    borderRadius: 12,
    flex: 1,
    marginHorizontal: 8,
  },
  uploadIcon: {
    fontSize: 24,
    marginBottom: 8,
  },
  uploadText: {
    fontSize: 14,
    color: '#1e293b',
    fontWeight: '500',
  },
  uploadProgress: {
    margin: 16,
    padding: 16,
    backgroundColor: '#ffffff',
    borderRadius: 12,
    alignItems: 'center',
  },
  progressText: {
    fontSize: 16,
    color: '#64748b',
    marginBottom: 8,
  },
  progressBar: {
    width: '100%',
    height: 8,
    backgroundColor: '#e2e8f0',
    borderRadius: 4,
    overflow: 'hidden',
  },
  progressFill: {
    width: '60%',
    height: '100%',
    backgroundColor: '#3b82f6',
  },
  statsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    padding: 16,
    backgroundColor: '#ffffff',
    margin: 16,
    borderRadius: 12,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  statItem: {
    alignItems: 'center',
  },
  statNumber: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#3b82f6',
  },
  statLabel: {
    fontSize: 12,
    color: '#64748b',
    marginTop: 4,
  },
  content: {
    flex: 1,
    padding: 16,
  },
  sectionTitle: {
    fontSize: 22,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  sectionSubtitle: {
    fontSize: 14,
    color: '#64748b',
    marginBottom: 16,
  },
  gridContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'space-between',
  },
  imageCard: {
    width: (width - 48) / 2,
    marginBottom: 16,
    borderRadius: 12,
    overflow: 'hidden',
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    position: 'relative',
  },
  uploadedImage: {
    width: '100%',
    height: 150,
  },
  imageOverlay: {
    position: 'absolute',
    top: 8,
    right: 8,
    backgroundColor: 'rgba(0, 0, 0, 0.6)',
    borderRadius: 12,
    padding: 6,
    flexDirection: 'row',
    alignItems: 'center',
  },
  overlayIcon: {
    fontSize: 12,
    color: '#ffffff',
    marginRight: 4,
  },
  overlayCount: {
    fontSize: 12,
    color: '#ffffff',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
  },
  navItem: {
    alignItems: 'center',
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  activeNavIcon: {
    color: '#3b82f6',
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
  activeNavText: {
    color: '#3b82f6',
  },
});

export default ImageUploadPage;

请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
本文介绍了一个采用React Native开发的狗狗照片上传页面,具备完整的图片上传和管理功能。页面采用组件化架构,通过状态管理实现图片上传、删除和查看操作。核心功能包括拍照上传、相册选择、照片管理(查看/删除)和上传进度显示。技术实现上完全使用React Native原生组件,无第三方依赖,确保跨平台兼容性,特别针对鸿蒙系统进行了适配优化。页面布局清晰,包含头部标题、上传选项、统计信息、照片网格和底部导航。该方案可作为跨平台图片上传类应用的通用实现模板,提供原生级的用户体验和性能表现。

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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐