HarmonyOS Tabs嵌套TabContent内部嵌套一个可拖动的组件导致冲突
这边使用Tabs组件嵌套两个TabContent页面,第一个TabContent页面内嵌套了一个可随意拖动的组件。
拖动FloatWindowView这个组件时,会触发TabContent左右滑动,导致了滑动冲突。在onTouchEvent事件内调用了event.stopPropagation(),好像并没有拦截成功。或者有没有其他办法可以解决此冲突?以下是demo代码:
import { FloatWindowView } from './FloatWindowView';
@Entry
@Component
struct Index {
// 父组件宽度
@State containerWidth: number = 0;
// 父组件高度
@State containerHeight: number = 0;
array?: Array<string> = new Array
aboutToAppear(): void {
this.array?.push('page1')
this.array?.push('page2')
}
build() {
Stack() {
Tabs() {
ForEach(this.array, (item: string, index) => {
// 模拟两个页面
TabContent() {
// 第一个
if (index == 0) {
Stack() {
List().width('100%')
.height('100%')
.backgroundColor(Color.Gray)
FloatWindowView({
containerWidth: this.containerWidth, containerHeight: this.containerHeight,
initPositionX: 0, initPositionY: 300,
})
}
} else {
// 第二个
List().width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
}
.tabBar(item)
.onAreaChange((oldValue: Area, newValue: Area) => {
console.log('test55 父级onAreaChange ')
})
}, (item: string) => JSON.stringify(item))
}
}
.height('100%')
.width('100%')
.onAreaChange((oldValue: Area, newValue: Area) => {
// TODO:onAreaChange是高频回调,仅在父组件尺寸改变时获取新的父组件宽高,避免性能损耗
if (oldValue.width !== newValue.width) {
this.containerWidth = newValue.width as number;
}
if (oldValue.height !== newValue.height) {
this.containerHeight = newValue.height as number;
}
})
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
import { curves, display } from '@kit.ArkUI';
@Component
export struct FloatWindowView {
// 悬浮窗相对于父组件四条边的距离,top和bottom同时设置时top生效,right和left同时设置时left生效
@State edge: Edges = null!!;
@Link containerWidth: number;
@Link containerHeight: number;
// 拖拽移动开始时悬浮窗在窗口中的坐标,每次移动回调触发时更新
private windowStartX: number = 0;
private windowStartY: number = 0;
openAdsorb: boolean = true
@Prop PAGE_PADDING: number = 0; // 页面内容内边距,用于悬浮窗位置计算
@Prop FLOAT_WINDOW_WIDTH: number = 100; // 悬浮窗宽度
@Prop FLOAT_WINDOW_HEIGHT: number = 30; // 悬浮窗高度
@Prop initPositionY: number = 300; // 悬浮窗相对父容器左上角的Y坐标初始值
@Prop initPositionX: number = 0; // 悬浮窗相对父容器左上角的X坐标初始值
aboutToAppear(): void {
this.edge = { top: this.initPositionY, right: this.initPositionX }
}
/**
* 触摸回调,悬浮窗跟手和贴边动画
*/
onTouchEvent(event: TouchEvent): void {
switch (event.type) {
case TouchType.Down: {
// 获取拖拽开始时悬浮窗在窗口中的坐标
this.windowStartX = event.touches[0].windowX;
this.windowStartY = event.touches[0].windowY;
AppStorage.set('childScrolling', true)
console.log('test551: 子的touch')
break;
}
case TouchType.Move: {
const windowX: number = event.touches[0].windowX;
const windowY: number = event.touches[0].windowY;
// TODO:知识点:跟手动画,推荐使用默认参数的弹性跟手动画曲线curves.responsiveSpringMotion。
animateTo({ curve: curves.responsiveSpringMotion() }, () => {
// 判断当前edge中属性left和right哪个不为undefined,用于控制悬浮窗水平方向的位置
if (this.edge.left !== undefined) {
this.edge.left = this.edge.left as number + (windowX - this.windowStartX);
} else {
this.edge.right = this.edge.right as number - (windowX - this.windowStartX);
}
this.edge.top = this.edge.top as number + (windowY - this.windowStartY);
this.windowStartX = windowX;
this.windowStartY = windowY;
})
break;
}
case TouchType.Up: {
console.log('test551: 子的touch up')
// 计算悬浮窗中心点在父组件中水平方向的坐标
let centerX: number;
if (this.edge.left !== undefined) {
centerX = this.edge.left as number + this.FLOAT_WINDOW_WIDTH / 2;
} else {
centerX = this.containerWidth - (this.edge.right as number) - this.FLOAT_WINDOW_WIDTH / 2;
}
// TODO:通过判断悬浮窗在父组件中的位置,设置悬浮窗贴边,使用curves.springMotion()弹性动画曲线,可以实现阻尼动画效果
animateTo({ curve: curves.springMotion() }, () => {
// 判断悬浮窗中心在水平方向是否超过父组件宽度的一半,根据结果设置靠左或靠右
if (this.edge.top as number < this.PAGE_PADDING) {
this.edge.top = this.PAGE_PADDING;
} else if (this.edge.top as number >
this.containerHeight - this.FLOAT_WINDOW_HEIGHT - this.PAGE_PADDING) {
this.edge.top = this.containerHeight - this.FLOAT_WINDOW_HEIGHT - this.PAGE_PADDING;
}
let width = px2vp(display.getDefaultDisplaySync().width)
if (this.openAdsorb) {
if (centerX > (this.containerWidth / 2)) {
this.edge.right = this.PAGE_PADDING;
this.edge.left = undefined;
this.currentAdsorbLeft = false
} else {
this.edge.right = undefined;
this.edge.left = this.PAGE_PADDING;
this.currentAdsorbLeft = true
}
} else {
// 是否超出了左侧屏幕
let overflowLeft = this.edge.right! > width - this.FLOAT_WINDOW_WIDTH
// 是否超出了右侧屏幕
let overflowRight = this.edge.right! < 0
if (overflowLeft) { // 超出左边屏幕了
this.edge.left = undefined;
this.edge.right = width - this.FLOAT_WINDOW_WIDTH;
} else if (overflowRight) { // 超出右边屏幕了
this.edge.right = this.PAGE_PADDING;
this.edge.left = undefined;
}
}
AppStorage.set('childScrolling', false)
})
break;
}
default: {
break;
}
}
// 停止向父级传递事件
event.stopPropagation()
}
@State currentAdsorbLeft?: boolean = false
build() {
Row() {
}
.backgroundColor(Color.Pink)
.width(this.FLOAT_WINDOW_WIDTH)
.height(this.FLOAT_WINDOW_HEIGHT)
.position(this.edge)
.onTouch((event: TouchEvent) => {
this.onTouchEvent(event);
})
.onClick(() => {
})
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
HarmonyOS
赞
收藏 0
回答 1
相关问题
HarmonyOS Tabs组件嵌套Web组件,导致横向滑动冲突
691浏览 • 1回复 待解决
HarmonyOS 可滑动组件嵌套后内部的可滑动组件无法监听滑动
793浏览 • 1回复 待解决
JS如可开发一个可横向拖动的表格
7293浏览 • 1回复 待解决
HarmonyOS Tabs组件嵌套Tabs组件问题
1739浏览 • 1回复 待解决
HarmonyOS Tabs组件嵌套滑动
1166浏览 • 1回复 待解决
Tabs组件嵌套滑动组件
2418浏览 • 1回复 待解决
HarmonyOS Scroll容器内部嵌套2个Waterflow组件,滑动条嵌套设置不生效
798浏览 • 1回复 待解决
HarmonyOS 嵌套滚动冲突
869浏览 • 1回复 待解决
HarmonyOS Refresh组件嵌套滑动冲突问题
1920浏览 • 1回复 待解决
HarmonyOS list嵌套tabs,tabs嵌套web,滑动问题
996浏览 • 1回复 待解决
HarmonyOS 多一个自定义的tabs冲突
955浏览 • 1回复 待解决
scroll中嵌套一个或多个grid,如何实现嵌套滚动?
3371浏览 • 1回复 待解决
HarmonyOS Scroll中嵌套一个自定义TabBar的Tabs,如何实现吸顶
598浏览 • 1回复 待解决
滑动嵌套事件冲突处理
1025浏览 • 0回复 待解决
HarmonyOS list嵌套MapComponent滑动冲突
588浏览 • 1回复 待解决
HarmonyOS Scroll嵌套web手势冲突
683浏览 • 1回复 待解决
HarmonyOS Tabs嵌套使用问题
639浏览 • 1回复 待解决
HarmonyOS Tabs嵌套Grid问题
739浏览 • 1回复 待解决
HarmonyOS waterFlow里面是否可以嵌套一个横向滑动的list
885浏览 • 1回复 待解决
HarmonyOS ListItem嵌套Tabs显示不全
636浏览 • 1回复 待解决
由UIAbility创建的一个子窗口,能配置为可拖动吗
2162浏览 • 1回复 待解决
HarmonyOS Tabs以及嵌套Tabs生命周期的支持
876浏览 • 1回复 待解决
Web和List嵌套手势冲突问题
1684浏览 • 1回复 待解决
HarmonyOS Scroll中嵌套List滑动事件冲突
816浏览 • 1回复 待解决
可以通过给tabs添加scrollable,通过true或false来控制tabs是否可滑动,通过FloatWindowView中的触摸事件和手抬起事件来控制
示例demo如下: