HarmonyOS鸿蒙Next中手势拖拽时和Swiper组件滑动发生冲突如何解决
HarmonyOS鸿蒙Next中手势拖拽时和Swiper组件滑动发生冲突如何解决
【问题现象】
用Swiper实现图片的预览、缩放和切换。
期待效果:既可以对图片进行预览、缩放、拖拽,又可以切换不同图片进行预览。
实际效果:只能对图片进行预览、缩放、拖拽,无法切换不同的图片进行预览。
问题代码如下:
// 单手指动作,移动图片PanGesture({ fingers: 1 })
.onActionUpdate((event: GestureEvent) => {
if (this.imageScaleInfo.scaleValue === this.imageScaleInfo.defaultScaleValue) {
// 默认大小下不允许移动
return true;
}
// 修改坐标轴位置
this.imageOffsetInfo.currentX = this.imageOffsetInfo.lastX + event.offsetX;
this.imageOffsetInfo.currentY = this.imageOffsetInfo.lastY + event.offsetY;
return false;
})
.onActionEnd((event: GestureEvent) => {
// 设置图片大小值
this.imageOffsetInfo.stash();
})
【背景知识】
Swiper官方文档链接:滑块视图容器,提供子组件滑动轮播显示的能力。
TapGesture官方文档链接:支持单击、双击和多次点击事件的识别。
【定位思路】
单手指事件会对图片进行位置的移动,跟Swiper组件滑动发生冲突。因此,只需要把单手指的事件取消掉,就可以实现Swiper组件滑动来切换图片。
【解决方案】
根据以上分析,解决方案如下:
-
取消掉Swiper组件下的缩放效果,即把关于手势事件的问题代码都删除掉,只保留原始的切换图片效果。在点击图片时,进入一个新的图片预览页面,在预览页面添加手势事件的代码,进行图片的缩放和拖拽操作。
-
当预览结束后,返回到可以滑动切换图片的页面。
图片缩放及预览解决方案如下:
1. 双击切换图片大小
代码示例如下:
TapGesture({ count: 2 })
.onAction(() => {
let fn: Function;
// 已经是放大状态下,双击缩小
if (this.imageScaleInfo.scaleValue > this.imageScaleInfo.defaultScaleValue) {
fn = () => {
this.isEnableSwipe = true;
// 修改图片大小到初始值
this.imageScaleInfo.reset();
// 修改图片偏移量到初始值
this.imageOffsetInfo.reset();
this.matrix = matrix4.identity().copy();
};
} else {
// 已经是缩小状态,双击放大
fn = () => {
this.isEnableSwipe = false;
// 根据图片初始大小和屏幕的大小计算缩放比例的值
const ratio: number = this.calcFitScaleRatio(this.imageDefaultSize, windowSizeManager.get());
// 通过计算出来的缩放比例来对图片进行放大
this.imageScaleInfo.scaleValue = ratio;
// 修改图片偏移量到初始值
this.imageOffsetInfo.reset();
this.matrix = matrix4.identity().scale({
x: ratio,
y: ratio,
}).copy();
this.imageScaleInfo.stash();
}
}
runWithAnimation(fn);
})
2. 双指捏合缩放图片
代码示例如下:
PinchGesture({ fingers: 2, distance: 1 })
.onActionUpdate((event: GestureEvent) => {
// 根据双指捏合事件捕捉到的缩放值,进行图片尺寸的重新计算
this.imageScaleInfo.scaleValue = this.imageScaleInfo.lastValue * event.scale;
// 缩放时不允许大于最大缩放因子+额外缩放因子,不允许小于默认大小-额外缩放因子,额外缩放因子用于提升用户体验
if (this.imageScaleInfo.scaleValue > this.imageScaleInfo.maxScaleValue *
(1 + this.imageScaleInfo.extraScaleValue)
) {
this.imageScaleInfo.scaleValue = this.imageScaleInfo.maxScaleValue *
(1 + this.imageScaleInfo.extraScaleValue);
}
if (this.imageScaleInfo.scaleValue < this.imageScaleInfo.defaultScaleValue *
(1 - this.imageScaleInfo.extraScaleValue)) {
this.imageScaleInfo.scaleValue = this.imageScaleInfo.defaultScaleValue *
(1 - this.imageScaleInfo.extraScaleValue);
}
// matrix默认缩放中心为组件中心
this.matrix = matrix4.identity().scale({
x: this.imageScaleInfo.scaleValue,
y: this.imageScaleInfo.scaleValue,
}).copy();
console.debug(this.imageScaleInfo.toString());
})
// 缩放事件结束,对特殊情况进行判断后,根据计算出来的新的尺寸值,对图片的重新渲染
.onActionEnd((event: GestureEvent) => {
/**
* 当小于默认大小时,恢复为默认大小
*/
if (this.imageScaleInfo.scaleValue < this.imageScaleInfo.defaultScaleValue) {
runWithAnimation(() => {
// 修改图片大小到初始值
this.imageScaleInfo.reset();
// 修改图片偏移量到初始值
this.imageOffsetInfo.reset();
this.matrix = matrix4.identity().copy();
})
}
// 当大于最大缩放因子时,恢复到最大
if (this.imageScaleInfo.scaleValue > this.imageScaleInfo.maxScaleValue) {
runWithAnimation(() => {
this.imageScaleInfo.scaleValue = this.imageScaleInfo.maxScaleValue;
this.matrix = matrix4.identity()
.scale({
x: this.imageScaleInfo.maxScaleValue,
y: this.imageScaleInfo.maxScaleValue
});
})
}
// 根据新计算出来的图片大小值来重新渲染图片
this.imageScaleInfo.stash();
})
3. 单手指拖拽图片至指定位置预览
代码示例如下:
PanGesture({ fingers: 1 })
.onActionUpdate((event: GestureEvent) => {
console.info("event", JSON.stringify(event))
// 根据事件捕捉到的坐标轴值来修改图片的坐标,实现拖动图片的效果
this.imageOffsetInfo.currentX = this.imageOffsetInfo.lastX + event.offsetX;
this.imageOffsetInfo.currentY = this.imageOffsetInfo.lastY + event.offsetY;
return false;
})
.onActionEnd((event: GestureEvent) => {
// 根据新的坐标轴来渲染图片的位置
this.imageOffsetInfo.stash();
})
更多关于HarmonyOS鸿蒙Next中手势拖拽时和Swiper组件滑动发生冲突如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中手势拖拽时和Swiper组件滑动发生冲突如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
取消Swiper组件下的手势事件代码,保留原始切换图片效果。在进入图片预览页面时,添加手势事件代码实现缩放和拖拽。预览结束后返回可切换图片的页面。