当前位置:   article > 正文

Cocos2dx-lua ScrollView[三]高级篇

Cocos2dx-lua ScrollView[三]高级篇

一.概述

本文缩写说明:sv = ScrollView, cell代表ScrollView的一个子节点

本文介绍sv的一种封装类库,来实现快速创建sv,有如下几个优点:

1.item的位置通过参数控制,提高开发效率

2.免去了调用sv的API,提高开发效率

3.分帧创建,提高性能

4.可通过参数控制,复用item类似tableview,提高性能

本文和上一篇Cocos2dx-lua ScrollView[二]进阶篇-CSDN博客

对比有一定相似之处,但也有较多不同,读者可仔细对比代码实现,详细品读,有所取舍和偏爱

二.效果演示

三.代码实现

3.1 说明

a.下面2个模块需要require

b.svCmn是比较复杂的,有必要阅读代码掌握运行原理

c.代码原封不动搬到工程里基本可以正常运行(当然哪里出了问题读者得会排查,本文基本喂饭喂到嘴里了)

d.svCmn经过上线项目验证,可放心使用,在项目中大量推广

3.2 辅助定时器模块:GlobalTimeTicket

  1. GlobalTimeTicket = GlobalTimeTicket or {}
  2. auto_id = auto_id or 0
  3. function autoId()
  4. auto_id = auto_id + 1
  5. return auto_id
  6. end
  7. -- 获取单例
  8. -- New和不New只是一层一层调用__init和__delete,对于单例没有影响
  9. function GlobalTimeTicket:getInstance()
  10. if not self.is_init then
  11. self.scheduler = cc.Director:getInstance():getScheduler()
  12. self.schedulers = {}
  13. self.is_init = true
  14. self.is_stop = nil
  15. end
  16. return self
  17. end
  18. -- 定时回调 通用版
  19. -- call_back : function 回调函数 必填
  20. -- interval : int 时间间隔 默认1 秒
  21. -- limit_time: int 限制次数 默认0 无限
  22. -- with_name : any 定时器标识 默认自增id
  23. -- 返回用于删除的标识
  24. -- simple : local id = GlobalTimeTicket:getInstance():add(fun) ; GlobalTimeTicket:getInstance():remove(id)
  25. -- : GlobalTimeTicket:getInstance():add(fun, 0.1, 1) -- 次数达到自动删除
  26. -- : GlobalTimeTicket:getInstance():add(fun, 0.1, 3, "name")
  27. function GlobalTimeTicket:add(call_back, interval, limit_time, with_name)
  28. if self.is_stop then return end
  29. with_name = with_name or autoId()
  30. if nil == call_back or self.schedulers == nil or nil ~= self.schedulers[with_name] then return end -- 已经有定义了,不能重复
  31. limit_time = limit_time or 0
  32. interval = interval or 1
  33. local schedul_hander = self.scheduler:scheduleScriptFunc(function(dt)
  34. if self.is_stop then return end
  35. if call_back ~= nil then
  36. if limit_time == 1 then
  37. self:remove(with_name)
  38. elseif limit_time > 1 then
  39. limit_time = limit_time - 1
  40. end
  41. call_back(dt)
  42. end
  43. end, interval, false)
  44. self.schedulers[with_name] = schedul_hander
  45. return with_name
  46. end
  47. -- 删除一个定时器
  48. function GlobalTimeTicket:remove(with_name)
  49. if with_name == nil then return end
  50. local schedul_hander = self.schedulers[with_name]
  51. if schedul_hander ~= nil then
  52. self.scheduler:unscheduleScriptEntry(schedul_hander)
  53. self.schedulers[with_name] = nil
  54. end
  55. end
  56. -- 清除所有定时器
  57. function GlobalTimeTicket:removeAll()
  58. for _, v in pairs(self.schedulers) do
  59. self.scheduler:unscheduleScriptEntry(v)
  60. end
  61. self.schedulers = {}
  62. end
  63. function GlobalTimeTicket:hasTicket(with_name)
  64. local schedul_hander = self.schedulers[with_name]
  65. if schedul_hander ~= nil then
  66. return true
  67. end
  68. return false
  69. end
  70. function GlobalTimeTicket:getSchedulers()
  71. return self.schedulers
  72. end
  73. -- 停止定时器
  74. function GlobalTimeTicket:stop()
  75. self.is_stop = true
  76. self:removeAll()
  77. end

3.3 sv封装模块:svCmn

  1. --[[使用例子
  2. if not self.svCmn then
  3. local setting = {
  4. start_x = 18, space_x = 0,
  5. start_y = 26, space_y = 6,
  6. item_width = 686, item_height = 172,
  7. row = 1, col = 1,
  8. delay = 4, once_num = 1,
  9. }
  10. self.svCmn = svCmn.new(self.scr_con, cc.p(0,0) , ScrollViewDir.vertical, ScrollViewStartPos.top, self.scr_con:getContentSize(), setting, cc.p(0, 0))
  11. self.svCmn:registerScriptHandlerSingle(handler(self,self.createNewCell), ScrollViewFuncType.CreateNewCell)
  12. self.svCmn:registerScriptHandlerSingle(handler(self,self.numberOfCells), ScrollViewFuncType.NumberOfCells)
  13. self.svCmn:registerScriptHandlerSingle(handler(self,self.updateCellByIndex), ScrollViewFuncType.UpdateCellByIndex)
  14. end
  15. self.svCmn:reloadData()
  16. ]]--
  17. --ScrollView的方法类型
  18. ScrollViewFuncType = {
  19. UpdateCellByIndex = 1, -- 更新cell体
  20. CreateNewCell = 2, -- 创建 新的cell
  21. NumberOfCells = 3, -- 返回 数据的数量
  22. OnCellTouched = 4, -- 点击cell回调方法
  23. }
  24. svCmn = class("svCmn", function()
  25. return ccui.Layout:create()
  26. end)
  27. function svCmn:ctor(parent, pos, dir, start_pos, size, setting, ap)
  28. self.parent = parent
  29. self.pos = pos or cc.p(0, 0)
  30. self.dir = dir or ScrollViewDir.vertical
  31. self.start_pos = start_pos or ScrollViewStartPos.top
  32. self.size = size or cc.size(100, 100)
  33. self.ap = ap or cc.p(0, 0)
  34. self.allCellList = {} --存放cell对象和其坐标,结构:{x, y, cell}, cell存在重复对象, 长度=cell总数量
  35. self.cacheList = {} --保存所有实际创建的cell, 长度=cell最大显示数量
  36. self.activeCellIdx = {} --保存每个位置的cell当前是否处于显示状态, 长度=cell总数量
  37. self.handler = {} --回调方法
  38. self.time_show_index = 0 --到时间显示的索引
  39. self.is_first_init = true --是否初始化
  40. self:analysisSetting(setting)
  41. self:createRootWnd()
  42. end
  43. --要求规定setting的所有变量 都应该在这里定义出来
  44. function svCmn:analysisSetting(setting)
  45. self.setting = setting or {}
  46. self.start_x = self.setting.start_x or 0 -- 第一个单元的起点X
  47. self.end_x = self.setting.end_x or self.start_x -- 最后一个单元结束X间隔 如果是nil 默认 和 start_x一致
  48. self.start_y = self.setting.start_y or 0 -- 第一个单元的起点Y
  49. self.end_y = self.setting.end_y or self.start_y -- 最后一个单元结束Y间隔 如果是nil 默认 和 start_y一致
  50. self.space_x = self.setting.space_x or 3 -- 横向间隔空间
  51. self.space_y = self.setting.space_y or 3 -- 竖向间隔空间
  52. self.item_width = self.setting.item_width or 115 -- 单元的宽度
  53. self.item_height = self.setting.item_height or 115 -- 单元的高度
  54. self.row = self.setting.row or 5 -- 行数,作用于水平方向的滚动
  55. self.col = self.setting.col or 5 -- 列数,作用于垂直方向的滚动
  56. self.delay = 1 --self.setting.delay or 4 -- 创建延迟时间 强制改为1
  57. self.once_num = self.setting.once_num or 1 -- 每次创建的数量
  58. self.need_dynamic = true -- 默认是无限的
  59. self.checkovercallback = self.setting.checkovercallback --滑动回调函数
  60. self.is_auto_scroll = setting.is_auto_scroll or false --是否自动判断是否能滚动..个数小于一屏大小时候scroll 不能滚动
  61. --位置列表
  62. self.position_data_list = self.setting.position_data_list
  63. --固定容器大小 如果有值.将不运算容器大小
  64. self.container_width = setting.container_width
  65. self.container_height = setting.container_height
  66. self.inner_hight_offset = setting.inner_hight_offset or 0 -- 内容高度偏移值(仅对纵向有效)
  67. --横向的只支持一行的..
  68. if self.dir == ScrollViewDir.horizontal then
  69. self.row = 1
  70. end
  71. self:calculationMaxSum()
  72. end
  73. function svCmn:updateSetting(setting)
  74. if not setting then return end
  75. for k,v in pairs(setting) do
  76. self[k] = v
  77. end
  78. end
  79. --desc:计算一下一屏最多创建的个数
  80. function svCmn:calculationMaxSum()
  81. local max_sum
  82. if self.dir == ScrollViewDir.horizontal then
  83. max_sum = (math.ceil(self.size.width / (self.item_width + self.space_x)) + 1) * self.row
  84. else
  85. max_sum = (math.ceil(self.size.height / (self.item_height + self.space_y)) + 1) * self.col
  86. end
  87. self.cacheMaxSize = max_sum
  88. end
  89. function svCmn:createRootWnd()
  90. self:setContentSize(self.size)
  91. if not tolua.isnull(self.parent) then
  92. self.parent:addChild(self)
  93. end
  94. self:setPosition(self.pos)
  95. self:setAnchorPoint(self.ap)
  96. self.scroll_view = createScrollView(self.size.width, self.size.height, 0, 0, self, self.dir)
  97. self.container = self.scroll_view:getInnerContainer()
  98. self:registerEvent()
  99. end
  100. function svCmn:registerEvent()
  101. if self.need_dynamic == true then
  102. self.scroll_view:addEventListener(function(sender, eventType)
  103. if eventType == ccui.ScrollviewEventType.containerMoved then
  104. self:checkRectIntersectsRect()
  105. if self.checkovercallback then
  106. self.checkovercallback()
  107. end
  108. end
  109. end)
  110. end
  111. end
  112. function svCmn:registerScriptHandlerSingle(func, handlerId)
  113. self.handler[handlerId] = func
  114. end
  115. function svCmn:numberOfCells()
  116. local cells = ScrollViewFuncType.NumberOfCells
  117. if not self.handler or not self.handler[cells] then return end
  118. return self.handler[cells]()
  119. end
  120. --刷新每一个cell
  121. function svCmn:updateCellByIndex(cell, index)
  122. if not self.handler[ScrollViewFuncType.UpdateCellByIndex] then return end
  123. if not cell.index then
  124. cell.create_index = index
  125. end
  126. print("item刷新ing", "item创建时的索引:"..cell.create_index, "item数据索引变化:" .. (cell.index or "无") .. " -> " .. index)
  127. self.handler[ScrollViewFuncType.UpdateCellByIndex](cell, index)
  128. end
  129. --创建一个新cell
  130. function svCmn:createNewCell(idx)
  131. if not self.handler[ScrollViewFuncType.CreateNewCell] then return end
  132. print("createNewCell", idx)
  133. return self.handler[ScrollViewFuncType.CreateNewCell](self.item_width, self.item_height, idx)
  134. end
  135. -- --点击cell --在createNewCell 自行实现
  136. function svCmn:onCellTouched(cell, index)
  137. if not self.handler[ScrollViewFuncType.OnCellTouched] then return end
  138. self.handler[ScrollViewFuncType.OnCellTouched](cell, index)
  139. end
  140. --设置 scrollview 是否可点
  141. function svCmn:setClickEnabled(status)
  142. self.scroll_view:setTouchEnabled(status)
  143. end
  144. --设置 是否吞噬点击
  145. function svCmn:setSwallowTouches(status)
  146. self.scroll_view:setSwallowTouches(status)
  147. end
  148. function svCmn:setBounceEnabled( status )
  149. self.scroll_view:setBounceEnabled(status)
  150. end
  151. --desc:移动的过程中盘点是否不再可视范围,不再的时候移除掉,放到对象池,并且准备下一次创建
  152. function svCmn:checkRectIntersectsRect()
  153. if self.dir == ScrollViewDir.vertical then
  154. if self.start_pos == ScrollViewStartPos.top then
  155. self:checkOverShowByVertical()
  156. else
  157. -- 支持ScrollViewStartPos.bottom的了 --by lwc
  158. self:checkOverShowByVerticalBottom()
  159. end
  160. elseif self.dir == ScrollViewDir.horizontal then
  161. self:checkOverShowByHorizontal()
  162. end
  163. end
  164. function svCmn:checkOverShowByVertical()
  165. if not self.allCellList then return end
  166. local container_y = self.container:getPositionY()
  167. --计算 视图的上部分和下部分在self.container 的位置
  168. local bot = -container_y
  169. local top = self.size.height + bot
  170. local col_count = math.ceil(#self.allCellList/self.col)
  171. --下面因为 self.allCellList 是一维数组 所以要换成二维来算
  172. --活跃cell开始行数
  173. local activeCellStartRow = 1
  174. for i=1, col_count do
  175. local index = 1 + (i-1)* self.col
  176. local cell = self.allCellList[index]
  177. activeCellStartRow = i
  178. if cell and cell.y - self.item_height * 0.5 <= top then
  179. break
  180. end
  181. end
  182. --活跃cell结束行数
  183. local activeCellEndRow = col_count
  184. if bot > 0 then
  185. for i = activeCellStartRow, col_count do
  186. local index = 1 + (i-1)* self.col
  187. local cell = self.allCellList[index]
  188. if cell and cell.y + self.item_height * 0.5 < bot then
  189. activeCellEndRow = i - 1
  190. break
  191. end
  192. end
  193. end
  194. -- print("@保留--> top --> :"..top .." self.col:"..self.col)
  195. -- print("@保留--> bot --> :"..bot )
  196. -- print("@保留--> 开始行: "..activeCellStartRow.."@结束行: "..activeCellEndRow)
  197. local max_count = self:numberOfCells()
  198. if max_count then
  199. for i=1, col_count do
  200. if i >= activeCellStartRow and i <= activeCellEndRow then
  201. for k=1, self.col do
  202. local index = (i-1) * self.col + k
  203. if not self.activeCellIdx[index] then
  204. if index <= max_count then
  205. self:updateCellAtIndex(index)
  206. self.activeCellIdx[index] = true
  207. end
  208. end
  209. end
  210. else
  211. for k=1, self.col do
  212. local index = (i-1) * self.col + k
  213. if index <= max_count then
  214. self.activeCellIdx[index] = false
  215. end
  216. end
  217. end
  218. end
  219. end
  220. end
  221. function svCmn:checkOverShowByVerticalBottom()
  222. if not self.allCellList then return end
  223. local container_y = self.container:getPositionY()
  224. --计算 视图的上部分和下部分在self.container 的位置
  225. local bot = -container_y
  226. local top = self.size.height + bot
  227. local col_count = math.ceil(#self.allCellList/self.col)
  228. --下面因为 self.allCellList 是一维数组 所以要换成二维来算
  229. --活跃cell开始行数
  230. local activeCellStartRow = col_count
  231. for i=col_count, 1,-1 do
  232. local index = 1 + (i-1)* self.col
  233. local cell = self.allCellList[index]
  234. activeCellStartRow = i
  235. if cell and cell.y - self.item_height * 0.5 <= top then
  236. break
  237. end
  238. end
  239. --活跃cell结束行数
  240. local activeCellEndRow = 1
  241. if bot > 0 then
  242. for i = activeCellStartRow, 1, -1 do
  243. local index = 1 + (i-1)* self.col
  244. local cell = self.allCellList[index]
  245. if cell and cell.y + self.item_height * 0.5 < bot then
  246. activeCellEndRow = i + 1
  247. break
  248. end
  249. end
  250. end
  251. -- print("@保留--> top --> :"..top .." self.col:"..self.col)
  252. -- print("@保留--> bot --> :"..bot )
  253. -- print("@保留--> 开始行: "..activeCellStartRow.."@结束行: "..activeCellEndRow)
  254. local max_count = self:numberOfCells()
  255. for i=1, col_count do
  256. if i <= activeCellStartRow and i >= activeCellEndRow then
  257. for k=1, self.col do
  258. local index = (i-1) * self.col + k
  259. if not self.activeCellIdx[index] then
  260. if index <= max_count then
  261. self:updateCellAtIndex(index)
  262. self.activeCellIdx[index] = true
  263. end
  264. end
  265. end
  266. else
  267. for k=1, self.col do
  268. local index = (i-1) * self.col + k
  269. if index <= max_count then
  270. self.activeCellIdx[index] = false
  271. end
  272. end
  273. end
  274. end
  275. end
  276. function svCmn:checkOverShowByHorizontal()
  277. if not self.allCellList then return end
  278. local container_x = self.container:getPositionX()
  279. --计算 视图的左部分和右部分在self.container 的位置
  280. local top = -container_x
  281. local bot = top + self.size.width
  282. local row_count = #self.allCellList
  283. --横向的只支持一行
  284. --活跃cell开始行数
  285. local activeCellStartRow = 1
  286. if top > 0 then
  287. for index=1, row_count do
  288. local cell = self.allCellList[index]
  289. activeCellStartRow = index
  290. if cell and cell.x + self.item_width * 0.5 >= top then
  291. break
  292. end
  293. end
  294. end
  295. --活跃cell结束行数
  296. local activeCellEndRow = row_count
  297. for index = activeCellStartRow, row_count do
  298. local cell = self.allCellList[index]
  299. if cell and cell.x - self.item_width * 0.5 > bot then
  300. activeCellEndRow = index - 1
  301. break
  302. end
  303. end
  304. -- print("@保留--> top --> :"..top .." self.row:"..self.row)
  305. -- print("@保留--> bot --> :"..bot )
  306. -- print("@保留--> 开始行: "..activeCellStartRow.."@结束行: "..activeCellEndRow)
  307. local max_count = self:numberOfCells()
  308. if max_count then
  309. for index=1, row_count do
  310. if index >= activeCellStartRow and index <= activeCellEndRow then
  311. if not self.activeCellIdx[index] then
  312. if index <= max_count then
  313. self:updateCellAtIndex(index)
  314. self.activeCellIdx[index] = true
  315. end
  316. end
  317. else
  318. if index <= max_count then
  319. self.activeCellIdx[index] = false
  320. end
  321. end
  322. end
  323. end
  324. end
  325. --desc:滚动容器移动到指定位置
  326. function svCmn:updateMove(pos)
  327. local target_pos = self:checkPosition(pos.x, pos.y)
  328. local move_to = cc.MoveTo:create(0.1, cc.p(target_pos.x, target_pos.y))
  329. local ease_out = cc.EaseSineOut:create(move_to)
  330. self.container:runAction(cc.Sequence:create(ease_out))
  331. end
  332. function svCmn:jumpToMove(pos, time, callback)
  333. local target_pos = self:checkPosition(pos.x, pos.y)
  334. time = time or 1
  335. local move_to = cc.MoveTo:create(time, cc.p(target_pos.x, target_pos.y))
  336. self.container:runAction(cc.Sequence:create(move_to, cc.CallFunc:create(function()
  337. if callback then
  338. callback()
  339. end
  340. end)))
  341. end
  342. function svCmn:checkPosition(x, y)
  343. local _x, _y = self.container:getPositionX(), self.container:getPositionY()
  344. if self.dir == ScrollViewDir.horizontal then
  345. _x = _x + x
  346. elseif self.dir == ScrollViewDir.vertical then
  347. _y = _y + y
  348. end
  349. if _x > 0 then
  350. _x = 0
  351. elseif _x < (self.size.width - self.container_size.width) then
  352. _x = self.size.width - self.container_size.width
  353. end
  354. if _y > 0 then
  355. _y = 0
  356. elseif _y < (self.size.height - self.container_size.height) then
  357. _y = self.size.height - self.container_size.height
  358. end
  359. return cc.p(_x, _y)
  360. end
  361. --获取当前容器的y位置
  362. function svCmn:getCurContainerPosY()
  363. if self.container and not tolua.isnull(self.container) then
  364. return self.container:getPositionY()
  365. end
  366. end
  367. --获取当前容器的x位置
  368. function svCmn:getCurContainerPosX()
  369. if self.container and not tolua.isnull(self.container) then
  370. return self.container:getPositionX()
  371. end
  372. end
  373. function svCmn:setInnerContainer()
  374. local number = self:numberOfCells()
  375. local container_width = self.container_width or self.size.width
  376. local container_height = self.container_height or self.size.height
  377. if self.dir == ScrollViewDir.horizontal then -- 水平
  378. if self.container_width == nil then
  379. local num = math.ceil(number / self.row)
  380. container_width = num * self.item_width + self.end_x + self.start_x + (num - 1) * self.space_x
  381. end
  382. else
  383. if self.container_height == nil then
  384. local num = math.ceil(number / self.col)
  385. container_height = num * self.item_height + self.end_y + self.start_y + (num - 1) * self.space_y + self.inner_hight_offset
  386. end
  387. end
  388. container_width = math.max(container_width, self.size.width)
  389. container_height = math.max(container_height, self.size.height)
  390. self.container_size = cc.size(container_width, container_height)
  391. --记录在当前的contariner位置..因为在 setInnerContainerSize 方法会被重置
  392. self.cur_container_x, self.cur_container_y = self.container:getPosition()
  393. self.scroll_view:setInnerContainerSize(self.container_size)
  394. if self.start_pos == ScrollViewStartPos.top then
  395. self.scroll_view:jumpToTop()
  396. elseif self.start_pos == ScrollViewStartPos.bottom then
  397. self.scroll_view:jumpToBottom()
  398. end
  399. end
  400. --刷新当前显示的item数据 (不改变任何位置的,前提数据数量没有改变如果有改变用 reload)
  401. function svCmn:resetCurrentItems()
  402. for i,v in pairs(self.activeCellIdx) do
  403. if v then
  404. self:updateCellAtIndex(i)
  405. end
  406. end
  407. end
  408. --根据index 刷新对应索引..如果在显示视图内
  409. function svCmn:resetItemByIndex(index)
  410. -- body
  411. if self.activeCellIdx[index] then
  412. self:updateCellAtIndex(index)
  413. end
  414. end
  415. --获取活跃中的cell对象
  416. function svCmn:getActiveCellList()
  417. local list = {}
  418. for i,v in pairs(self.activeCellIdx) do
  419. if v and self.allCellList[i] and self.allCellList[i].cell then
  420. table.insert(list, self.allCellList[i].cell)
  421. end
  422. end
  423. return list
  424. end
  425. --获取index索引对应cell(不管是否活跃)
  426. function svCmn:getCellByIndex(index)
  427. if self.allCellList[index] and self.allCellList[index].cell then
  428. return self.allCellList[index].cell
  429. end
  430. end
  431. --获取index索引对应cellXY位置(不管是否活跃)
  432. function svCmn:getCellXYByIndex(index)
  433. if self.allCellList[index] then
  434. return self.allCellList[index].x, self.allCellList[index].y
  435. end
  436. end
  437. --获取index索引对应cellXY位置(不活跃会返回空)
  438. function svCmn:getActiveCellByIndex(index)
  439. if self.activeCellIdx[index] and self.allCellList[index] then
  440. return self.allCellList[index].cell
  441. end
  442. end
  443. --获取当前容器所在显示窗口的x y位置
  444. function svCmn:getContainerXY()
  445. if self.container then
  446. local x, y = self.container:getPosition()
  447. return x, y
  448. end
  449. end
  450. --获取当前容器所在显示窗口的x y位置
  451. function svCmn:setContainerXY(x, y)
  452. if self.container then
  453. if x and y then
  454. self.container:setPosition(x,y)
  455. else
  456. if x then
  457. self.container:setPositionX(x)
  458. end
  459. if y then
  460. self.container:setPositionY(y)
  461. end
  462. end
  463. end
  464. end
  465. --根据索引判断是否活跃中
  466. function svCmn:isActiveByIndex(index)
  467. if self.activeCellIdx[index] then
  468. return true
  469. end
  470. return false
  471. end
  472. --移动到以选中idenx的位置作为在中间 显示 目前只支持y 方向的
  473. function svCmn:jumpToMoveByIndex(index)
  474. if not self.allCellList[index] then return end
  475. local y = self.allCellList[index].y or 0
  476. local pos = self.container_size.height - (y + self.size.height * 0.5 )
  477. if pos < 0 then
  478. pos = 0
  479. end
  480. local pos_per = pos * 100 / (self.container_size.height - self.size.height)
  481. if pos_per ~= pos_per then
  482. pos_per = 0;
  483. end
  484. if pos_per > 100 then
  485. pos_per = 100
  486. end
  487. if pos_per == 100 then
  488. if self.start_pos == ScrollViewStartPos.top then
  489. self:checkOverShowByVertical()
  490. else
  491. self:checkOverShowByVerticalBottom()
  492. end
  493. end
  494. self.scroll_view:scrollToPercentVertical(pos_per, 0.8, true)
  495. end
  496. --desc:设置数据
  497. --select_idnex 从第几个开始
  498. --@setting: 如果有改变的话
  499. --@is_keep_position 是否保持原来位置 --item数量有变化情况. 无变化请用resetCurrentItems
  500. function svCmn:reloadData(select_index, setting, is_keep_position)
  501. if setting then
  502. self:updateSetting(setting)
  503. end
  504. local old_width , old_height = 0, 0
  505. if self.container_size then
  506. old_width = self.container_size.width
  507. old_height = self.container_size.height
  508. end
  509. self.allCellList = {}
  510. self.activeCellIdx = {}
  511. for k, v in ipairs(self.cacheList) do
  512. --相当于隐藏
  513. v:setPositionX(-10000)
  514. end
  515. --设置容器大小
  516. self:setInnerContainer()
  517. local number = self:numberOfCells()
  518. if number == 0 then
  519. return
  520. end
  521. for i = 1, number do
  522. local cell = nil
  523. if i <= self.time_show_index then
  524. cell = self:getCacheCellByIndex(i)
  525. end
  526. local count = #self.allCellList
  527. local x, y
  528. if self.position_data_list then
  529. local pos = self.position_data_list[count + 1]
  530. if pos then
  531. x, y = pos.x, pos.y
  532. else
  533. x, y = self:getCellPosition(count + 1)
  534. end
  535. else
  536. x, y = self:getCellPosition(count + 1)
  537. end
  538. local cellData = {cell = cell, x = x, y = y}
  539. table.insert(self.allCellList, cellData)
  540. end
  541. if self.is_first_init then
  542. self:startTimeTicket()
  543. else
  544. --如果时间显示索引小于总数 应该显示继续当前定时器 让下面的能显示出来
  545. if self.time_show_index <= number then
  546. self:startTimeTicket()
  547. end
  548. end
  549. if is_keep_position then
  550. --是否保持当前显示位置
  551. local cur_container_x = self.cur_container_x or 0
  552. local cur_container_y = self.cur_container_y or 0
  553. if self.dir == ScrollViewDir.vertical then --竖方向
  554. if self.start_pos == ScrollViewStartPos.top then
  555. local temp_height = self.container_size.height - old_height
  556. cur_container_y = cur_container_y - temp_height
  557. end
  558. if cur_container_y > 0 then
  559. cur_container_y = 0
  560. elseif cur_container_y < (self.size.height - self.container_size.height) then
  561. cur_container_y = self.size.height - self.container_size.height
  562. end
  563. elseif self.dir == ScrollViewDir.horizontal then --横方向
  564. if cur_container_x > 0 then
  565. cur_container_x = 0
  566. elseif cur_container_x < (self.size.width - self.container_size.width) then
  567. cur_container_x = self.size.width - self.container_size.width
  568. end
  569. end
  570. self.container:setPosition(cur_container_x, cur_container_y)
  571. self:checkRectIntersectsRect()
  572. else
  573. if select_index == nil then
  574. local maxRefreshNum
  575. if self.dir == ScrollViewDir.horizontal then -- 水平
  576. maxRefreshNum = self.cacheMaxSize - self.row
  577. else
  578. maxRefreshNum = self.cacheMaxSize - self.col
  579. end
  580. local refreshNum = number < maxRefreshNum and number or maxRefreshNum
  581. for i = 1, refreshNum do
  582. if i <= self.time_show_index then
  583. self:updateCellAtIndex(i)
  584. end
  585. self.activeCellIdx[i] = true
  586. end
  587. else
  588. self:selectCellByIndex(select_index)
  589. end
  590. end
  591. if self.is_auto_scroll then
  592. local cur_max_count = self.cacheMaxSize
  593. if self.dir == ScrollViewDir.horizontal then
  594. cur_max_count = cur_max_count - 2 * self.row
  595. else
  596. cur_max_count = cur_max_count - 2 * self.col
  597. end
  598. if number <= cur_max_count then
  599. self:setClickEnabled(false)
  600. else
  601. self:setClickEnabled(true)
  602. end
  603. end
  604. end
  605. --选中index索引对象(如果列表允许 会排序在开始第一位)
  606. function svCmn:selectCellByIndex(index)
  607. local index = index or 1
  608. if self.allCellList[index] == nil then
  609. index = 1
  610. end
  611. if self.allCellList[index] == nil then return end
  612. --一屏幕显示的最大数量
  613. local maxRefreshNum
  614. if self.dir == ScrollViewDir.horizontal then -- 水平
  615. maxRefreshNum = self.cacheMaxSize - self.row
  616. else
  617. maxRefreshNum = self.cacheMaxSize - self.col
  618. end
  619. local number = self:numberOfCells()
  620. if number < maxRefreshNum then
  621. --不够显示一屏幕
  622. if self.time_show_index == 0 then
  623. self.time_show_index = index
  624. end
  625. for i = 1, number do
  626. if i <= self.time_show_index then
  627. self:updateCellAtIndex(i)
  628. end
  629. self.activeCellIdx[i] = true
  630. end
  631. else
  632. --列表允许 情况
  633. if self.dir == ScrollViewDir.horizontal then -- 水平
  634. --容器x方向位置
  635. local container_x
  636. if index == 1 then
  637. container_x = 0
  638. else
  639. container_x = -(self.allCellList[index].x - (self.item_width + self.space_x) * 0.5 )
  640. end
  641. --容器x方向最大位置
  642. local max_contariner_x = -(self.container_size.width - self.size.width)
  643. --这两个值都是负数
  644. if container_x < max_contariner_x then
  645. container_x = max_contariner_x
  646. end
  647. local show_index = math.floor(math.abs(container_x) / self.item_width) + 1
  648. if self.time_show_index < show_index then
  649. self.time_show_index = show_index
  650. end
  651. self.container:setPositionX(container_x)
  652. self:checkRectIntersectsRect()
  653. else -- 垂直
  654. local container_y
  655. if index == 1 then
  656. container_y = (self.start_y + self.allCellList[index].y + self.item_height * 0.5) - self.size.height
  657. else
  658. container_y = (self.allCellList[index].y + (self.item_height + self.space_y) * 0.5) - self.size.height
  659. end
  660. if container_y < 0 then
  661. container_y = 0
  662. end
  663. local index_1 = math.floor( (self.container_size.height - (container_y + self.size.height)) / self.item_height) + 1
  664. local show_index = (index_1 - 1) * self.col + 1
  665. if self.time_show_index < show_index then
  666. self.time_show_index = show_index
  667. end
  668. self.container:setPositionY(- container_y)
  669. self:checkRectIntersectsRect()
  670. end
  671. end
  672. if index > 0 and index <= self:numberOfCells() then
  673. local cell = self:getCacheCellByIndex(index)
  674. cell.index = index
  675. self.allCellList[index].cell = cell
  676. self:onCellTouched(cell, index)
  677. end
  678. end
  679. function svCmn:setOnCellTouched(index)
  680. local cell = self:getCacheCellByIndex(index)
  681. cell.index = index
  682. self.allCellList[index].cell = cell
  683. self:onCellTouched(cell, index)
  684. end
  685. function svCmn:startTimeTicket()
  686. if self.time_ticket == nil then
  687. if #self.allCellList == 0 then
  688. return
  689. end
  690. --到时间显示的索引
  691. local once_num = self.once_num or 1
  692. local _callback = function()
  693. if tolua.isnull(self.container) then return end
  694. local count = self.time_show_index + once_num
  695. local index = self.time_show_index + 1
  696. if index == 0 then
  697. index = 1
  698. end
  699. local size = #self.allCellList
  700. self.time_show_index = self.time_show_index + once_num
  701. for i = index, count do
  702. if i > size then
  703. --超过总数了
  704. break
  705. end
  706. local cellData = self.allCellList[i]
  707. if cellData and cellData.cell == nil then
  708. cellData.cell = self:getCacheCellByIndex(i)
  709. end
  710. if self.activeCellIdx[i] then
  711. self:updateCellAtIndex(i)
  712. end
  713. end
  714. if self.time_show_index >= size then
  715. self:clearTimeTicket()
  716. self.is_first_init = false
  717. end
  718. end
  719. self.time_ticket = GlobalTimeTicket:getInstance():add(_callback, self.delay / display.DEFAULT_FPS)
  720. end
  721. end
  722. function svCmn:clearTimeTicket()
  723. if self.time_ticket ~= nil then
  724. GlobalTimeTicket:getInstance():remove(self.time_ticket)
  725. self.time_ticket = nil
  726. end
  727. end
  728. function svCmn:getCellPosition(index)
  729. local cur_item_index = index
  730. local anchor_point = cc.p(0.5,0.5)
  731. local _x, _y = 0, 0
  732. if self.dir == ScrollViewDir.horizontal then
  733. _x = self.start_x + self.item_width * anchor_point.x +(self.item_width + self.space_x) *(math.floor((index - 1) / self.row))
  734. _y = self.container_size.height -(self.start_y + self.item_height *(1 - anchor_point.y) +((index - 1) % self.row) *(self.item_height + self.space_y))
  735. else
  736. if self.start_pos == ScrollViewStartPos.top then
  737. _x = self.start_x + self.item_width * anchor_point.x + (self.item_width + self.space_x) *((index - 1) % self.col)
  738. _y = self.container_size.height -(self.start_y + self.item_height *(1 - anchor_point.y) +(math.floor((index - 1) / self.col)) *(self.item_height + self.space_y))
  739. else
  740. _x = self.start_x + self.item_width * anchor_point.x +(self.item_width + self.space_x) *((index - 1) % self.col)
  741. _y = self.start_y + self.item_height * anchor_point.y +(math.floor((index - 1) / self.col)) *(self.item_height + self.space_y)
  742. end
  743. end
  744. return _x, _y
  745. end
  746. --通过创建或复用的方式,获取index对应的cell对象
  747. function svCmn:getCacheCellByIndex(index)
  748. local cacheIndex = (index - 1) % self.cacheMaxSize + 1
  749. if not self.cacheList[cacheIndex] then
  750. local newCell = self:createNewCell(index)
  751. if newCell then
  752. newCell:setAnchorPoint(cc.p(0.5, 0.5))
  753. newCell:setPositionX(-10000)--隐藏
  754. self.cacheList[cacheIndex] = newCell
  755. self.scroll_view:addChild(newCell)
  756. end
  757. return newCell
  758. else
  759. return self.cacheList[cacheIndex]
  760. end
  761. end
  762. --cell设置位置,并刷新cell的UI
  763. function svCmn:updateCellAtIndex(index)
  764. if index > self.time_show_index then
  765. return
  766. end
  767. if not self.allCellList[index] then return end
  768. local cellData = self.allCellList[index]
  769. if cellData.cell == nil then
  770. cellData.cell = self:getCacheCellByIndex(index) --self.allCellList的cell赋值在这里
  771. end
  772. cellData.cell:setPosition(cellData.x, cellData.y)
  773. self:updateCellByIndex(cellData.cell, index)
  774. end
  775. function svCmn:clearTimeTicket()
  776. if self.time_ticket ~= nil then
  777. GlobalTimeTicket:getInstance():remove(self.time_ticket)
  778. self.time_ticket = nil
  779. end
  780. end
  781. function svCmn:getMaxSize()
  782. return self.container_size
  783. end
  784. function svCmn:getContainer()
  785. return self.container
  786. end
  787. function svCmn:scrollToPercentVertical( percent, time )
  788. if percent ~= percent then percent = 0 end
  789. self.scroll_view:scrollToPercentVertical(percent, time, true)
  790. end
  791. function svCmn:DeleteMe()
  792. doStopAllActions(self.container)
  793. self:clearTimeTicket()
  794. for k, item in ipairs(self.cacheList) do
  795. if item.DeleteMe then
  796. item:DeleteMe()
  797. end
  798. end
  799. self.allCellList = nil
  800. self.activeCellIdx = nil
  801. self.cacheList = nil
  802. self:removeAllChildren()
  803. self:removeFromParent()
  804. end

3.4 应用举例

  1. function ModuleTest:updateSVCmn()
  2. self.cellData = {
  3. [1] = {index = 1},
  4. [2] = {index = 2},
  5. [3] = {index = 3},
  6. [4] = {index = 4},
  7. [5] = {index = 5},
  8. [6] = {index = 6},
  9. [7] = {index = 7},
  10. [8] = {index = 8},
  11. [9] = {index = 9},
  12. [10] = {index = 10},
  13. [11] = {index = 11},
  14. [12] = {index = 12},
  15. }
  16. if not self.svCmn then
  17. local setting = {
  18. start_x = 18, space_x = 0,
  19. start_y = 26, space_y = 6,
  20. item_width = 686, item_height = 172,
  21. row = 1, col = 1,
  22. delay = 4, once_num = 1,
  23. }
  24. self.svCmn = svCmn.new(self.scr_con, cc.p(0,0) , ScrollViewDir.vertical, ScrollViewStartPos.top, self.scr_con:getContentSize(), setting, cc.p(0, 0))
  25. self.svCmn:registerScriptHandlerSingle(handler(self,self.createNewCell), ScrollViewFuncType.CreateNewCell)
  26. self.svCmn:registerScriptHandlerSingle(handler(self,self.numberOfCells), ScrollViewFuncType.NumberOfCells)
  27. self.svCmn:registerScriptHandlerSingle(handler(self,self.updateCellByIndex), ScrollViewFuncType.UpdateCellByIndex)
  28. end
  29. self.svCmn:reloadData()
  30. end
  31. function ModuleTest:createNewCell(width, height)
  32. local cell = ActionCommonItem.new()
  33. return cell
  34. end
  35. function ModuleTest:numberOfCells()
  36. if not self.cellData then return 0 end
  37. return #self.cellData
  38. end
  39. function ModuleTest:updateCellByIndex(cell, index)
  40. local onecellData = self.cellData[index]
  41. cell.root_wnd:getChildByName("label"):setString(onecellData.index)
  42. end

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/351611
推荐阅读
相关标签
  

闽ICP备14008679号