代码拉取完成,页面将自动刷新
最近为了实现皇室战争主页中嵌套滑动,在PageView中嵌入ScrollView,发现在ScrollView区域内拖拽UI,无法滑动PageView。原来是creator默认不支持嵌套滑动,这里尝试解决它。
先来看下源码就会发现每一个处理触摸的函数最开始都有这两行代码
// touch event handler
_onTouchBegan (event, captureListeners) {
if (!this.enabledInHierarchy) return;
if (this._hasNestedViewGroup(event, captureListeners)) return;
...
},
_onTouchMoved (event, captureListeners) {
if (!this.enabledInHierarchy) return;
if (this._hasNestedViewGroup(event, captureListeners)) return;
...
},
_onTouchEnded (event, captureListeners) {
if (!this.enabledInHierarchy) return;
if (this._hasNestedViewGroup(event, captureListeners)) return;
...
},
_onTouchCancelled (event, captureListeners) {
if (!this.enabledInHierarchy) return;
if (this._hasNestedViewGroup(event, captureListeners)) return;
...
},
分析代码后,就可以知道不能嵌套的原因就在这个_hasNestedViewGroup函数里面
//this is for nested scrollview
_hasNestedViewGroup (event, captureListeners) {
if (event.eventPhase !== cc.Event.CAPTURING_PHASE) return;
if (captureListeners) {
//captureListeners are arranged from child to parent
for (let i = 0; i < captureListeners.length; ++i){
let item = captureListeners[i];
if (this.node === item) {
if (event.target.getComponent(cc.ViewGroup)) {
return true;
}
return false;
}
if(item.getComponent(cc.ViewGroup)) {
return true;
}
}
}
return false;
},
原因就出在
if (event.target.getComponent(cc.ViewGroup)) {
return true;
}
如果event.target的组件中不包含cc.ViewGroup,就可以解决这个问题。
很多小伙伴的做法很可能都是继承ScrollView/PageView,重写一个ScrollView/PageView来解决嵌套滑动问题。
这里借鉴论坛中“向前”大大的方法,不用这种继承ScrollView/PageView的侵入式方案,可以手动发射一个假事件,让它不会被_hasNestedViewGroup过滤掉,并且我们的目标是让它成为一个单独的组件
代码不多,直接上原吗
const { ccclass, property } = cc._decorator;
interface EventTouch extends cc.Event.EventTouch {
simulate?: boolean
sham?: boolean
}
@ccclass
export default class ViewGroupNesting extends cc.Component {
private events: EventTouch[] = [];
onLoad() {
this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchHandle, this, true);
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchHandle, this, true);
this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchHandle, this, true);
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchHandle, this, true);
}
private onTouchHandle(event: EventTouch) {
if (event.sham || event.simulate || event.target === this.node) return;
const cancelEvent: EventTouch = new cc.Event.EventTouch(event.getTouches(), event.bubbles);
cancelEvent.type = event.type;
cancelEvent.touch = event.touch;
cancelEvent.sham = true;
// 问:这里为啥不直接dispatchEvent
// 答:必须让ScrollView把真的event先消耗掉,我们再发射假的才可以,
// 可以去CCNode.js下找一个_doDispatchEvent函数,里面用到了_cachedArray这么个全局变量,
// 先发射假的话,真的那个数据就被清空了
this.events.push(cancelEvent);
}
update() {
if (this.events.length === 0) return;
for (let index = 0; index < this.events.length; index++) {
this.node.dispatchEvent(this.events[index]);
}
this.events.length = 0;
}
}
如此,就实现了PageView/ScrollView的嵌套滑动,具体效果就不贴出图了,有兴趣的小伙伴可以自己去试下。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。