1 Star 0 Fork 16

tony / ScrollViewNesting

forked from 向前 / ScrollViewNesting 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

ScrollView/PageView嵌套方案。

基于CocosCreator2.4.x

最近在群和论坛里发现不少ScrollView/PageView嵌套需求的小伙伴,但是Creator默认不支,我们尝试解决它。

一、分析原因


看一下源码就会发现每一个处理触摸(滚轮的就不管了)的函数最开始都有这两行

_onTouchBegan(event, captureListeners) {
    if (!this.enabledInHierarchy) return;
    if (this._hasNestedViewGroup(event, captureListeners)) return;
    ...
}

不能嵌套的原因就在这个_hasNestedViewGroup函数里面

...
if (event.target.getComponent(cc.ViewGroup)) {
    return true;
}
...

二、解决问题


这个时候大部分小伙伴的做法可能都是继承ScrollView或PageView,然后重写一部分方法来解决嵌套的问题。

但是我们这里尝试换一个角度,比如我们手动发射一个假事件,让它不会被_hasNestedViewGroup过滤掉,并且我们的目标是让它成为一个单独的组件。


代码不多,直接上源码(新鲜出炉,未测BUG)

demo项目地址:https://gitee.com/cocos2d-zp/scrollview-nesting

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;
    }
}

空文件

简介

ScrollView/PageView嵌套演示 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/tonyshow/scrollview-nesting.git
git@gitee.com:tonyshow/scrollview-nesting.git
tonyshow
scrollview-nesting
ScrollViewNesting
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891