HarmonyOS鸿蒙Next中RN OpenHarmony特征&多设备适配最佳实践
HarmonyOS鸿蒙Next中RN OpenHarmony特征&多设备适配最佳实践
- 概述
现有的伙伴应用使用RN框架开发的历史页面多且冗杂。为达到HarmonyOS系统一多体验,所有页面若均使用ArkUI框架重新开发耗时长、成本高,不可行。针对此问题,本文将主要提供一套RN多设备响应式组件及方案:
1)一套基于RN的鸿蒙特征动画组件库,在RN页面实现鸿蒙特征动画UI效果;
2)一套基于RN的一多高阶组件库,在RN页面实现折叠屏悬停避让分栏的UI效果;
首先介绍组件及效果说明,再分别结合组件效果提供对应场景的开发案例,最终提供示例代码指导实际开发。
组件库安装
参考rn_multidevice_layout_scenepkg 和 rn_hmfeatures。
- 多设备断点
2.1 断点设计原理
RN断点是基于鸿蒙多设备封装的一套断点机制,通过设置断点,让开发者可以结合窗口宽度去实现不同的页面布局效果。
断点以应用窗口宽度为基准,将应用窗口在宽度维度上分成了几个不同的区间即不同的断点,默认提供的断点区间如下所示。
断点名称 | 取值范围(px) |
---|---|
xs | [0, 320) |
sm | [320, 600) |
md | [600, 840) |
lg | [840, 1440) |
xl | [1440, +∞) |
2.2 多设备适配指导
在实际开发过程中,可以使用rn_multidevice_layout_scenepkg的setBreakpoints自定义断点的区间,也可以使用上述默认的断点区间。使用useBreakpointValue时,只需将屏幕断点所对应的参数传入useBreakpointValue,当屏幕断点发生变化时,该hook会根据当前断点的类型返回所对应的数据。
具体示例如下所示:
自定义断点区间
// 自定义断点区间,可选
useEffect(() => {
setBreakpoints({
base: 320,
md: 768,
lg: 1024,
});
});
使用断点hook并获取不同断点下的属性值
const color = useBreakpointValue({
base: 'red',
xs: 'blue',
sm: 'green',
md: 'yellow',
lg: 'purple',
xl: 'orange',
});
return (
<Text style={{ color }}>Responsive Color Text</Text>
);
- RN 鸿蒙特征动画组件
3.1 组件使用说明
rn_hmfeatures鸿蒙特征动画组件GeometryView,基于ArkUI的geometryTransition接口,实现了鸿蒙特征动画效果,详细介绍可参考:使用geometryTransition共享元素转场。
组件导入方式
import GeometryView from 'rn_hmfeatures/src/';
组件API
名称 | 类型 | 必填 | 说明 |
---|---|---|---|
geometryViewID | string | 是 | 设置转场动效ID |
onGeometryViewClick | DirectEventHandler | 否 | 点击回调函数 |
3.2 场景案例
点击歌单页当前播放音乐控件,跳转音乐播放页,触发一镜到底的转场效果。
关键代码片段
1、将歌单页中的当前播放音乐控件设置共享元素ID,监听点击事件并发送消息至ArkUI侧。(SampleTurboModule为自定义TurboModule,执行调用ArkUI侧发送消息方法)
return (
<GeometryView
style={styles.container}
geometryViewID={'test'} // 设置共享元素ID
onGeometryViewClick={() => {
SampleTurboModule.pushStringToHarmony('pages/MusicPlay', 1);
}}>
<Image source={require('../..../..../asset/cover.png')} style={[styles.albumCover, { marginLeft: itemLeft }]} />
<View style={styles.songInfo}>
<Text style={styles.songTitle}>{song.title}</Text>
<Text style={styles.songArtist}>{song.artist}</Text>
</View>
<View style={{ flex: 1 }} />
{controlIcons}
</GeometryView>
);
2、ArkUI侧监听跳转事件,在animateTo闭包内执行页面跳转逻辑
aboutToAppear() {
emitter.on({ eventId: 1 }, () => {
animateTo({ duration: 700, curve: Curve.Friction }, () => {
this.navPathStack.pushPath({ name: 'MusicPlayPage' });
});
});
}
3、音乐播放页设置与歌单页一致的共享元素ID
@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)
} else if (this.instance) {
BaseRN({
rnInstance: this.instance,
moduleName: this.moduleName,
bundlePath: this.bundlePath,
}).align(Alignment.Top)
}
}
.geometryTransition('test') // 设置共享元素ID
.hideTitleBar(true)
}
}
- RN 折叠屏适配组件
4.1 组件使用说明
RN折叠屏适配组件FoldSplitContainer,包含primary、secondary、extra三个区域,实现折叠屏二分栏、三分栏在展开态、悬停态以及折叠屏悬停状态下折痕区避让,详情参考:rn_multidevice_layout_scenepkg。
组件导入方式
import { FoldSplitContainer } from 'rn_multidevice_layout_scenepkg/src';
FoldSplitContainer组件
Name | Description | Type | Platform |
---|---|---|---|
primary | 主要区域回调函数。 | function | OpenHarmony |
secondary | 次要区域回调函数。 | function | OpenHarmony |
extra | 扩展区域回调函数,不传入的情况,没有对应区域。 | function | OpenHarmony |
expandedLayoutOptions | 展开态布局信息。 | ExpandedRegionLayoutOptions | OpenHarmony |
hoverModeLayoutOptions | 悬停态布局信息。 | HoverModeRegionLayoutOptions | OpenHarmony |
foldedLayoutOptions | 折叠态布局信息。 | FoldedRegionLayoutOptions | OpenHarmony |
onHoverStatusChange | 折叠屏进入或退出悬停模式时触发的回调函数。 | onHoverStatusChangeHandler | OpenHarmony |
ExpandedRegionLayoutOptions
Name | Description | Type | Platform |
---|---|---|---|
isExtraRegionPerpendicular | 扩展区域是否从上到下贯穿整个组件,当且仅当extra有效时此字段才生效。默认值:true。 | boolean | OpenHarmony |
verticalSplitRatio | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 | number | OpenHarmony |
horizontalSplitRatio | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 | number | OpenHarmony |
extraRegionPosition | 扩展区域的位置信息,当且仅当isExtraRegionPerpendicular = false有效时此字段才生效。默认值:ExtraRegionPosition.top。 | ExtraRegionPosition | OpenHarmony |
HoverModeRegionLayoutOptions
Name | Description | Type | Platform |
---|---|---|---|
showExtraRegion | 可折叠屏幕在半折叠状态下是否显示扩展区域。默认值:false。 | boolean | OpenHarmony |
horizontalSplitRatio | 主要区域与扩展区域之间的宽度比例,当且仅当extra有效时此字段才生效。默认值:PresetSplitRatio.LAYOUT_3V2。 | number | OpenHarmony |
extraRegionPosition | 扩展区域的位置信息,当且仅当showExtraRegion时此字段才生效。默认值:ExtraRegionPosition.top。 | ExtraRegionPosition | OpenHarmony |
FoldedRegionLayoutOptions
Name | Description | Type | Platform |
---|---|---|---|
verticalSplitRatio | 主要区域与次要区域之间的高度比例。默认值:PresetSplitRatio.LAYOUT_1V1。 | number | OpenHarmony |
onHoverStatusChangeHandler
Name | Description | Type | Platform |
---|---|---|---|
callback | 折叠屏进入或退出悬停模式时触发的回调函数。 | (status: HoverModeStatus) => void | OpenHarmony |
HoverModeStatus
Name | Description | Type | Platform |
---|---|---|---|
foldStatus | 设备的折叠状态。 | FoldStatus | OpenHarmony |
isHoverMode | app当前是否处于悬停态。 | boolean | OpenHarmony |
ExtraRegionPosition
Name | Description | Value |
---|---|---|
top | 扩展区域在组件上半区域。 | 1 |
bottom | 扩展区域在组件下半区域。 | 2 |
PresetSplitRatio
Name | Description | Value |
---|---|---|
LAYOUT_1V1 | 1:1比例。 | 1/1 |
LAYOUT_3V2 | 3:2比例。 | 3/2 |
LAYOUT_2V3 | 2:3比例。 | 2/3 |
推荐使用方式
const primaryRender = () => (
<View>
<Text> 此区域为primary </Text>
</View>
);
const secondRender = () => (
<View>
<Text> 此区域为second </Text>
</View>
);
const extraRender = () => (
<View>
<Text> 此区域为extra </Text>
</View>
);
const expandedLayoutOptions: ExpandedRegionLayoutOptions = {
isExtraRegionPerpendicular: true,
verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
horizontalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
};
const foldedRegionLayoutOptions: FoldedRegionLayoutOptions = {
verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
};
const hoverModeLayoutOptions: HoverModeRegionLayoutOptions = {
horizontalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
showExtraRegion: true,
};
<FoldSplitContainer
primary={primaryRender()}
secondary={secondRender()}
extra={extraRender()}
expandedLayoutOptions={expandedLayoutOptions}
foldedLayoutOptions={foldedRegionLayoutOptions}
hoverModeLayoutOptions={hoverModeLayoutOptions}
/>
4.2 场景案例
实现效果
fold | expanded | hover |
---|---|---|
![]() |
![]() |
![]() |
关键代码片段
const secondRender = () => (
<View style={{flex: 1, alignItems: 'center'}}>
<View style={styles.message}>
<View>
<Text style={styles.title}>{title}</Text>
<Text style={styles.artist}>{artist}</Text>
</View>
<Image
source={require('../../asset/likes.svg')}
style={styles.imageGrey}
/>
</View>
<View style={styles.slider}>
<Slider
style={{width: '100%'}}
minimumValue={0}
maximumValue={duration}
value={position}
minimumTrackTintColor="#e8e1e1"
maximumTrackTintColor="#784949"
thumbStyle={{opacity: 0}}
onValueChange={(val: number) => {
seekTo(val);
}}
/>
</View>
<View style={styles.controls}>
<Text style={styles.text}>{formatTime(position)}</Text>
<Text style={styles.text}>{formatTime(duration)}</Text>
</View>
<View style={styles.container}>
<Image
source={require('../../asset/repeat.svg')}
style={styles.imageGrey}
/>
<TouchableOpacity onPress={skipToPrevious}>
<Image
source={require('../../asset/left.svg')}
style={styles.image}
/>
</TouchableOpacity>
<TouchableOpacity onPress={togglePlayPause}>
<Image
source={playState === State.Playing ? require('../../asset/pause.svg') : require('../../asset/play.svg')}
style={styles.imagePlay}
/>
</TouchableOpacity>
<TouchableOpacity onPress={skipToNext}>
<Image
source={require('../../asset/forward_end_fill.svg')}
style={styles.image}
/>
</TouchableOpacity>
<Image
source={require('../../asset/music_note_list.svg')}
style={styles.imageGrey}
/>
</View>
<View style={styles.container}>
<Image
source={require('../../asset/share_play.svg')}
style={styles.imageGrey}
/>
<Image
source={require('../../asset/bell.svg')}
style={styles.imageGrey}
/>
<Image
source={require('../../asset/arrow_down_circle.svg')}
style={styles.imageGrey}
/>
<Image
source={require('../../asset/dot.svg')}
style={styles.imageGrey}
/>
</View>
</View>
);
const extraRender = () => (
<View style={styles.extra}>
<Text style={{
marginTop: isHover ? 70 : 0,
marginRight: isPad ? 200 : 0,
fontSize: 23,
color: '#ffffff',
}}>
此歌曲为纯音乐,请您欣赏
</Text>
</View>
);
const expandedLayoutOptions: ExpandedRegionLayoutOptions = {
isExtraRegionPerpendicular: true,
verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
horizontalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
};
const foldedRegionLayoutOptions: FoldedRegionLayoutOptions = {
verticalSplitRatio: PresetSplitRatio.LAYOUT_1V1,
};
const hoverModeLayoutOptions: HoverModeRegionLayoutOptions = {
horizontalSplitRatio: 0.66,
showExtraRegion: true,
};
return (
<ImageBackground
source={require('../../asset/blur.png')}
style={{width: '100%', height: '100%'}}>
<View style={{position: 'absolute', width: '100%', alignItems: 'center'}}>
<FoldSplitContainer
primary={primaryRender()}
secondary={secondRender()}
extra={extraRender()}
expandedLayoutOptions={expandedLayoutOptions}
foldedLayoutOptions={foldedRegionLayoutOptions}
hoverModeLayoutOptions={hoverModeLayoutOptions}
/>
</ImageBackground>
);
更多关于HarmonyOS鸿蒙Next中RN OpenHarmony特征&多设备适配最佳实践的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,React Native(RN)与OpenHarmony的结合为开发者提供了跨平台开发的能力,同时支持多设备适配。RN在OpenHarmony中的特征主要包括:
-
跨平台一致性:RN允许开发者使用JavaScript编写代码,并在多个设备上运行,确保应用在手机、平板、智能手表等设备上的一致性体验。
-
组件化开发:RN的组件化开发模式与OpenHarmony的组件化架构相匹配,开发者可以通过RN的组件库快速构建应用界面,并与OpenHarmony的底层能力进行无缝集成。
-
性能优化:RN在OpenHarmony中通过Native Modules和Native Components与底层系统进行高效通信,确保应用的性能接近原生应用。
-
多设备适配:RN支持响应式布局和自适应UI,能够根据不同设备的屏幕尺寸和分辨率自动调整界面布局,确保应用在不同设备上的显示效果。
-
生态系统支持:RN与OpenHarmony的生态系统紧密结合,开发者可以利用OpenHarmony的分布式能力,实现跨设备的协同工作和数据共享。
在多设备适配的最佳实践中,开发者应关注以下几点:
-
统一设计规范:遵循OpenHarmony的设计规范,确保应用在不同设备上的UI一致性。
-
响应式布局:使用RN的Flexbox布局和Dimensions API,确保应用界面能够自适应不同屏幕尺寸。
-
设备特性适配:根据设备特性(如触摸屏、传感器等)调整应用功能,充分利用设备的硬件能力。
-
性能监控:使用RN的性能监控工具,优化应用在不同设备上的运行效率。
通过以上特征和最佳实践,开发者可以在HarmonyOS鸿蒙Next中充分发挥RN与OpenHarmony的优势,构建高效、一致且适配多设备的应用。
更多关于HarmonyOS鸿蒙Next中RN OpenHarmony特征&多设备适配最佳实践的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,RN(React Native)与OpenHarmony的结合主要关注跨平台开发与多设备适配。最佳实践包括:
- 统一UI组件库:使用鸿蒙提供的UI组件库,确保在不同设备上的一致性。
- 响应式布局:采用Flexbox布局,适配不同屏幕尺寸和分辨率。
- 设备能力检测:通过API检测设备特性(如屏幕尺寸、传感器等),动态调整应用行为。
- 跨平台API封装:封装鸿蒙与RN的API,简化多平台开发。
- 性能优化:利用鸿蒙的分布式能力,优化跨设备协同性能。
通过这些实践,开发者可以高效构建适配多设备的应用。