Cocos2d-x嵌套使用ScrollView的方案

Cocos2d-x嵌套使用ScrollView的方案
比较典型的是皇室战争的UI设计,上下可以滚动,左右可以翻页
假设我们做一个PageView内嵌套ScrollView的UI,直接使用组件,会产生PageView和ScrollView同时发生位移的问题。

经过试验,只需要在UIScrollView.cpp的onTouchMove中
增加一句,通过_direction控制scrollview的滚动行为即可

//UIScrollView.cpp onTouchMove:
if(_direction == Direction::NONE)
          return;

之后,对于PageView的面板,增加一个触摸Layer,用于判断滑动的方向,如果为水平,则设置一个水平值,同时对ScrollView的面板,要透传PageView的ctx,通过ctx的isHorizontal来设置ScrollView的direction以及swallowTouches的行为。ScrollView也需要一个用于触摸检测的Layer。
这样可以做到与皇室战争一样的控制效果。

代码大概如下

function MyPageViewPanel:onCreate()
    local pageView = ccui.PageView:create()
    local touchLayer = display.newLayer() -- {r=255,g=0,b=0}
    for i=1, 3 do
        local myPage = MyPage:create(self)
        pageView:addPage(myPage)
    end
    self:addChild(pageView)
    self:addChild(touchLayer)
    touchLayer:onTouch(handler(self,self.onTouchLayer))
end
function MyPageViewPanel:onTouchLayer(event)
    local touchPos = cc.p(event.x,event.y)
    local touchLayer = self.touchLayer
    if event.name == 'began' then
        local p = touchLayer:convertToNodeSpace(touchPos)
        local size = self.touchLayerSize
        local intersect = cc.rectContainsPoint(cc.rect(0,0, size.width, size.height), p)
        if intersect then
            self.pageStartPos = touchPos
            return true
        end
        return false
    end

    if event.name == 'moved' then
        if self.determined then return end
        local dp = cc.pSub(touchPos,self.pageStartPos)
        if  math.abs(dp.x) < 5 and math.abs(dp.y) < 5 or self.determined then
            return
        end
        self.determined = true
        local angle = cc.pToAngleSelf(dp)
        angle = math.deg(angle)
        -- 用于ScrollView的判断
        self.isHorizontal = isHorizontal(angle)
    end

    if event.name == 'ended' then
        self.determined = false
        self.isHorizontal = nil
    end
end

MyPage.lua

function MyPage:onCreate(ctx)
    self.ctx = ctx
    self.scrollView = ccui.ScrollView:create()
    self.scrollView:setDirection(0) -- 初始方向为0
    self.touchLayer = display.newLayer()
    self:addChild(self.scrollView)
    self:addChild(touchLayer)
    touchLayer:onTouch(handler(self,self.onTouchLayer))
end

function MyPage:onTouchLayer(event)
    local touchPos = cc.p(event.x,event.y)
    local touchLayer = self.touchLayer

    if event.name == 'began' then
        local p = touchLayer:convertToNodeSpace(touchPos)
        local size = touchLayer:getContentSize()
        local intersect = cc.rectContainsPoint(cc.rect(0,0, size.width, size.height), p)
        if intersect then
            self.beganY = touchPos.y
            return true
        end
        return false
    end        
    
    if event.name == 'moved' then
        -- 上层还未确定是否为需要翻页或确实为翻页操作
        local isHorizontal = self.ctx.isHorizontal
        if isHorizontal == nil or isHorizontal then
            if self.scrollView:getDirection() ~= 0 then
                self.scrollView:setDirection(0) -- 设置为NONE,不会移动
                self.scrollView:setSwallowTouches(false)
            end
        else
            if self.scrollView:getDirection() == 0 then
                self.scrollView:setDirection(1)
                self.scrollView:setSwallowTouches(true)
            end
        end
    end

    if event.name == 'ended' then
        self.scrollView:setDirection(0)
        self.scrollView:setSwallowTouches(false)
    end
end

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 5,299评论 4 23
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 3,433评论 4 10
  • 简介 一般说的“命令行”是指命令,linux命令是对Linux系统进行管理的命令。对于Linux系统来说,无论是中...
    王平升阅读 141评论 2 4
  • 睡觉 八点半就张罗着给闺女洗漱,九点左右时我们一起躺在了床上。 我就发现,闺女在家的时候特别话痨,不停地“妈妈,妈...
    大脸and小脸阅读 100评论 0 2
  • 又是一年的结尾,大学的八分之一就这么结束了,作为比较提前归家的一部分人,在家乡等着朋友们一个个回家。 ...
    横折弯钩丶阅读 26评论 0 0