基于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)
}
}
目前OpenHarmony暂不支持AutoLink,所以Link步骤需要手动配置。
首先需要使用DevEco Studio打开项目里的OpenHarmony工程,在工程根目录的 oh-package.json5
添加 overrides 字段:
{
...
"overrides": {
"@rnoh/react-native-openharmony" : "./react_native_openharmony"
}
}
目前有两种方法:
-
通过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
然后编译、运行即可。
-
直接链接源码。
如需使用直接链接源码,请参考直接链接源码说明
说明: "Platform"列表示支持的平台,All表示支持所有平台。
Name | Description | Type | Platform |
---|---|---|---|
geometryViewID | 共享元素ID. | string | OpenHarmony |
onGeometryViewClick | 点击GeometryView回调. | callback | OpenHarmony |