@hadss/react_native_geometry_transition

1.0.0-rc.0 • Public • Published

@hadss/react_native_geometry_transition

介绍

基于Fabric CAPI实现OpenHarmony一镜到底效果。

工程目录

├─harmony
│  ├─geometry_transition.har
│  └─geometry_transition
│     └─src
│        └─main
│           └─cpp          // OpenHarmony侧CAPI实现Fabric组件
│              ├─CMakeLists.txt
│              ├─GeometryViewComponentDescriptor.h
│              ├─GeometryViewComponentInstance.cpp
│              ├─GeometryViewComponentInstance.h
│              ├─GeometryViewEventEmitter.cpp
│              ├─GeometryViewEventEmitter.h
│              ├─GeometryViewJSIBinder.h
│              ├─GeometryViewNode.cpp
│              ├─GeometryViewNode.h
│              ├─GeometryViewPackage.cpp
│              ├─GeometryViewPackage.h
│              ├─Props.cpp
│              └─Props.h
└─src
   ├─index.tsx
   └─fabric
      └─GeometryView.tsx   // RN 侧Fabric组件

安装与使用

进入到工程目录并输入以下命令:

npm

npm install @hadss/react_native_geometry_transition

yarn

yarn add @hadss/react_native_geometry_transition

下面的代码展示了这个库的基本使用场景:ArkUI的navigation控制路由跳转,NavDestination加载对应的RN bundle。

PlayList页面

使用了GeometryView组件,并设置了geometryViewID为'test',点击事件调用原生navPathStack.pushPath,跳转MusicPlay页面。

function PlayList() {
  return (
    <SafeAreaView style={styles.container}>
      <GeometryView
        style={[styles.geometryView, { top: 100, left: 100 }]} 
        geometryViewID={'test'}
        onGeometryViewClick={() => {
          SampleTurboModule.pushStringToHarmony('pages/MusicPlay', 1);
        }}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%',
    height: '100%',
  },
  geometryView: {
    position: 'absolute', 
    width: 60,
    height: 60,
    backgroundColor: 'red',
  },
});

export default PlayList;

MusicPlay页面

function MusicPlay() {
  return (
    <SafeAreaView style={styles.container}>
      <GeometryView style={{ width: 200, height: 200, backgroundColor: 'red' }} geometryViewID={'test'} onGeometryViewClick={() => {
        SampleTurboModule.pushStringToHarmony('pop', 2)
      }} >
      </GeometryView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%',
    height: '100%'
  },
  text: {
    fontSize: 18,
    color: '#333',
  },
});

export default MusicPlay;

原生侧

PlayListPage监听RN页面跳转事件,如果事件触发,调用this.navPathStack.pushPath({ name: 'MusicPlayPage' }),跳转至原生MusicPlayPage页面。

@Component
export default struct PlayListPage {
  private instance: RNInstance = LoadManager.instance;
  private bundlePath = 'bundle/playlist.harmony.bundle'
  private moduleName = 'PlayList'
  @StorageLink('isMetroAvailable') isMetroAvailable: boolean = false
  @Consume('navPathStack') navPathStack: NavPathStack

  aboutToAppear() {
    emitter.on({ eventId: 1 }, () => {
      animateTo({duration: 700, curve: Curve.Friction}, () => {
        this.navPathStack.pushPath({ name: 'MusicPlayPage' })
      });
    });
  }

  aboutToDisappear() {
    emitter.off(1);
  }

  build() {
    NavDestination() {
      if (this.isMetroAvailable) {
        MetroBaseRN({
          moduleName: this.moduleName,
        }).align(Alignment.Top).margin({ top: 0 })
      } else if (this.instance) {
        BaseRN({
          rnInstance: this.instance,
          moduleName: this.moduleName,
          bundlePath: this.bundlePath,
        }).align(Alignment.Top).margin({ top: 0 })
      } else {
        Text('加载失败')
      }
    }
    .hideTitleBar(true)
  }
}

MusicPlayPage加载RN侧MusicPlay页面

@Component
export default struct MusicPlayPage {
  private instance: RNInstance = LoadManager.instance
  private bundlePath = 'bundle/musicplay.harmony.bundle'
  private moduleName = 'MusicPlay'
  @StorageLink('isMetroAvailable') isMetroAvailable: boolean = false
  @Consume('navPathStack') navPathStack: NavPathStack

  aboutToAppear() {
    emitter.on({ eventId: 2 }, () => {
      animateTo({duration: 700, curve: Curve.Friction}, () => {
        this.navPathStack.pop()
      });
    });
  }

  aboutToDisappear() {
    emitter.off(2);
  }

  build() {
    NavDestination() {
      if (this.isMetroAvailable) {
        MetroBaseRN({
          moduleName: this.moduleName,
        })
          .align(Alignment.Top).margin({ top: 20 })
      } else if (this.instance) {
        BaseRN({
          rnInstance: this.instance,
          moduleName: this.moduleName,
          bundlePath: this.bundlePath,
        }).align(Alignment.Top).margin({ top: 20 })
      } else {
        Text('加载失败')
      }
    }
    .geometryTransition('test')   // 设置同RN侧一致的id
    .hideTitleBar(true)
  }
}

Link

目前OpenHarmony暂不支持AutoLink,所以Link步骤需要手动配置。

首先需要使用DevEco Studio打开项目里的OpenHarmony工程,在工程根目录的 oh-package.json5 添加 overrides 字段:

{
  ...
  "overrides": {
    "@rnoh/react-native-openharmony" : "./react_native_openharmony"
  }
}

引入原生端代码

目前有两种方法:

  1. 通过har包引入(在IDE完善相关功能后该方法会被遗弃,目前首选此方法)。

    说明: har包位于三方库安装路径的harmony文件夹下。

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

    "dependencies": {
        "@rnoh/react-native-openharmony": "file:../react_native_openharmony",
        "@hadss/react_native_geometry_transition": "file:../../node_modules/@hadss/react_native_geometry_transition/harmony/geometry_transition.har",
      }

    b.配置CMakeLists和引入GeometryViewPackage:

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

    project(rnapp)
    cmake_minimum_required(VERSION 3.4.1)
    set(CMAKE_SKIP_BUILD_RPATH TRUE)
    set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
    set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
    
    set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")
    set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated")
    set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
    set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
    add_compile_definitions(WITH_HITRACE_SYSTRACE)
    set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
    + add_subdirectory("${OH_MODULE_DIR}/@hadss/react_native_geometry_transition/src/main/cpp" ./geometry_transition)
    
    add_subdirectory("${RNOH_CPP_DIR}" ./rn)
    
    add_library(rnoh_app SHARED
        "./PackageProvider.cpp"
        "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
    )
    
    target_link_libraries(rnoh_app PUBLIC rnoh)
    + target_link_libraries(rnoh_app PUBLIC geometry_transition)

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

    #include "RNOH/PackageProvider.h"
    + #include "GeometryViewPackage.h"
    
    using namespace rnoh;
    
    std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
        return {
    +        std::make_shared<GeometryViewPackage>(ctx)
        };
    }

    d.运行:

    点击右上角的sync按钮

    或者在终端执行:

    cd entry
    ohpm install

    然后编译、运行即可。

  2. 直接链接源码。

    如需使用直接链接源码,请参考直接链接源码说明

API

说明: "Platform"列表示支持的平台,All表示支持所有平台。

Name Description Type Platform
geometryViewID 共享元素ID. string OpenHarmony
onGeometryViewClick 点击GeometryView回调. callback OpenHarmony

/@hadss/react_native_geometry_transition/

    Package Sidebar

    Install

    npm i @hadss/react_native_geometry_transition

    Weekly Downloads

    4

    Version

    1.0.0-rc.0

    License

    Apache-2.0

    Unpacked Size

    50.1 kB

    Total Files

    27

    Last publish

    Collaborators

    • fangzy0823
    • hyryyds1
    • chensheng_slfx
    • cepandxy