ReactNative项目OpenHarmony三方库集成实战:react-native-shadow-2

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

项目基于 RN 0.72.90 开发

📋 前言

,阴影效果是提升UI层次感和视觉体验的重要手段。react-native-shadow-2 是一个功能强大的阴影效果库,提供了跨平台一致的阴影渲染能力,支持渐变色阴影、自定义形状、多方向阴影等高级特性,是实现精美UI的理想选择。

🎯 库简介

基本信息

为什么需要阴影库?

特性 原生方案 react-native-shadow-2
跨平台一致性 ⚠️ 差异大 ✅ 统一效果
渐变阴影 ❌ 不支持 ✅ 完美支持
自定义形状 ⚠️ 复杂 ✅ 简单配置
性能优化 ⚠️ 需手动优化 ✅ 自动优化
圆角阴影 ⚠️ 需额外处理 ✅ 原生支持
HarmonyOS 支持 ⚠️ 需适配 ✅ 完善适配

核心功能

功能 说明 HarmonyOS 支持
startColor 阴影起始颜色
endColor 阴影结束颜色
distance 阴影延伸距离
offset 阴影偏移
paintInside 内部绘制
sides 边控制
corners 角控制
style 子组件容器样式
stretch 水平拉伸
disabled 禁用阴影

兼容性验证

在以下环境验证通过:

  • RNOH : 0.72.90; SDK : HarmonyOS 6.0.0; IDE : DevEco Studio 6.0.2; ROM: 6.0.0

📦 安装步骤

1. 安装依赖

bash 复制代码
# RN 0.72 版本
npm install react-native-shadow-2@7.0.8

# RN 0.77 版本
npm install react-native-shadow-2@7.1.1

# 或者使用 yarn
yarn add react-native-shadow-2

2. 验证安装

安装完成后,检查 package.json 文件:

json 复制代码
{
  "dependencies": {
    "react-native-shadow-2": "^7.0.8"
  }
}

🔧 HarmonyOS 平台配置 ⭐

依赖说明

本库 HarmonyOS 侧实现依赖 react-native-svg 的原生端代码,如已在 HarmonyOS 工程中引入过该库,则无需再次引入。

如未引入,请参照 https://blog.csdn.net/2402_83107102/article/details/159203447

1. 安装 react-native-svg

bash 复制代码
npm install @react-native-ohos/react-native-svg

2. 引入原生端代码

打开 harmony/entry/oh-package.json5,添加以下依赖:

json5 复制代码
"dependencies": {
  "@react-native-ohos/react-native-svg": "file:../../node_modules/@react-native-ohos/react-native-svg/harmony/svg.har"
}

点击右上角的 sync 按钮,或者在终端执行:

bash 复制代码
cd entry
ohpm install

3. 配置 CMakeLists

打开 entry/src/main/cpp/CMakeLists.txt,添加:

cmake 复制代码
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")

# RNOH_BEGIN: manual_package_linking_1
add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-svg/src/main/cpp" ./svg)
# RNOH_END: manual_package_linking_1

# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_svg)
# RNOH_END: manual_package_linking_2

4. 引入 SvgPackage

打开 entry/src/main/cpp/PackageProvider.cpp,添加:

cpp 复制代码
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "SvgPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
      std::make_shared<RNOHGeneratedPackage>(ctx),
      std::make_shared<SvgPackage>(ctx)
    };
}

打开 entry/src/main/ets/RNPackagesFactory.ts,添加:

typescript 复制代码
import { SvgPackage } from '@react-native-ohos/react-native-svg/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new SamplePackage(ctx),
    new SvgPackage(ctx)
  ];
}

📖 API 详解

Shadow 组件

Shadow 组件是本库的核心组件,用于为子组件添加阴影效果。

基本用法

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow>
  <View style={{ width: 100, height: 100, backgroundColor: 'white' }} />
</Shadow>

startColor - 阴影起始颜色

设置阴影的起始渐变色。

类型string

默认值#00000020

使用场景

  • 自定义阴影颜色
  • 创建彩色阴影效果
  • 匹配品牌色调
tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow startColor="#eb9066d8">
  <View style={styles.box} />
</Shadow>

<Shadow startColor="#007AFF40">
  <View style={styles.box} />
</Shadow>

endColor - 阴影结束颜色

设置阴影的结束渐变色,与 startColor 配合实现渐变效果。

类型string

默认值:透明

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow startColor="#00000040" endColor="#00000000">
  <View style={styles.box} />
</Shadow>

<Shadow startColor="#FF000080" endColor="#FF000000">
  <View style={styles.box} />
</Shadow>

distance - 阴影延伸距离

设置阴影从组件边缘延伸的距离。

类型number

默认值10

使用场景

  • 控制阴影大小
  • 创建柔和或硬朗的阴影效果
tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow distance={5}>
  <View style={styles.box} />
</Shadow>

<Shadow distance={30}>
  <View style={styles.box} />
</Shadow>

offset - 阴影偏移

移动阴影的位置。负 x 值向左移动,负 y 值向上移动。

类型[x: string | number, y: string | number]

默认值[0, 0]

注意 :设置此属性会将 paintInside 的默认值设为 true

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow offset={[10, 10]}>
  <View style={styles.box} />
</Shadow>

<Shadow offset={[-10, -10]} startColor="#00000040">
  <View style={styles.box} />
</Shadow>

<Shadow offset={['50%', '10%']}>
  <View style={styles.box} />
</Shadow>

paintInside - 内部绘制

将阴影应用于内容的下方/内部。当使用 offset 属性或子组件包含透明区域时很有用。

类型boolean

默认值false(设置 offset 后默认为 true

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow paintInside startColor="#eb9066d8">
  <View style={styles.box} />
</Shadow>

sides - 边控制

指定将要绘制阴影的边,不包括角落。

类型Record<'start' | 'end' | 'top' | 'bottom', boolean>

默认值 :所有边都为 true

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow sides={{ start: false, end: true, top: false, bottom: true }} startColor="#eb9066d8">
  <View style={styles.box} />
</Shadow>

<Shadow sides={{ top: true, bottom: true, start: false, end: false }} distance={20}>
  <View style={styles.box} />
</Shadow>

corners - 角控制

指定将要绘制阴影的角。

类型Record<'topStart' | 'topEnd' | 'bottomStart' | 'bottomEnd', boolean>

默认值 :所有角都为 true

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow 
  corners={{ topStart: true, topEnd: true, bottomStart: false, bottomEnd: false }}
  distance={20}
  startColor="red"
>
  <View style={styles.box} />
</Shadow>

style - 子组件容器样式

设置包裹子组件的视图样式。

类型StyleProp<ViewStyle>

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow style={{ backgroundColor: 'white', borderRadius: 10 }}>
  <View style={styles.box} />
</Shadow>

containerStyle - 外层容器样式

设置包裹阴影和子组件的视图样式,对于设置外边距很有用。

类型StyleProp<ViewStyle>

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow containerStyle={{ margin: 20, padding: 10 }}>
  <View style={styles.box} />
</Shadow>

stretch - 水平拉伸

使子组件占据所有可用的水平空间。

类型boolean

默认值false

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow stretch>
  <View style={styles.box} />
</Shadow>

safeRender - 安全渲染

在首次渲染时不使用相对尺寸,而是在后续渲染中采用 onLayout 返回的精确尺寸。用于避免处理半径大于边尺寸时的视觉瑕疵。

类型boolean

默认值false

tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<View style={{ width: 200, height: 200 }}>
  <Shadow distance={10} safeRender>
    <View style={{ width: '100%', height: '80%', backgroundColor: 'red' }} />
  </Shadow>
</View>

disabled - 禁用阴影

禁用阴影效果,containerStylestyle 属性仍然会生效。

类型boolean

默认值false

使用场景

  • 条件渲染阴影
  • 组件复用
tsx 复制代码
import { Shadow } from 'react-native-shadow-2';

<Shadow disabled={isDarkMode}>
  <View style={styles.box} />
</Shadow>

📋 完整示例

ts 复制代码
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  SafeAreaView,
  StatusBar,
} from 'react-native';
import { Shadow } from 'react-native-shadow-2';

const App: React.FC = () => {
  return (
    <SafeAreaView style={styles.container}>
      <StatusBar barStyle="dark-content" backgroundColor="#FFFFFF" />
      <View style={styles.header}>
        <Text style={styles.headerTitle}>阴影效果演示</Text>
      </View>

      <ScrollView style={styles.content}>
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>基础阴影</Text>
          
          <View style={styles.row}>
            <Shadow>
              <View style={styles.box}>
                <Text style={styles.boxText}>默认</Text>
              </View>
            </Shadow>

            <Shadow distance={20}>
              <View style={styles.box}>
                <Text style={styles.boxText}>大距离</Text>
              </View>
            </Shadow>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>彩色阴影</Text>
          
          <View style={styles.row}>
            <Shadow startColor="#FF6B6B40" distance={15}>
              <View style={[styles.box, { backgroundColor: '#FF6B6B' }]}>
                <Text style={styles.boxText}>红色</Text>
              </View>
            </Shadow>

            <Shadow startColor="#4ECDC440" distance={15}>
              <View style={[styles.box, { backgroundColor: '#4ECDC4' }]}>
                <Text style={styles.boxText}>青色</Text>
              </View>
            </Shadow>

            <Shadow startColor="#FFE66D40" distance={15}>
              <View style={[styles.box, { backgroundColor: '#FFE66D' }]}>
                <Text style={[styles.boxText, { color: '#333' }]}>黄色</Text>
              </View>
            </Shadow>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>渐变阴影</Text>
          
          <View style={styles.row}>
            <Shadow startColor="#667eea80" endColor="#764ba200" distance={20}>
              <View style={[styles.box, { backgroundColor: '#667eea' }]}>
                <Text style={styles.boxText}>渐变1</Text>
              </View>
            </Shadow>

            <Shadow startColor="#f093fb80" endColor="#f5576a00" distance={20}>
              <View style={[styles.box, { backgroundColor: '#f093fb' }]}>
                <Text style={styles.boxText}>渐变2</Text>
              </View>
            </Shadow>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>偏移阴影</Text>
          
          <View style={styles.row}>
            <Shadow offset={[10, 10]} startColor="#00000030">
              <View style={styles.box}>
                <Text style={styles.boxText}>右下</Text>
              </View>
            </Shadow>

            <Shadow offset={[-10, -10]} startColor="#00000030">
              <View style={styles.box}>
                <Text style={styles.boxText}>左上</Text>
              </View>
            </Shadow>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>边控制</Text>
          
          <Shadow 
            sides={{ start: false, end: false, top: true, bottom: true }}
            distance={15}
            startColor="#007AFF40"
          >
            <View style={[styles.wideBox, { backgroundColor: '#007AFF' }]}>
              <Text style={styles.boxText}>仅上下边阴影</Text>
            </View>
          </Shadow>

          <View style={{ height: 16 }} />

          <Shadow 
            sides={{ start: true, end: true, top: false, bottom: false }}
            distance={15}
            startColor="#34C75940"
          >
            <View style={[styles.wideBox, { backgroundColor: '#34C759' }]}>
              <Text style={styles.boxText}>仅左右边阴影</Text>
            </View>
          </Shadow>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>圆角卡片</Text>
          
          <Shadow 
            distance={20}
            startColor="#00000020"
            style={{ borderRadius: 16 }}
          >
            <View style={styles.card}>
              <Text style={styles.cardTitle}>卡片标题</Text>
              <Text style={styles.cardContent}>
                这是一个带有圆角和阴影效果的卡片组件,展示了 react-native-shadow-2 的强大功能。
              </Text>
            </View>
          </Shadow>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>内部绘制</Text>
          
          <View style={styles.row}>
            <Shadow paintInside startColor="#FF3B3020" distance={10}>
              <View style={[styles.box, { backgroundColor: 'rgba(255,59,48,0.3)' }]}>
                <Text style={styles.boxText}>透明</Text>
              </View>
            </Shadow>

            <Shadow offset={[5, 5]} paintInside startColor="#5856D630">
              <View style={styles.box}>
                <Text style={styles.boxText}>偏移+内部</Text>
              </View>
            </Shadow>
          </View>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>拉伸模式</Text>
          
          <Shadow stretch distance={10} startColor="#00000020">
            <View style={[styles.stretchBox, { backgroundColor: '#FF9500' }]}>
              <Text style={styles.boxText}>拉伸填充</Text>
            </View>
          </Shadow>
        </View>

        <View style={styles.section}>
          <Text style={styles.sectionTitle}>禁用阴影</Text>
          
          <View style={styles.row}>
            <Shadow disabled={false} distance={10}>
              <View style={styles.box}>
                <Text style={styles.boxText}>启用</Text>
              </View>
            </Shadow>

            <Shadow disabled={true} distance={10}>
              <View style={styles.box}>
                <Text style={styles.boxText}>禁用</Text>
              </View>
            </Shadow>
          </View>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5F5F5',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 16,
    backgroundColor: '#FFFFFF',
    borderBottomWidth: 1,
    borderBottomColor: '#E5E5EA',
  },
  headerTitle: {
    fontSize: 20,
    fontWeight: '700',
    color: '#333333',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  section: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    padding: 16,
    marginBottom: 16,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#333333',
    marginBottom: 16,
  },
  row: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    flexWrap: 'wrap',
    gap: 16,
  },
  box: {
    width: 80,
    height: 80,
    backgroundColor: '#007AFF',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  wideBox: {
    width: '100%',
    height: 60,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  stretchBox: {
    height: 60,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  boxText: {
    color: '#FFFFFF',
    fontSize: 14,
    fontWeight: '600',
  },
  card: {
    width: '100%',
    backgroundColor: '#FFFFFF',
    borderRadius: 16,
    padding: 20,
  },
  cardTitle: {
    fontSize: 18,
    fontWeight: '700',
    color: '#333333',
    marginBottom: 8,
  },
  cardContent: {
    fontSize: 14,
    color: '#666666',
    lineHeight: 20,
  },
});

export default App;

⚠️ 注意事项

1. 依赖 react-native-svg

本库强依赖 react-native-svg,请确保已正确安装和配置:

bash 复制代码
npm install @react-native-ohos/react-native-svg

2. 颜色格式

颜色支持以下格式:

  • 十六进制:#RRGGBB#RRGGBBAA
  • RGBA:rgba(r, g, b, a)

推荐使用带透明度的十六进制格式:#00000040

3. 性能优化

  • 避免在列表项中使用过于复杂的阴影效果
  • 对于静态内容,考虑使用图片替代
  • 使用 disabled 属性在不需要时禁用阴影

4. 圆角处理

当使用圆角时,确保 Shadow 组件的 style 和子组件的圆角一致:

tsx 复制代码
<Shadow style={{ borderRadius: 16 }} distance={10}>
  <View style={{ borderRadius: 16, backgroundColor: 'white' }} />
</Shadow>

5. 布局影响

阴影会增加组件的实际占用空间,使用 containerStyle 设置外边距:

tsx 复制代码
<Shadow containerStyle={{ margin: 20 }} distance={10}>
  <View style={styles.box} />
</Shadow>

6. 安全渲染

对于圆形或半径大于边尺寸的情况,使用 safeRender 避免视觉瑕疵:

tsx 复制代码
<Shadow safeRender distance={50}>
  <View style={{ width: 100, height: 100, borderRadius: 50 }} />
</Shadow>
相关推荐
xinzheng新政2 小时前
Javascript·深入学习基础知识
前端·javascript·学习
代码煮茶2 小时前
Vue3 插件开发实战 | 从 0 开发一个全局通知组件(Toast/Message)并发布到 npm
javascript·vue.js
程序员Ctrl喵2 小时前
Flutter 第三阶段:基础 Widget 全面指南
开发语言·javascript·flutter
韭菜炒大葱2 小时前
事件捕获、事件冒泡、事件源对象、事件委托
javascript·面试
品克缤2 小时前
Vue3 + Router 页面切换时滚动条闪烁问题记录
前端·javascript·css·vue.js
冰暮流星3 小时前
javascript之dom方法访问内容
开发语言·前端·javascript
竹林8183 小时前
React + wagmi 实战:从零构建一个能“读”能“写”的 DeFi 前端,我踩了这些坑
前端·javascript
我命由我123453 小时前
在 React 项目中,配置了 setupProxy.js 文件,无法正常访问 http://localhost:3000
开发语言·前端·javascript·react.js·前端框架·ecmascript·js
J2虾虾3 小时前
在Vue3中推荐使用的函数定义方法
前端·javascript·vue.js