FastScrollView实现及其setContentSize与setInnerContainerSize理解
2017-01-22 10:41
423 查看
FastScrollDataSource = FastScrollDataSource or { } function FastScrollDataSource:getTotalSize( ) end function FastScrollDataSource:setData( node, dataIndex ) end FastScrollView = FastScrollView or { } FastScrollView = class("FastScrollView", function() local view = ccui.ScrollView:create() UI.fixScrollView(view) return view end) function FastScrollView:create() local view = FastScrollView:new() view: __init( ) return view end function FastScrollView:__init() self.node_list = { } self:addEventListener( function( sender, eventType ) self:scrollCallback(eventType) end ) end function FastScrollView:setScrollSize( rowSize, columnSize, cellWidth, cellHeight ) self.rowSize = rowSize self.columnSize = columnSize self.cellWidth = cellWidth self.cellHeight = cellHeight end function FastScrollView:addScrollNode( node ) table.insert( self.node_list , node ) self:addChild( node ) UI.setVisible( node , false ) end function FastScrollView:setModel( dataSource ) self.dataSource = dataSource self.totalSize = dataSource:getTotalSize( ) self.maxVisibleSize = -1 self.newIndex = -1 local contentSize = self:getContentSize() self.canScrollCallback = false local direction = self:getDirection() if direction == ccui.ScrollViewDir.vertical then local totalRow = math.ceil( self.totalSize / self.columnSize ) local totalHeight = totalRow * self.cellHeight if totalHeight <= contentSize.height then totalHeight = contentSize.height end self:setInnerContainerSize( cc.size( contentSize.width, totalHeight ) ) self:jumpToTop() elseif direction == ccui.ScrollViewDir.horizontal then local totalColumn = math.ceil( self.totalSize / self.rowSize ) local totalWidth = totalColumn * self.cellWidth if totalWidth <= contentSize.width then totalWidth = contentSize.width end self:setInnerContainerSize( cc.size( totalWidth, contentSize.height ) ) self:jumpToLeft() end self.canScrollCallback = true self.splitItemList = {} self:updateView( ) end -- 此方法为船坞添加分割使用 function FastScrollView:setSplitOffsetValue( splitIndex , splitItemHeight ) self.splitIndex = splitIndex self.splitItemHeight = splitItemHeight end function FastScrollView:setScrollListenerCallback( callback ) self.listenerCallback = callback end function FastScrollView:updateView( ) local posValue , scrLength , cellLength , start local direction = self:getDirection() if direction == ccui.ScrollViewDir.vertical then posValue = self:getInnerContainer():getPositionY() cellLength = self.cellHeight scrLength = self:getInnerContainer():getContentSize().height start = (posValue + scrLength) - self:getContentSize().height if self.splitIndex and self.splitItemHeight then if start > self.splitIndex * self.cellHeight then start = start - self.splitItemHeight end end if start < 0.5 then start = 0.5 elseif start > (posValue + scrLength + 0.5) then start = (posValue + scrLength + 0.5) end elseif direction == ccui.ScrollViewDir.horizontal then cellLength = self.cellWidth start = -self:getInnerContainer():getPositionX() if start < 0.5 then start = 0.5 elseif start > (self:getInnerContainer():getContentSize().width - self:getContentSize().width + 0.5) then start = (self:getInnerContainer():getContentSize().width - self:getContentSize().width + 0.5) end end local newIndex = math.ceil( start / cellLength ) if newIndex ~= self.newIndex then local oldIndex = self.newIndex self.newIndex = newIndex self:updateInnerNode( newIndex , oldIndex ) end end function FastScrollView:updateInnerNode( newIndex , oldIndex ) local totalIndex = self.rowSize * self.columnSize local itemSize local cellWidth , cellHeight = self.cellWidth , self.cellHeight local totalLength local direction = self:getDirection() if direction == ccui.ScrollViewDir.vertical then itemSize = self.columnSize totalLength = self:getInnerContainer():getContentSize().height elseif direction == ccui.ScrollViewDir.horizontal then itemSize = self.rowSize totalLength = self:getInnerContainer():getContentSize().width end local startIndex = (newIndex - 1) * itemSize + 1 local endIndex = startIndex + totalIndex - 1 if endIndex > self.totalSize then endIndex = self.totalSize end local maxVisibleSize = ( endIndex - startIndex + 1 ) local oldVisibleSize = self.maxVisibleSize self.maxVisibleSize = maxVisibleSize local node_list = self.node_list local dataSource = self.dataSource local curNode = nil -- 如果是第一次 local startIndexToSet = 1 local endIndexToSet = maxVisibleSize if oldVisibleSize and oldVisibleSize >= 0 then if newIndex > oldIndex then --头部调到尾部 local adjustSize = ( newIndex - oldIndex ) * itemSize for i = 1, adjustSize do curNode = node_list[ 1 ] table.remove( node_list , 1 ) table.insert( node_list, curNode ) end -- 从上次显示结尾位置开始 startIndexToSet = ( oldVisibleSize - adjustSize + 1 ) endIndexToSet = maxVisibleSize else --尾部调整到头部 local adjustSize = ( oldIndex - newIndex ) * itemSize for i = 1, adjustSize do curNode = node_list[ totalIndex ] table.remove( node_list , totalIndex ) table.insert( node_list, 1, curNode ) end --从开始显示到调整的位置 startIndexToSet = 1 endIndexToSet = adjustSize end end if startIndexToSet < 1 then startIndexToSet = 1 end -- 需要重设的节点 for i = startIndexToSet, endIndexToSet do if node_list[ i ] then curNode = node_list[ i ] curNode:setVisible( true ) local round = math.floor( ( startIndex + i - 1 - 1) / itemSize ) local remainder = ( startIndex + i - 1 - 1) % itemSize local x , y if direction == ccui.ScrollViewDir.vertical then x = cellWidth/2.0 + cellWidth * remainder y = cellHeight/2.0 + cellHeight * round y = totalLength - y elseif direction == ccui.ScrollViewDir.horizontal then x = cellWidth/2.0 + cellWidth * round y = cellHeight/2.0 + cellHeight * remainder end curNode:setPosition( x, y) dataSource:setData( curNode, startIndex + i - 1 ) end end for i, node in ipairs( node_list ) do node:setVisible( false ) end for i = 1, maxVisibleSize do node_list[ i ]:setVisible( true ) end end function FastScrollView:scrollCallback( eventType ) if self.canScrollCallback then if eventType == ccui.ScrollviewEventType.bounceBottom or eventType == ccui.ScrollviewEventType.bounceTop then self.isBounceing = true return end self.isBounceing = nil self:updateView( ) if self.listenerCallback then self.listenerCallback() end end end
其实本质很简单,就是根据滚动距离,重新设置滚动视图。
start = (posValue +scrLength) -self:getContentSize().height
就是重新滚动的距离。
-- 船坞滚动试图的模型数据设置 DockShipDatasource = class( "DockShipDatasource" ) function DockShipDatasource:create( dataList , nodeSize , callbackObj , callbackFuncs , splitIndex , splitItemHeight ) local datasource = DockShipDatasource:new() datasource.dataList = dataList datasource.nodeSize = nodeSize datasource.callbackObj = callbackObj datasource.callbackFuncs = callbackFuncs datasource.splitIndex = splitIndex datasource.splitItemHeight = splitItemHeight return datasource end function DockShipDatasource:setData( node, dataIndex ) local shipData = self.dataList[dataIndex] if shipData.__cname == "DictWarship" then if shipData.waitActivate then node:updateView( shipData, ShipFullNode.STATE_LOCK_CHIP_ENOUGH ) UI.onClickItem( node.btn_bg, self.callbackFuncs[ShipFullNode.STATE_LOCK_CHIP_ENOUGH], self.callbackObj ) else node:updateView( shipData, ShipFullNode.STATE_LOCK_CHIP_NOT_ENOUGH ) UI.onClickItem( node.btn_bg, self.callbackFuncs[ShipFullNode.STATE_LOCK_CHIP_NOT_ENOUGH], self.callbackObj ) end else node:updateView( shipData, ShipFullNode.STATE_UNLOCK ) UI.onClickItem( node.btn_bg, self.callbackFuncs[ShipFullNode.STATE_UNLOCK], self.callbackObj ) end local scr = node:getParent():getParent() if not self.splitLabel then scr:removeChildByName( "splitLabel" ) local splitLabel = UI.label( Res.FileNames.res_font_arts_ttf, 20, "——以下尚未解锁——" ) scr:addChild( splitLabel ) splitLabel:setName( "splitLabel" ) splitLabel:setPositionX( scr:getContentSize().width / 2 ) splitLabel:setPositionY( -200 ) scr:setInnerContainerSize( cc.size( scr:getInnerContainer():getContentSize().width , scr:getInnerContainer():getContentSize().height + self.splitItemHeight ) ) scr:jumpToTop() self.splitLabel = splitLabel end if dataIndex >= self.splitIndex then node:setPositionY( node:getPositionY() - self.splitItemHeight ) end if dataIndex == self.splitIndex then self.splitLabel:setPositionY( node:getPositionY() + self.nodeSize.height/2 + self.splitItemHeight/2 ) end end function DockShipDatasource:getTotalSize( ) return #self.dataList end
其实,这个东西就是根据数据源,在滚动的时候,不断刷新数据。当有扩展,比如:加入分割线等后,直接在刷新处处理即可。
self.scrollView:setScrollListenerCallback( function() local posX = self.scrollView:getInnerContainer():getPositionX() UI.setVisible( self.spr_left , posX < -20 ) UI.setVisible( self.spr_right , posX > self.scrollView:getContentSize().width - self.scrollView:getInnerContainerSize().width ) end)考虑这个水平的滚动:这个滚动时,左箭头和右箭头显示逻辑,但是FastScrollView的话,因为里面开始只有几个节点,所以posX开始肯定是0,但是innerContainerSize.width却是个很大的数字。
--test local posY = self.scrollview:getInnerContainer():getPositionY() local contentHeight = self.scrollview:getContentSize().height local innerContainerHeight = self.scrollview:getInnerContainerSize().height rlog("scrollView test") rlog("posY:" .. posY) rlog("contentHeight:" .. contentHeight) rlog("innerContainerHeight:" .. innerContainerHeight) [LUA-print] posY:-9632 [LUA-print] contentHeight:400 [LUA-print] innerContainerHeight:10032
右箭头显示逻辑,这个可以理解下innerContainer的位置是怎么做的。
相关文章推荐
- ndroid setContentView 实现同一个activity下不同view的切换
- setContentView()实现布局页面的跳转
- Android开发:setContentView切换界面,自定义带CheckBox的ListView显示SQlite条目-----实现
- Unity3D ScrollRect+ContentSizeFitter+GridLayoutGroup实现无限滚动(一)
- Android setContentView 实现同一个activity下不同view的切换
- 使用setContentView实现跳转
- 【页面】手机页面跳转的实现方法(一)——setContentView
- Android实现欢迎页:在onCreate方法中两次调用setContentView
- scrollview contentsize,contentoffset,bounds,frame,
- 通过定义BaseActivity来实现项目中代码重用,重写setContentView实现多个Activity部分UI布局相同
- VC/MFC加滚动条显示大图片SetScrollRange()、SetScrollInfo()两种思路实现及其两者优劣比较
- Unity3D ScrollRect+ContentSizeFitter+GridLayoutGroup实现无限滚动之排行榜(二)
- 2014-10-31Android学习------setContentView(View view)--------GIF动画实现
- Android setContentView 实现同一个activity下不同view的切换
- Android 使用setContentView来实现Acitivity的跳转
- CScrollView::SetScrollSizes
- Android setContentView 实现同一个activity下不同view的切换
- RecyclerView:实现带header的grid(ViewType和setSpanSizeLookup()方法)
- Android中级教程之(四)----->页面的转换,利用setContentView方法
- ListActivity与setContentView的关系