需求及分析
竖屏游戏,首界面有多页需要左右滑动翻页,每页需要上下滑动显示内容,且两个方向的滑动不能相互干扰。(参考效果:《部落冲突:皇室战争》)
左右滑动翻页选择PageView组件,上下滑动选择ScrollView界面。主要问题在于两者之间滑动不能相互干扰。
ScrollView是嵌套在PageView中的,PageView的滑动是ScrollView一层层传递上来的。可以考虑根据当前的滑动事件来限制他们的滑动方向。
实现
在PageView上方增加一个滑动层,当滑动距离到达某个阈值的时候判断当前的滑动行为是否为水平方向。如果是,则限制ScrollView的滑动,反之,则限制PageView的滑动。
对于ScrollView,可以通过设置滑动方向来限制滑动。对于PageView,可以通过禁止ScrollView传递触摸事件来限制滑动。
主界面相关代码
-- touchLayer为增加的滑动层,当滑动距离到达某个阈值的时候判断当前的滑动行为是否为水平方向。
local threshold = 5
touchLayer:addTouchEventListener(function(senter, eventType)
if eventType == ccui.TouchEventType.began then
self.maskTouchBeganPos = sender:getTouchBeganPosition()
elseif eventType == ccui.TouchEventType.moved then
if self.horizontalMoved ~= nil then
return
end
local touchMovePos = sender:getTouchMovePosition()
local dp = cc.pSub(touchMovePos, self.maskTouchBeganPos)
if math.abs(dp.x) < threshold and math.abs(dp.y) < threshold then
return
end
self.horizontalMoved = math.abs(dp.x) > math.abs(dp.y)
elseif eventType == ccui.TouchEventType.ended or eventType == ccui.TouchEventType.canceled then
self.horizontalMoved = nil
end
end)
单页相关代码
-- 初始化的时候把主界面传过来并且设置为self.mainPange
scrollView:addTouchEventListener(function(senter, eventType)
if self.mainPange.horizontalMoved == nil then
if scrollView:getDirection() ~= ccui.ScrollViewDir.none then
scrollView:setDirection(ccui.ScrollViewDir.none)
end
if scrollView:isPropagateTouchEvents() then
scrollView:setPropagateTouchEvents(false)
end
elseif self.mainPange.horizontalMoved == true then
if scrollView:getDirection() ~= ccui.ScrollViewDir.none then
scrollView:setDirection(ccui.ScrollViewDir.none)
end
if not scrollView:isPropagateTouchEvents() then
scrollView:setPropagateTouchEvents(true)
end
else
if scrollView:getDirection() == ccui.ScrollViewDir.none then
scrollView:setDirection(ccui.ScrollViewDir.vertical)
end
if scrollView:isPropagateTouchEvents() then
scrollView:setPropagateTouchEvents(false)
end
end
end
补充
本例的界面是采用CocosStudio 2.x编辑生成的。嵌套的界面,CSLoader生成的是Node而非UIWidget,没有propagateTouchEvent接口,导致ScrollView的触摸事件无法传递到PageView。 解决方式,暴力修改NodeReader中的createNodeWithFlatBuffers方法,默认生成一个空的UIWidget而非Node。