swiper + image 捏合放大缩小与滑动出现冲突 在 HarmonyOS 鸿蒙Next

发布于 1周前 作者 gougou168 来自 鸿蒙OS

swiper + image 捏合放大缩小与滑动出现冲突 在 HarmonyOS 鸿蒙Next 期望达到的效果:在水平滑动的情况下swiper 进行滑动操作,屏蔽图片手势;当手势为捏合时,屏蔽swiper,进行图片缩放操作。目前处理手势问题,关于手势拦截的,大佬们指点一二

9 回复

不推荐使用Swiper进行图片缩放,会有手势冲突,可以参考我的三方库:ImagePreview: 基于ArkUI的HarmonyOS图片预览器,支持丝滑的缩放和拖动,并提供丰富的回调供用户使用。

其中使用List作为根容器

更多关于swiper + image 捏合放大缩小与滑动出现冲突 在 HarmonyOS 鸿蒙Next的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


标题

这是段落文字。

子标题

这是另一段落文字。

你这个有个问题,不能指定滑动到某一张图显示,

可以的,readme 里面有对相应功能的描述,

你好,请参考如下demo: 在index.ets中:

import display from '@ohos.display';
import { GalleryImage } from './GalleryImage';

@Entry
@Component
export struct PreviewImagePage2 {
@State content: string = '';
private swiperController: SwiperController = new SwiperController()
private data: MyDataSource = new MyDataSource([])
@State disableSwipe: boolean = false;

aboutToAppear(): void {
console.info("屏幕宽度:" + display.getDefaultDisplaySync().width)
let list: string[] = [
"https://images.dog.ceo/breeds/terrier-sealyham/n02095889_4899.jpg",
"https://images.dog.ceo/breeds/pug/n02110958_340.jpg",
"https://images.dog.ceo/breeds/pembroke/n02113023_1198.jpg",
"https://images.dog.ceo/breeds/wolfhound-irish/n02090721_1696.jpg",
"https://images.dog.ceo/breeds/chihuahua/n02085620_4951.jpg",
"https://images.dog.ceo/breeds/hound-basset/n02088238_10063.jpg",
"https://images.dog.ceo/breeds/shiba/shiba_20.jpg"
]
this.data = new MyDataSource(list);
}

build() {
Column() {
Swiper(this.swiperController) {
LazyForEach(this.data, (item: string, index: number) => {
GalleryImage({ url: item, index: index, isScaling: this.disableSwipe })
},
(index: number, item: string) => index + "__" + item)
}
.disableSwipe(this.disableSwipe)
.cachedCount(1)
.indicator(true)
.loop(false)
.duration(200)
.curve(Curve.Linear)
.effectMode(EdgeEffect.None)
.indicator(Indicator.digit()
.right("43%")
.bottom(20)
.fontColor(Color.White)
.selectedFontColor(Color.White)
.digitFont({ size: 14, weight: FontWeight.Normal })
.selectedDigitFont({ size: 14, weight: FontWeight.Normal })
)
.onChange((index: number) => {
console.info(index.toString())
})

Row({ space: 12 }) {
Button('showNext')
.onClick(() => {
this.swiperController.showNext()
})
Button('showPrevious')
.onClick(() => {
this.swiperController.showPrevious()
})
}.margin(5).position({ x: 20, y: px2vp(display.getDefaultDisplaySync().height) - 100 })
}
.width('100%')
.height('100%')
.backgroundColor("#000000")
}
}

class MyDataSource implements IDataSource {
private list: string[] = []

// private listener: DataChangeListener

constructor(list: string[]) {
this.list = list
}

totalCount(): number {
return this.list.length
}

getData(index: number): string {
return this.list[index]
}

getList(): string[] {
return this.list;
}

registerDataChangeListener(listener: DataChangeListener): void {
// this.listener = listener
}

unregisterDataChangeListener() {}
}

再GalleryImage.ets中:

import display from '@ohos.display';

@Component
export struct GalleryImage {
private url: string = "";
private index: number = 0;
@State downLoadEnable: boolean = true;
@Link isScaling: boolean
@State showLoading: boolean = false;
@State rotateAngle: number = 0;
@State showError: boolean = false;
@State scaleValue: number = 1;
@State pinchValue: number = 1;
@State pinchX: number | string = '50%';
@State pinchY: number | string = '50%';
private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.None, fingers: 1 })
@State offsetX: number = 0
@State offsetY: number = 0
@State positionX: number = 0
@State positionY: number = 0
private imageWith: number = 0;
@State sizeValue: number = 0;

aboutToAppear(): void {
this.showLoading = true;
this.downLoadEnable = false;
console.info("");
}

aboutToDisAppear(): void {
console.info("");
}

aboutToReuse(): void {
console.info("");
}

build() {
Column() {
Image(this.url)
.width('100%')
.height("100%")
.objectFit(ImageFit.Contain)//todo 加载失败时占位图没隐藏
.alt($r("app.media.startIcon"))
.onComplete(msg => {
if (msg) {
console.info("index:" + this.index + ", loadingStatus:" + msg.loadingStatus)
// 图片数据加载成功
if (msg.loadingStatus === 0) {
this.showLoading = true;
this.downLoadEnable = false;
} else if (msg.loadingStatus === 1) {
// 图片数据解码成功
this.showLoading = false;
this.downLoadEnable = true;
this.imageWith = px2vp(display.getDefaultDisplaySync().width)
}
}
})
.onError(() => {
console.info("图片加载异常")
this.showLoading = false;
this.showError = true;
})// 在组件上绑定缩放比例,可以通过修改缩放比例来实现组件的缩小或者放大
.scale({
x: this.scaleValue,
y: this.scaleValue,
z: 1,
centerX: this.pinchX,
centerY: this.pinchY
})// 以组件左上角为坐标原点进行移动
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.gesture(
GestureGroup(GestureMode.Parallel,
// 两指或以上的捏合手势
PinchGesture({ fingers: 2 })
.onActionStart(() => {
console.info('Pinch start');
})// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例
.onActionUpdate(event => {
const scaleValue = this.pinchValue * event.scale;
if (scaleValue <= 3 && scaleValue >= 0.8) {
this.scaleValue = scaleValue;
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
}
})
.onActionEnd(() => {
this.pinchValue = this.scaleValue;
console.info('Pinch end');
if (this.pinchValue > 1) {
this.panOption.setDirection(PanDirection.Horizontal)
this.isScaling = true;
} else {
this.panOption.setDirection(PanDirection.None)
this.isScaling = false;
}
}),
// 绑定count为1的TapGesture
TapGesture({ count: 1 })
.onAction(() => {
}),
// 绑定count为2的TapGesture
TapGesture({ count: 2 })
.onAction(() => {
animateTo({
duration: 400,
}, () => {
this.scaleValue = 1;
this.pinchX = '50%';
this.pinchY = '50%';
this.pinchValue = this.scaleValue;
this.offsetX = 0;
this.offsetY = 0;
this.positionX = 0;
this.positionY = 0;
this.panOption.setDirection(PanDirection.None);
this.isScaling = false;
})
}),
PanGesture(this.panOption)
.onActionStart(() => {
console.info('Pan start')
})
.onActionUpdate(event => {
if (event) {
if (this.scaleValue > 1) {
this.offsetX = this.positionX + event.offsetX
this.offsetY = this.positionY + event.offsetY
this.sizeValue = this.imageWith
}
}
})
.onActionEnd(() => {
this.positionX = this.offsetX
this.positionY = this.offsetY
console.info('Pan end')
})
)
)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

这份代码是将swiper屏蔽了吗,我的意思是想让swiper能滑动图片,Image也能手势缩放图片,目前在Image加上了

试着使用priorityGesture、parallelGesture

在 HarmonyOS 鸿蒙 Next 中,当你使用 swiper 组件结合 image 组件实现捏合放大缩小与滑动功能时,可能会出现冲突。这通常是因为 swiper 组件默认处理滑动事件,而捏合手势(缩放)与滑动手势在事件处理上存在竞争。

为了解决这个问题,你可以尝试以下方法:

  1. 自定义事件处理:为 image 组件添加自定义的手势识别逻辑,通过监听触摸事件(如 onTouchStartonTouchMoveonTouchEnd)来判断用户是在进行捏合缩放还是滑动。根据判断结果,动态调整 swiper 的滑动响应。

  2. 使用第三方库:寻找支持复杂手势处理的第三方库,这些库通常提供了更灵活的手势识别和处理机制,可以帮助你更好地协调捏合缩放与滑动功能。

  3. 调整 swiper 组件属性:检查 swiper 组件是否有相关属性可以调整其手势响应的优先级或灵敏度,以便与捏合缩放手势更好地兼容。

  4. 分层处理:考虑将 swiperimage 组件分层处理,例如,在 swiper 外层再包裹一个容器,并在该容器上处理捏合缩放手势,而将滑动手势留给 swiper 处理。

如果问题依旧没法解决请联系官网客服, 官网地址是 https://www.itying.com/category-93-b0.html

回到顶部