class ListViewAdapter { constructor(scrollView) { this.scrollView = scrollView; this.content = scrollView.content; this.scriptItems = []; this.dataList = []; // this.initialize(); this.updateTimer = 0; this.updateInterval = 0.1; this.lastContentPosY = 0; // use this variable to detect if we are scrolling up or down this.spawnCount = 7; //生成多少个预制资源 this.itemHeight = 0; this.bufferZone = 500; this.spacing = 0; //两个item之间的空隙 this.scriptName = ''; this.topHeight = 0; //顶部空间 this.shouldRemove = true; //初始化前是否需要清除所有节点 this.fuckingItem = null; } initialize(itemTemplate) { this.actualCount = this.dataList.length < this.spawnCount ? this.dataList.length : this.spawnCount; // let actualCount = this.dataList.length; this.scriptItems = []; if (this.itemHeight > 0) { this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight; } if (this.shouldRemove) { this.content.removeAllChildren(); } for (let i = 0; i < this.actualCount; ++i) { // spawn items, we only need to do this once let item = cc.instantiate(itemTemplate); if (this.itemHeight === 0) { this.itemHeight = item.height; // get total content height this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight; } this.content.addChild(item); item.setPosition(0, -(item.height * (0.5 + i) + this.spacing * (i + 1) + this.topHeight)); let itemScript = item.getComponent(this.scriptName); itemScript.setListViewAdapter(this); itemScript.updateItem(this.dataList[i], i, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); this.scriptItems.push(itemScript); // console.log('content height: ', this.content.height); } this.bufferZone = (this.scrollView.node.height + this.itemHeight) / 2; //第一次数据加载完成后发出回调 if (this.loadFinish != undefined) { this.loadFinish(); } } getPositionInView(item) { // get item position in scrollview's node space let worldPos = item.parent.convertToWorldSpaceAR(item.position); let viewPos = this.scrollView.node.convertToNodeSpaceAR(worldPos); return viewPos; } update(dt) { // this.updateTimer += dt; // if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame this.updateTimer = 0; let buffer = this.bufferZone; let isDown = this.content.y < this.lastContentPosY; // scrolling direction let offset = (this.itemHeight + this.spacing) * this.scriptItems.length; for (let i = 0; i < this.scriptItems.length; ++i) { let viewPos = this.getPositionInView(this.scriptItems[i].node); if (isDown) { // if away from buffer zone and not reaching top of content if (viewPos.y < -buffer && this.scriptItems[i].node.y + offset < 0) { // this.scriptItems[i].node.setPositionY(this.scriptItems[i].node.y + offset); let itemScript = this.scriptItems[i]; let itemId = itemScript._itemId - this.scriptItems.length; if (itemId < 0) { // this.scriptItems[i].node.active = false; continue; } // this.scriptItems[i].node.active = true; this.scriptItems[i].node.y = this.scriptItems[i].node.y + offset; itemScript.updateItem(this.dataList[itemId], itemId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); } } else { // if away from buffer zone and not reaching bottom of content if (viewPos.y > buffer && this.scriptItems[i].node.y - offset > -this.content.height) { // this.scriptItems[i].node.setPositionY(this.scriptItems[i].node.y - offset); let itemScript = this.scriptItems[i]; let itemId = itemScript._itemId + this.scriptItems.length; if (itemId >= this.dataList.length) { // this.scriptItems[i].node.active = false; continue; } // this.scriptItems[i].node.active = true; this.scriptItems[i].node.y = this.scriptItems[i].node.y - offset; itemScript.updateItem(this.dataList[itemId], itemId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); if (itemId === (this.dataList.length - 1)) { if (this.loadMore != undefined) { this.loadMore(); } } } } } // update lastContentPosY this.lastContentPosY = this.content.y; } updateItems(dataList, itemPrefab, scriptName, topHeight) { this.scriptName = scriptName; this.itemPrefab = itemPrefab; this.dataList = dataList; this.topHeight = (topHeight === undefined) ? 0 : topHeight; this.initialize(itemPrefab); } //更新数据 updateDataList(dataList, roomId) { this.dataList = dataList; for (let i = 0; i < this.scriptItems.length; ++i) { let itemScript = this.scriptItems[i]; if (itemScript.data.roomId == roomId) { let itemId = itemScript._itemId; itemScript.updateItem(this.dataList[itemId], itemId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); } } } //刷新已有数据 refreshItems(dataList) { this.dataList = dataList; this.update(); } addData(newdataList) { this.dataList = this.dataList.concat(newdataList); this.content.height = (this.itemHeight + this.spacing) * this.dataList.length; // get total content height } setLoadMoreCallBack(loadMore) { this.loadMore = loadMore; } setFirstLoadFinish(loadFinish) { this.loadFinish = loadFinish; } playRemoveItemAnimation(itemScript, animCallback) { this.dataList.splice(itemScript._itemId, 1); this.content.height = (this.itemHeight + this.spacing) * this.dataList.length; // get total content height let sequ = cc.sequence(cc.moveBy(0.2, -750, 0), animCallback); itemScript.node.runAction(sequ); } addItemsToDataList(model, head) { if (head) { this.dataList.unshift(model); } else { this.dataList.push(model); } this.actualCount = this.dataList.length < this.spawnCount ? this.dataList.length : this.spawnCount; //判断新的数据个数是否比设定的个数要大,不是的话就要创建新的item,是的话就直接复用已创建的 if (this.dataList.length <= this.spawnCount) { let item = cc.instantiate(this.itemPrefab); this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight; this.content.addChild(item); var i = 0; if (!head) { } item.setPosition(600, -(item.height * (0.5 + i) + this.spacing * (i + 1) + this.topHeight)); let action = cc.moveBy(0.2,cc.v2(-600, 0)); item.runAction(action); let itemScript = item.getComponent(this.scriptName); itemScript.setListViewAdapter(this); itemScript._itemId = 0; itemScript.updateItem(this.dataList[i], i, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); this.scriptItems.unshift(itemScript); if (head) { for (let i = 1; i < this.actualCount; ++i) { // spawn items, we only need to do this once let itemScript = this.scriptItems[i]; // this.scriptItems[i].node.y = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight); let moveY = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight); // let action = cc.moveTo(0.2,cc.v2(0, moveY)); // itemScript.node.runAction(action); itemScript.node.y = moveY; itemScript._itemId = i; } } } else { this.content.height = (this.itemHeight + this.spacing) * this.dataList.length + this.topHeight; //已生成足够多的预制资源,从底部抽取来使用 if (head) { let last = this.scriptItems.length - 1; let itemScript = this.scriptItems[last]; var index = 0; itemScript.updateItem(this.dataList[index], index, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); itemScript._itemId = 0; itemScript.node.y = -(this.itemHeight * (0.5 + index) + this.spacing * (index + 1) + this.topHeight); itemScript.node.x = 600; let action = cc.moveBy(0.2,cc.v2(-600, 0)); itemScript.node.runAction(action); var temp = this.scriptItems[last]; this.scriptItems.pop(); this.scriptItems.unshift(temp); for (let i = 1; i < this.scriptItems.length; ++i) { let itemScript = this.scriptItems[i]; let moveY = -(this.itemHeight * (0.5 + i) + this.spacing * (i + 1) + this.topHeight); // let action = cc.moveTo(0.2,cc.v2(0, moveY)); // itemScript.node.runAction(action); itemScript.node.y = moveY; itemScript._itemId = i; } } else { } } } updateItemsAndDataList(dataList,itemScript) { this.dataList = dataList; let index = itemScript._itemId; let scriptItems = this.scriptItems; if (this.dataList.length >= scriptItems.length) { // itemScript.scheduleOnce(() => { // itemScript.node.x = 0; // }, 0.2); for (let i = 0; i < scriptItems.length; ++i) { let itemNode = scriptItems[i].node; let script = scriptItems[i]; let itemId = script._itemId; if (itemId < this.dataList.length) { if (script._itemId > index) { let finish = cc.callFunc(() => { itemNode.y = itemNode.y - (this.itemHeight + this.spacing); // script.updateItem(this.dataList[itemId], itemId); script.updateItem(this.dataList[itemId], itemId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); }, this); let s = cc.sequence(cc.moveBy(0.2, 0, (this.itemHeight + this.spacing)), finish); itemNode.runAction(s); } else { // itemScript.scheduleOnce(() => { // script.updateItem(this.dataList[itemId], itemId); script.updateItem(this.dataList[itemId], itemId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); // }, 0.2); } } } } else { for (let i = 0; i < scriptItems.length; ++i) { let itemId = scriptItems[i]._itemId; if (itemId === itemScript._itemId) { this.scriptItems.splice(i, 1); } } for (let i = 0; i < scriptItems.length; ++i) { let itemNode = scriptItems[i].node; let script = scriptItems[i]; if (script._itemId > index) { let newId = script._itemId - 1; itemNode.runAction(cc.moveBy(0.2, 0, (this.itemHeight + this.spacing))); // script.updateItem(this.dataList[newId], newId); script.updateItem(this.dataList[newId], newId, (newBuildingInfo, newItemId) => { this.dataList[newItemId] = newBuildingInfo; }); } } itemScript.node.destroy(); } } removeItem(itemScript) { let finish = cc.callFunc(() => { this.updateItemsAndDataList(itemScript); }); this.playRemoveItemAnimation(itemScript, finish); } onDestroy() { this.scriptItems = []; this.content.removeAllChildren(); } } module.exports = ListViewAdapter;