cocoscreator 怎么实现同时左右翻页和上下滚动 就像皇室战争的UI界面一样

pageview和 scrollBar并不能同时使用吗 这两天搞的头大

我用的是ts脚本 有大佬告诉我怎么实现吗

根据触摸移动y轴和x轴的位移,哪个先到达滑动触发值,则触发那个方向的滑动
两种方法:
一、自己写触摸滑动,难点是按钮点击事件和滑动事件冲突,需要自己解决
二、修改现有scrollView,加上滑动位移判断,修改scrollView嵌套滑动
附 192版本
`var NUMBER_OF_GATHERED_TOUCHES_FOR_MOVE_SPEED = 5;
var OUT_OF_BOUNDARY_BREAKING_FACTOR = 0.05;
var EPSILON = 1e-4;
var MOVEMENT_FACTOR = 0.7;

var quintEaseOut = function(time) {
time -= 1;
return (time * time * time * time * time + 1);
};

var getTimeInMilliseconds = function() {
var currentTime = new Date();
return currentTime.getMilliseconds();
};
var quintEaseOut = function(time) {
time -= 1;
return (time * time * time * time * time + 1);
};

cc.Class({
extends: cc.ScrollView,

editor: CC_EDITOR && {
    menu: 'i18n:MAIN_MENU.component.ui/ScrollView',
    help: 'i18n:COMPONENT.help_url.scrollview',
    executeInEditMode: false,
},

properties: {
   isMoveLocked: true, // 控制滑动是否解锁
   isPageView: false, // 控制滑动是否按cell落点
   cellWidth: 0, // cell 宽
   cellHeight: 0, // cell 高
   touchPageStartCallback: null,
    touchPageMovedCallback: null,
    touchPageEndCallback: null,
    touchPageCancelledCallback: null,
    controlPosX: 30, // 控制启动x轴滑动临界点
    controlPosY: 15, // 控制启动y轴滑动临界点
},

setPageTouchCallback(touchStart, touchMoved, touchEnd, touchCancelled) {
    this.touchPageStartCallback = touchStart;
    this.touchPageMovedCallback = touchMoved;
    this.touchPageEndCallback = touchEnd;
    this.touchPageCancelledCallback = touchCancelled;
},

setControlPos(x, y) {
    this.controlPosX = x;
    this.controlPosY = y;
},

//this is for nested scrollview
_hasNestedViewGroup: function (event, captureListeners) {
    // if(event.eventPhase !== cc.Event.CAPTURING_PHASE) return;

    if (!this.isMoveLocked) {
        return false;
    }
    // 修改当触摸 scrollView 滑动时,也要检测 是否有嵌套滑动
    if (event.eventPhase !== cc.Event.CAPTURING_PHASE && event.target === this.node && !captureListeners) {
        captureListeners = [];
        event.target._getCapturingTargets(event.type, captureListeners);
    }

    if(captureListeners) {
        //captureListeners are arranged from child to parent
        for(var i = 0; i < captureListeners.length; ++i){
            var item = captureListeners[i];
            if(this.node === item) {
                if (event.target.getComponent(cc.ViewGroup) && !event.target.getComponent(cc.ViewGroup).isMoveLocked){
                    return true;
                }
            }

            if(this.node !== item) {
                if(item.getComponent(cc.ViewGroup)) {
                    if (!item.getComponent(cc.ViewGroup).isMoveLocked) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
},

// 修改原方法, isMoveLocked 控制滑动是否解锁
_handleMoveLogic: function(touch) {
    if (this.isMoveLocked)
    {
       return; 
    }
    var deltaMove = touch.getDelta();
    this._processDeltaMove(deltaMove);
},

// 修改原方法, isMoveLocked 控制滑动是否解锁
_handleReleaseLogic: function(touch) {
    if (this.isMoveLocked)
    {
       return; 
    }
    
    var delta = touch.getDelta();
    this._gatherTouchMove(delta);
    this._processInertiaScroll();

    if (this._scrolling) {
        this._scrolling = false;
        if (!this._autoScrolling) {
            this._dispatchEvent('scroll-ended');
        }
    }
},

// 修改原方法, 去掉 touchMoveVelocity 与 cc.p(0,0) 的判断
_processInertiaScroll: function () {
    var bounceBackStarted = this._startBounceBackIfNeeded();
    if (!bounceBackStarted && this.inertia) {
        var touchMoveVelocity = this._calculateTouchMoveVelocity();
        if (this.brake < 1) {
            this._startInertiaScroll(touchMoveVelocity);
        }
    }

    this._onScrollBarTouchEnded();
},

// 修改原方法,达到滑动按照cell落点
_startAutoScroll: function(deltaMove, timeInSecond, attenuated) {
    var adjustedDeltaMove = this._flattenVectorByDirection(deltaMove);

    this._autoScrolling = true;
    this._autoScrollTargetDelta = adjustedDeltaMove;
    this._autoScrollAttenuate = attenuated;
    this._autoScrollStartPosition = this.getContentPosition();
    this._autoScrollTotalTime = timeInSecond;
    this._autoScrollAccumulatedTime = 0;
    this._autoScrollBraking = false;
    this._isScrollEndedWithThresholdEventFired = false;
    this._autoScrollBrakingStartPosition = cc.p(0, 0);
    // 通过修改 滑动距离和滑动时间,控制 content 最终滑动停止位置
    if (this.isPageView && this.vertical && (this.content.y > 0 && this.content.y < this.content.getContentSize().height - this.node.getContentSize().height) ) {
        let tempDiff = this.cellHeight;
        if(this._autoScrollTargetDelta.y + this.content.y >= this.content.getContentSize().height - this.node.getContentSize().height || 
            this._autoScrollTargetDelta.y + this.content.y < 0) {
            // 超越 content 滑动范围时,不做操作
        } else if (Math.abs(this._autoScrollTargetDelta.y) <= tempDiff) {
            // 滑动距离小于等于cell height 时,做回弹处理
            let halfDiff = (this.content.y * 1.0) % tempDiff ;
            if(halfDiff > tempDiff / 2 )
            {
                    this._autoScrollTargetDelta.y = tempDiff - halfDiff;
            }
            else
            {
                    this._autoScrollTargetDelta.y = -halfDiff;
            }
            this._autoScrollTotalTime = 0.2;
        } else if ( Math.abs(this._autoScrollTargetDelta.y) > tempDiff ) {
            // 滑动距离大于cell height 时,修改滑动距离,以适应 按cell落点
            let targetPosY = this.content.y + this._autoScrollTargetDelta.y;
            let halfDiff = targetPosY * 1.0 % tempDiff;
            if(halfDiff > tempDiff / 2 )
            {
                    this._autoScrollTargetDelta.y = this._autoScrollTargetDelta.y + tempDiff - halfDiff;
            }
            else
            {
                    this._autoScrollTargetDelta.y =  this._autoScrollTargetDelta.y - halfDiff;
            }
            if (this._autoScrollTotalTime > 0.8) {
                this._autoScrollTotalTime = 0.8;
            }
        }
    } else if (this.isPageView && this.horizontal && (this.content.x < 0 && this.content.x > this.node.getContentSize().width - this.content.getContentSize().width)) {
        let tempDiff = this.cellWidth;
        if(this._autoScrollTargetDelta.x + this.content.x < this.node.getContentSize().width - this.content.getContentSize().width || 
            this._autoScrollTargetDelta.x + this.content.x > 0) {
            // 超越 content 滑动范围时,不做操作
        } else if (Math.abs(this._autoScrollTargetDelta.x) <= tempDiff) {
            // 滑动距离小于等于cell width 时,做回弹处理
            let halfDiff = Math.abs(this.content.x) * 1.0 % tempDiff ;
            if(halfDiff > tempDiff / 2 )
            {
                    this._autoScrollTargetDelta.x = -(tempDiff - halfDiff);
            }
            else
            {
                    this._autoScrollTargetDelta.x = halfDiff;
            }
            this._autoScrollTotalTime = 0.2;
        } else if ( Math.abs(this._autoScrollTargetDelta.x) > tempDiff ) {
            // 滑动距离大于cell width 时,修改滑动距离,以适应 按cell落点
            let targetPosX = this.content.x + this._autoScrollTargetDelta.x;
            let halfDiff = Math.abs(targetPosX) * 1.0 % tempDiff;
            if(halfDiff > tempDiff / 2 )
            {
                    this._autoScrollTargetDelta.x = this._autoScrollTargetDelta.x - tempDiff + halfDiff;
            }
            else
            {
                    this._autoScrollTargetDelta.x =  this._autoScrollTargetDelta.x + halfDiff;
            }
        }
    }

    var currentOutOfBoundary = this._getHowMuchOutOfBoundary();
    if (!cc.pFuzzyEqual(currentOutOfBoundary, cc.p(0, 0), EPSILON)) {
        this._autoScrollCurrentlyOutOfBoundary = true;
        var afterOutOfBoundary = this._getHowMuchOutOfBoundary(adjustedDeltaMove);
        if (currentOutOfBoundary.x * afterOutOfBoundary.x > 0 ||
            currentOutOfBoundary.y * afterOutOfBoundary.y > 0) {
            this._autoScrollBraking = true;
        }
    }

},

_checkMoveLocked(event) {
    var touch = event.touch;
    if(!touch) return;
    if(!this.isMoveLocked) return;
    var deltaMove = cc.pSub(touch.getLocation(), touch.getStartLocation());
    if (this.vertical && this.content.height >= this.node.height) {
        if (Math.abs(deltaMove.y) >= this.controlPosY * cc.view.getScaleY()) {
            this.isMoveLocked = false;
        }
    }
    if (this.horizontal && this.content.width >= this.node.width) {
        if (Math.abs(deltaMove.x) >= this.controlPosX * cc.view.getScaleX()) {
            this.isMoveLocked = false;
        }
    }
},

// touch event handler
_onTouchBegan: function(event, captureListeners) {
    if (!this.enabledInHierarchy) return;
    if (this._hasNestedViewGroup(event, captureListeners)) return;

    var touch = event.touch;
    if (this.content) {
        this._handlePressLogic(touch);
        if (this.touchPageStartCallback) {
            this.touchPageStartCallback(event);
        }
    }
    this._touchMoved = false;
    this.isMoveLocked = true;
    this._stopPropagationIfTargetIsMe(event);
},

_onTouchMoved: function(event, captureListeners) {
    if (!this.enabledInHierarchy) return;
    if (this._hasNestedViewGroup(event, captureListeners)) return;

    this._checkMoveLocked(event);

    var touch = event.touch;
    if (this.content) {
        if (this.touchPageMovedCallback && !this.isMoveLocked) { // 当isMoveLocked为true时不做移动操作
            this.touchPageMovedCallback(event);
        } else {
            this._handleMoveLogic(touch);
        }
    }
    // Do not prevent touch events in inner nodes
    if (!this.cancelInnerEvents) {
        return;
    }

    var deltaMove = cc.pSub(touch.getLocation(), touch.getStartLocation());
    // FIXME: touch move delta should be calculated by DPI.
    if (cc.pLength(deltaMove) > 7) {
        if (!this._touchMoved && event.target !== this.node) {
            // Simulate touch cancel for target node
            var cancelEvent = new cc.Event.EventTouch(event.getTouches(), event.bubbles);
            cancelEvent.type = cc.Node.EventType.TOUCH_CANCEL;
            cancelEvent.touch = event.touch;
            cancelEvent.simulate = true;
            event.target.dispatchEvent(cancelEvent);
            this._touchMoved = true;
        }
    }
    this._stopPropagationIfTargetIsMe(event);
},

_onTouchEnded: function(event, captureListeners) {
    if (!this.enabledInHierarchy) return;
    if (this._hasNestedViewGroup(event, captureListeners)) return;

    this._dispatchEvent('touch-up');

    var touch = event.touch;
    if (this.content) {
        if (this.touchPageEndCallback) {
            if (this._scrolling || this._autoScrolling) {
                this._scrolling = false; 
            }
            this.touchPageEndCallback(event);
        }   else {
            this._handleReleaseLogic(touch);
        }
    }
    if (this._touchMoved) {
        event.stopPropagation();
    } else {
        this._stopPropagationIfTargetIsMe(event);
    }

    this.isMoveLocked = true;
},

_onTouchCancelled: function(event, captureListeners) {
    if (!this.enabledInHierarchy) return;
    if (this._hasNestedViewGroup(event, captureListeners)) return;

    // Filte touch cancel event send from self
    if (!event.simulate) {
        var touch = event.touch;
        if(this.content){
            if (this.touchPageCancelledCallback) {
                if (this._scrolling || this._autoScrolling) {
                    this._scrolling = false;
                    this._autoScrolling = false;
                }
                this.touchPageCancelledCallback(event);
            } else {
                this._handleReleaseLogic(touch);
            }
        }
    }
    this._stopPropagationIfTargetIsMe(event);

    this.isMoveLocked = true;
},

});
`

// 修改 事件分发函数,原函数cachedArray用函数外局部变量赋值,在嵌套调用时,会把记录状态抹掉,导致错误,改成cachedArray为函数内局部变量,解决该问题(192版本)
cc.Node.prototype.dispatchEvent = function(event) {
let owner = this as any;
event.target = owner;

        // Event.CAPTURING_PHASE
        let cachedArray = [];
        owner._getCapturingTargets(event.type, cachedArray);
        // capturing
        event.eventPhase = 1;
        for (let i = cachedArray.length - 1; i >= 0; --i) {
            let target = cachedArray[i];
            if (target._isTargetActive(event.type) && target._capturingListeners) {
                event.currentTarget = target;
                // fire event
                target._capturingListeners.invoke(event, cachedArray);
                // check if propagation stopped
                if ((event as any)._propagationStopped) {
                    cachedArray.length = 0;
                    return;
                }
            }
        }
        cachedArray.length = 0;

        // Event.AT_TARGET
        // checks if destroyed in capturing callbacks
        if (owner._isTargetActive(event.type)) {
            // Event.AT_TARGET
            event.eventPhase = 2;
            event.currentTarget = owner;
            if (owner._capturingListeners) {
                owner._capturingListeners.invoke(event);
            }
            if (!(event as any)._propagationImmediateStopped && owner._bubblingListeners) {
                owner._bubblingListeners.invoke(event);
            }
        }

        if (!((event as any)._propagationStopped) && event.bubbles) {
            // Event.BUBBLING_PHASE
            owner._getBubblingTargets(event.type, cachedArray);
            // propagate
            event.eventPhase = 3;
            for (let i = 0; i < cachedArray.length; ++i) {
                let target = cachedArray[i];
                if (target._isTargetActive(event.type) && target._bubblingListeners) {
                    event.currentTarget = target;
                    // fire event
                    target._bubblingListeners.invoke(event);
                    // check if propagation stopped
                    if ((event as any)._propagationStopped) {
                        cachedArray.length = 0;
                        return;
                    }
                }
            }
        }
        cachedArray.length = 0;
    };