HarmonyOS 鸿蒙Next交互归一开发指导
HarmonyOS 鸿蒙Next交互归一开发指导
概述
在移动应用开发中,悬浮、点击、双击、长按、上下文菜单、拖拽、轻扫、滚动/平移、缩放和旋转这10种交互事件,在不同的移动端设备上可以分别由触控屏、触控板或鼠标这三类输入设备的不同操作方式触发。开发多设备项目时,必须考虑不同输入设备的交互方式。而使用交互归一组件,保证不同交互场景下的体验一致性,开发者只需要调用归一后的交互事件接口,无需为每个输入设备单独适配,从而大幅简化开发流程。
如下图为不同交互事件在不同设备上的触发方式:
如下表为不同框架上提供的交互归一组件实现不同交互事件的接口:
RN(组件地址) | Flutter(组件地址) | H5(组件地址) | |
---|---|---|---|
悬浮 | Gesture.Hover() | onHover | onHover |
点击 | Gesture.Pan() | onTap | onClick |
双击 | Gesture.Tap() | onDoubleTap | onDoubleClick |
长按 | Gesture.LongPress() | onLongPress | onLongPressStart onLongPressEnd onLongPressCancel |
上下文菜单 | react-native-popup-menu | onContentMenu | onContextMenu |
拖拽 | Gesture.Pan() | onDragStart onDragUpdate onDragEnd |
onDragStart onDragEnter onDragMove onDragLeave onDrop |
轻扫 | Gesture.Fling() | onSwipe | onSwipe |
滚动 | Gesture.Pan() | onPanStart onPanUpdate onPanEnd onPanCancel |
onScroll |
缩放 | Gesture.Pinch() | Transform onPinchStart onPinchUpdate |
onPinchStart onPinchMove onPinchEnd |
旋转 | Gesture.Rotation() | Transform onRotateStart onRotateUpdate onRotateEnd |
onRotateStart onRotateMove onRotateEnd |
交互归一事件适配
一、悬浮事件
-
RN适配指导
1. 主要方法和参数
Gesture.Hover():悬浮手势对象。
onHover:悬浮手势触发的回调方法。
2. 示例
import { GestureDetector, Gesture} from '@hadss/react-native-uniinput';
// 用手势组件包裹元素
<GestureDetector gesture={onHoverForTest}>
<Text style={[isHovered && styles.mouseHovered]}>
{title}
</Text>
</GestureDetector>
//在鼠标悬浮的时候改变样式
const onHoverForTest = Gesture.Hover().onHover(e => {
// 鼠标移入或移除的时候触发
setIsHovered(e.isHover);
});
-
Flutter适配指导
1. 主要方法
onHover:悬浮事件名,在onHover方法实现悬浮需要实现的具体事件效果。
2. 回调参数
isHover:鼠标是否悬浮。
3. 示例
UnifiedGestureDetector(
onHover: onHover,
child: Container(...) //需要实现悬浮效果的widget,例如Text
)
void onHover(bool isHover, PointerEvent event) {
if (mounted) {
setState(() {
if (isHover) {
// 悬浮,按钮变大逻辑
}else {
// 取消悬浮,按钮还原
}
});
}
}
-
H5适配指导
1. 主要方法
onHover:悬浮进入或退出事件。
onHoverMove:悬浮事件,在onHoverMove方法实现悬浮的具体效果。
2. 示例
<template>
<div ref="testDom" id="testId"></div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import {
PointerGestureManager,
PointerOptions,
GestureHandlers,
PointerState,
} from "@hadss/web_uni_input";
const handleHover = (state: PointerState) => {
// 代码编辑
};
const handleHoverMove = (state: PointerState) => {
// 代码编辑
};
const testDom = ref<HTMLElement | null>(null);
const instance = ref(null);
onMounted(() => {
// 如果要获取DOM元素,请在DOM元素挂载之后获取,比如VUE3生命周期的onMounted中获取DOM元素
const handlers: GestureHandlers = {
onHover: handleHover,
onHoverMove: handleHoverMove,
};
const configs: PointerOptions = {
enableHover: true,
};
if (testDom.value) {
instance.value = PointerGestureManager(testDom.value, handlers, configs);
}
});
onUnmounted(() => {
//destroy销毁实例,实例销毁以后交互归一事件不再触发
if (instance.value) {
instance.value.destroy();
}
});
</script>
<style scoped>
#testId {
width: 200px;
height: 200px;
background-color: aquamarine;
}
</style>
2、点击和双击事件
-
RN适配指导
1. 主要方法和参数
Gesture.Tap():手势点击对象,单击或双击的时候触发。
numberOfTaps:属性,用于触发点击手势所需的点击次数。
minPointers:属性,用于触发手势需要的手指数目。
onStart:回调方法,手势触发开始时的回调。
2. 示例
import { GestureDetector, Gesture} from '@hadss/react-native-uniinput';
// 用手势组件包裹元素
<GestureDetector gesture={Gesture.Exclusive(doubleTap, singleTap)}>
<View>
<Animated.View style={[animatedStyle]}>
{songsList.map((item, index) => (
<View key={index}>
<Text>1233333333333333</Text>
</View>
))}
</Animated.View>
</View>
</GestureDetector>
// 通过点击的次数区分单双击事件
// 单击事件
const singleTap = Gesture.Tap()
.numberOfTaps(1)
.onStart(() => {
console.log('Single tap!');
});
// 双击事件
const doubleTap = Gesture.Tap()
.numberOfTaps(2)
.onStart(() => {
console.log('Double tap!')
});
-
Flutter适配指导
1. 主要方法
onTap:单击事件名,在onTap方法实现单击具体操作。
onDoubleTap:双击事件名,在onDoubleTap方法实现双击具体操作。
2. 示例
UnifiedGestureDetector(
onTap: onTap,
onDoubleTap: onDoubleTap,
child: Container(...) //需要实现单击和双击的widget
)
void onTap() {
//单击进入歌曲详情页,歌曲暂停状态下不播放歌曲
}
void onDoubleTap() {
//双击进入歌曲详情页,歌曲暂停状态下播放歌曲
}
-
H5适配指导
1. 主要方法
onClick:单击事件,在onClick方法实现单击具体操作。
onDoubleClick:双击事件,在onDoubleClick方法实现双击具体操作。
2. 示例
<template>
<div ref="testDom" id="testId"></div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import {
PointerGestureManager,
PointerOptions,
GestureHandlers,
PointerState,
} from "@hadss/web_uni_input";
const handleClick = (state: PointerState) => {
// 代码编辑
};
const handleDoubleClick = (state: PointerState) => {
// 代码编辑
};
const testDom = ref<HTMLElement | null>(null);
const instance = ref(null);
onMounted(() => {
// 如果要获取DOM元素,请在DOM元素挂载之后获取,比如VUE3生命周期的onMounted中获取DOM元素
const handlers: GestureHandlers = {
onClick: handleClick, // 点击
onDoubleClick: handleDoubleClick // 双击
};
const configs: PointerOptions = {
enableClick: true,
enableDoubleClick: true,
};
if (testDom.value) {
instance.value = PointerGestureManager(testDom.value, handlers, configs);
}
});
onUnmounted(() => {
//destroy销毁实例,实例销毁以后交互归一事件不再触发
if (instance.value) {
instance.value.destroy();
}
});
</script>
<style scoped>
#testId {
width: 200px;
height: 200px;
background-color: aquamarine;
}
</style>
3、长按事件
-
RN适配指导
1. 主要方法和参数
Gesture.LongPress():长按事件对象,长按时创建。
repeat:boolean类型属性,是否允许长按手势重复触发。
minDuration:number类型属性,长按手势识别所需的最短持续时间(毫秒)。
onStart:回调方法,手势开始时的回调。
onCancel:回调方法,手势取消时的回调。
onEnd:回调方法,手势结束时的回调。
2. 示例
import { GestureDetector, Gesture} from '@hadss/react-native-uniinput';
// 用手势组件包裹元素
<GestureDetector gesture={longPressGesture}>
<Image
source={require('../../../asset/share.svg')}
style={styles.imageSmall}
/>
</GestureDetector>
// 长按的时候触发提醒
const longPressGesture = Gesture.LongPress().onEnd(() => Alert.alert('无法分享'));
-
Flutter适配指导
1. 主要方法
onLongPress:长按事件名,在onLongPress方法中实现长按需要的效果。
2. 示例
UnifiedGestureDetector(
pointerOptions: const PointerOptions(),
onLongPress: onLongPress,
child: Container(...) //需要实现长按效果的widget
)
void onLongPress() {
//长按事件触发后的处理逻辑
}
-
H5适配指导
1. 主要方法
onLongPressStart:长按开始事件,在onLongPressStart方法实现长按的具体操作。
onLongPressEnd:长按结束事件。
onLongPressCancel:长按取消事件,在onLongPressCancel方法实现长按取消的具体操作。
2. 示例
<template>
<div ref="testDom" id="testId"></div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import {
PointerGestureManager,
PointerOptions,
GestureHandlers,
PointerState,
} from "@hadss/web_uni_input";
const handlePressStart = (state: PointerState) => {
// 代码编辑
};
const handlePressEnd = (state: PointerState) => {
// 代码编辑
};
const handlePressCancel = (state: PointerEvent) => {
// 代码编辑
};
const testDom = ref<HTMLElement | null>(null);
const instance = ref(null);
onMounted(() => {
// 如果要获取DOM元素,请在DOM元素挂载之后获取,比如VUE3生命周期的onMounted中获取DOM元素
const handlers: GestureHandlers = {
onLongPressStart: handlePressStart, // 长按开始
onLongPressEnd: handlePressEnd, // 长按结束
onLongPressCancel: handlePressCancel, // 长按取消
};
const configs: PointerOptions = {
enableLongPress: true,
};
if (testDom.value) {
instance.value = PointerGestureManager(testDom.value, handlers, configs);
}
});
onUnmounted(() => {
// destroy销毁实例,实例销毁以后交互归一事件不再触发
if (instance.value) {
instance.value.destroy();
}
});
</script>
<style scoped>
#testId {
width: 200px;
height: 200px;
background-color: aquamarine;
}
</style>
4、上下文菜单
-
RN适配指导
1. 组件
MenuTrigger: 组件,用于嵌套在触发上下文的组件的外层。
MenuOptions: 组件,用于嵌套在上下文组件的外层,其内层可以有多个MenuOption 组件。
Menu: 组件,上下文外层组件,用于嵌套在MenuTrigger 和MenuOptions组件外。
MenuProvider: 组件,上下文外层组件,用于嵌套在Menu组件外。
2. 示例
import {
GestureDetector,
Gesture,
MenuProvider,
Menu,
MenuOptions,
MenuOption,
MenuTrigger,
ViewWithKeyEvent,
} from '@hadss/react-native-uniinput';
//MenuTrigger播过触发上下文的组件
//MenuOptions包裹弹出的上下文的内容
//MenuTrigger和MenuTrigger都是Menu的子组件,而Menu又是MenuProvider的子组件
<MenuProvider
style={{alignItems: 'center', marginTop: 20}}
onTouchStart={calculateMenuPosition}>
<Menu
onClose={() => {
setTimeout(() => setIsLongPressed(false), 500);
}}>
<MenuTrigger
triggerOnLongPress={true}
onPress={() => {
setIsLongPressed(true);
}}>
<Image
source={require('../../../../asset/song_item_icon.svg')}
style={styles.songIcon}
/>
</MenuTrigger>
<MenuOptions
optionsContainerStyle={[
styles.optionList,
{
position: 'absolute',
top: position.top,
left: position.left,
},
]}>
<MenuOption
onSelect={() => deleteItem(index)}
style={{flexDirection: 'row'}}>
<Image
source={require('../../../../asset/delete.svg')}
style={styles.songDelete}
/>
<Text style={styles.optionBtn}>{'删除'}</Text>
</MenuOption>
{item.hasCollect ? (
<MenuOption
onSelect={() => deleteCollectItem(index)}
style={{flexDirection: 'row'}}>
<Image
source={require('../../../../asset/deleteCollect.svg')}
style={styles.songDelete}
/>
<Text style={styles.optionBtn}>{'移除收藏'}</Text>
</MenuOption>
) : (
<MenuOption
onSelect={() => collectItem(index)}
style={{flexDirection: 'row'}}>
<Image
source={require('../../../../asset/collect.svg')}
style={styles.songDelete}
/>
<Text style={styles.optionBtn}>{'收藏到歌单'}</Text>
</MenuOption>
)}
</MenuOptions>
</Menu>
</MenuProvider>
-
Flutter适配指导
1. 主要方法
onContentMenu:下拉菜单功能,鼠标或者触控点位置存在的情况下,显示上下文菜单UI效果。
2. 回调参数
event.localPosition:当前鼠标或者触控点位置。
3. 示例
UnifiedGestureDetector(
pointerOptions: const PointerOptions(),
onContentMenu: onContentMenu,
child: CustomWidget(...) //需要实现上下文菜单的widget
)
void onContentMenu(GestureEvent event) {
//event.localPosition:当前鼠标或者触控点的位置
if (event.localPosition == null) {
return;
}
//创建上下文菜单Widget,使用PopupMenu的showMenu方法自定义PopupMenuItem实现上下文菜单UI
}
-
H5适配指导
1. 主要方法
onContextMenu:下拉菜单功能,鼠标或者触控点位置存在的情况下,显示上下文菜单UI效果。
2. 示例
<template>
<div ref
更多关于HarmonyOS 鸿蒙Next交互归一开发指导的实战教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next交互归一开发基于ArkTS语言,通过声明式UI和状态管理实现跨设备统一交互。开发者需使用ArkUI组件构建自适应界面,结合分布式能力实现多端协同。系统提供统一的交互事件处理机制,支持一次开发多端部署。关键API包括UI上下文管理、交互事件响应及布局自适应模块。
更多关于HarmonyOS 鸿蒙Next交互归一开发指导的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS Next的交互归一开发指导提供了跨设备交互事件的一致性解决方案,通过统一的API接口适配触控屏、触控板和鼠标等不同输入设备。该方案覆盖了悬浮、点击、双击、长按、上下文菜单、拖拽、轻扫、滚动/平移、缩放和旋转等10种核心交互事件,并针对RN、Flutter和H5框架分别提供了具体的组件和接口实现。
关键点包括:
- 统一接口设计:不同框架下的事件接口命名和参数保持一致(如onHover、onTap等),减少多设备适配成本。
- 框架适配示例:详细展示了RN(Gesture组件)、Flutter(UnifiedGestureDetector)和H5(PointerGestureManager)的代码实现,包括事件绑定和回调处理。
- 输入设备兼容:支持触控、鼠标和键盘事件的无缝切换,例如通过ViewWithKeyEvent处理物理按键。
- 性能优化:通过事件管理器的销毁机制(如destroy())避免资源泄漏,确保交互响应的流畅性。
开发者可直接参考提供的代码示例和组件地址(如GitCode仓库),快速集成到多设备项目中,无需针对不同输入方式单独开发,显著提升开发效率。