cc.Class({
extends: cc.Component,
properties: {
// item:[cc.Prefab],
// itemData:[],//item数据
// scrollView:cc.ScrollView,
// itemInterval:0, //间距
// firstItemData:{},
// lastItemData:{},
// itemArr:[],
// itemNode:[],
},
//得到此脚本的节点下总控制脚本,用来传递给它的所有成员item;
setTarget(target) {
this.target = target;
},
//itemData是item数据,itemPosMap是滚动条滚动时要用到的item位置数据.
init(itemData, scrollView, item, itemInterval, scrollViewCanFix) {
if (!arguments[0]) {
return false;
}
this.itemData = itemData; //item数据
this.scrollView = scrollView;
this.item = item;
this.itemInterval = itemInterval || 0; //间距
this.scrollViewCanFix = scrollViewCanFix || true; //是否自动修正
//初始化各类属性
this.content = this.scrollView.content;
this.layerHeight = this.scrollView.node.height;
this.firstItemIndex = 0;
this.lastItemIndex = 0;
this.firstItemData = {};
this.lastItemData = {};
this.itemArr = [];
this.itemNode = [];
this.itemPosMap = new Map();
this.initItemData = true;
this.count = 0;
for (let i = 0; i < this.item.length; i++) {
this.itemNode[i] = cc.instantiate(this.item[i]);
}
let time1 = new Date().getTime();
this.initItem();
this.getItemPos(0);
cc.log('tableView结束:' + this.testTime(time1));
},
getItemPos(index) {
for (let i = index; i < this.itemData.length; i++) {
let obj = {}
let y;
if (i === 0) {
obj.startPos = 0;
} else {
obj.startPos = this.itemPosMap.get(i - 1).endPos;
}
let j = this.itemData[i].pfbType;
obj.endPos = obj.startPos + this.itemNode[j].height + this.itemInterval;
this.itemPosMap.set(i, obj);
}
this.updateContentHeigh(this.itemPosMap.get(this.itemData.length - 1).endPos);
},
initItem() {
//实例化所有用到的item;j控制实例化item的数目,暂定超出两个
let j = 0;
for (let i = 0; i < this.itemData.length; i++) {
if (this.content.height > this.layerHeight) {
j++
if (j > 2) {
break;
}
}
let y;
if (i === 0) {
y = 0;
} else {
y = this.itemArr[i - 1].y - this.itemArr[i - 1].height - this.itemInterval;
}
this.addItemNode(i, y);
}
},
addItemNode(i, y) {
let pfbType = this.itemData[i].pfbType;
let item = cc.instantiate(this.itemNode[pfbType]);
item.parent = this.content;
item.pfbType = pfbType;
item.index = i;
if (i === 0) {
item.y = 0;
} else {
item.y = y;
}
item.x = 0;
//对item赋值
item.getComponent(cc.Component).init(this.itemData[i], this);
this.itemArr.push(item);
},
updateContentHeigh(num) {
this.content.height = num > this.layerHeight ? num : this.layerHeight;
cc.log('滚动条高度:', this.content.height);
},
//触摸滚动条的函数回调
//第一,滚动条
callback(event, eventType) {
cc.log(event.type || eventType)
if (this.content.height > this.layerHeight) {
let firstItemPos = this.scrollView.getScrollOffset().y;
let lastItemPos = firstItemPos + this.layerHeight;
if (firstItemPos < 0) return;
if (this.initItemData) {
this.initItemData = false;
this.updateFirstItemIndex(firstItemPos);
this.itemCanMoveDown = true;
this.updateLastItemIndex(lastItemPos);
this.itemCanMoveDown = false;
}
//超出边界直接返回.
//滚动条向上滑动可能会触发的函数
if (firstItemPos > this.firstItemData.endPos) {
if (this.lastItemIndex + 1 < this.itemData.length) {
this.updateFirstItemIndex(firstItemPos);
}
this.count++;
}
if (lastItemPos > this.lastItemData.endPos) {
if (this.lastItemIndex + 1 < this.itemData.length) {
this.itemCanMoveDown = true;
this.updateLastItemIndex(lastItemPos);
this.itemCanMoveDown = false;
}
}
//滚动条向下滑动可能会触发的函数
if (lastItemPos < this.lastItemData.startPos) {
this.updateLastItemIndex(lastItemPos);
this.count--;
}
if (firstItemPos < this.firstItemData.startPos) {
this.itemCanMoveUp = true;
this.updateFirstItemIndex(firstItemPos);
this.itemCanMoveUp = false;
}
}
},
updateFirstItemIndex() {
let num = this.firstItemIndex;
if (this.itemCanMoveUp && num > this.getItemIndex()()[0] && num > 0) {
this.itemMoveUp(this.firstItemIndex - 1);
}
this.updateItemIndex();
},
updateLastItemIndex() {
let num = this.lastItemIndex;
if (this.itemCanMoveDown && num < this.getItemIndex()()[1] && num + 1 < this.itemData.length) {
this.itemMoveDown(this.lastItemIndex + 1);
}
this.updateItemIndex();
},
testTime(time) {
let timestamp = new Date().getTime() - time;
return timestamp
},
updateItemIndex() {
cc.log(this.firstItemIndex, this.lastItemIndex, this.itemArr, this.itemData)
},
//得到滚动条此时状态下应有的itemNode元素,包括滚动条上方一个,滚动条下方一个.
getItemIndex() {
return (function () {
let firstItemPos = this.scrollView.getScrollOffset().y;
let lastItemPos = firstItemPos + this.layerHeight;
let arr = [];
for (let [key, value] of this.itemPosMap.entries()) {
//判断状态的位置关系是[);
let status1 = value.startPos <= firstItemPos && value.endPos > firstItemPos;
let status2 = value.startPos >= firstItemPos && value.endPos < lastItemPos;
let status3 = value.startPos <= lastItemPos && value.endPos > lastItemPos;
if (status1) {
this.firstItemData.startPos = value.startPos;
this.firstItemData.endPos = value.endPos;
this.firstItemIndex = key;
arr.push(key);
}
if (status3) {
this.lastItemData.startPos = value.startPos;
this.lastItemData.endPos = value.endPos;
this.lastItemIndex = key;
arr.push(key);
}
}
return arr;
}).bind(this);
},
//firstIndex 滚动条顺序是从上到下开始遍历
itemMoveUp(num) {
if (num < 0 || this.lastItemIndex + 1 < num || num + 1 > this.itemData.length) {
return;
}
if (!this.hasItem(num)) {
this.itemMove()(num, -this.itemPosMap.get(num).startPos);
}
num++;
return this.itemMoveUp(num);
},
itemMoveDown(num) {
if (num < 0 || this.firstItemIndex - 1 > num || num + 1 > this.itemData.length) {
return;
}
if (!this.hasItem(num)) {
this.itemMove()(num, -this.itemPosMap.get(num).startPos);
}
num--;
return this.itemMoveDown(num);
},
//判断指定index位置是否存在itemNode.
hasItem(index) {
for (let i = 0; i < this.itemArr.length; i++) {
if (this.itemArr[i].index === index) {
return true;
}
}
return false;
},
//得到要移动的item的索引index,
//逻辑判断,第一种情况,修改itemArr数组的某个对象,第二种情况实例化一个新itemNode
itemMove(index, y) {
return (function (index, y) {
for (let i = 0; i < this.itemArr.length; i++) {
let status1 = this.itemArr[i].index < this.firstItemIndex - 1 ? true : false;
let status2 = this.itemArr[i].index > this.lastItemIndex + 1 ? true : false;
let status3 = this.itemArr[i].pfbType === this.itemData[index].pfbType;
cc.log('item的索引', this.firstItemIndex, this.lastItemIndex)
if (status1 && status3 || status2 && status3) {
cc.log(i, index, this.itemArr, this.content.height);
//给item赋值还有设置位置
this.itemArr[i].index = index;
this.itemArr[i].y = y;
this.itemArr[i].getComponent(cc.Component).init(this.itemData[index], this);
return;
}
}
this.addItemNode(index, y);
}).bind(this);
},
addItem(obj) {
this.itemData.push(obj);
this.getItemPos(this.itemData.length - 1);
let endPos = this.itemPosMap.get(this.itemData.length - 1).endPos;
if (endPos - this.layerHeight > 0) {
let startPos = endPos - this.layerHeight;
for (let i = this.itemData.length - 1; i >= 0; i--) {
if (this.itemPosMap.get(i).endPos > startPos && this.itemPosMap.get(i).startPos <= startPos) {
this.firstItemIndex = i;
}
}
this.scrollView.scrollToBottom();
this.lastItemIndex = this.itemData.length - 1;
let num = this.firstItemIndex - 1 > 0 ? (this.firstItemIndex - 1) : 0;
this.itemMoveUp(num);
} else {
this.firstItemIndex = 0;
this.lastItemIndex = this.itemData.length - 1;
this.itemMoveUp(this.firstItemIndex);
}
},
clearItem() {
this.itemData = [];
this.itemPosMap.clear();
this.scrollView.scrollToTop();
this.content.height = 0;
for (let i in this.itemArr) {
this.itemArr[i].index = -1;
this.itemArr[i].y = 3000;
}
},
deleteItem(i) {
this.itemData.splice(i, 1);
this.getItemPos(this.itemData.length - 1);
//改变this.itemArr的内容
for (let j = 0; j < this.itemArr.length; j++) {
if (this.itemArr[j].index === i) {
this.itemArr[j].index = -1;
this.itemArr[j].y = 3000;
}
if (this.itemArr[j].index > i) {
let num = this.itemArr[j].index;
// cc.log(j,this.itemArr[j].index)
this.itemArr[j].y = -this.itemPosMap.get(num - 1).startPos;
this.itemArr[j].index = num - 1;
cc.log(this.itemArr[j].index, this.itemArr[j].y)
}
}
this.updateContentHeigh(this.itemPosMap.get(this.itemData.length - 1).endPos);
this.itemMoveUp(this.firstItemIndex);
},
resetItemData(index) {
for (let i = 0; i < this.itemArr.length; i++) {
if (this.itemArr[i].index === index) {
let js = this.itemArr[i].getComponent(cc.Component);
js.init(this.itemData[index], this);
break;
}
}
},
resetItemSize(index, infoHeight) {
let func = (function (index, infoHeight) {
for (let i = 0; i < this.itemArr.length; i++) {
if (this.itemArr[i].index > index) {
this.itemArr[i].y -= infoHeight;
}
}
for (let [key, value] of this.itemPosMap.entries()) {
if (key === index) {
value.endPos += infoHeight;
}
if (key > index) {
value.endPos += infoHeight;
value.startPos += infoHeight;
}
}
this.lastResetItemInfoHeight = infoHeight;
this.lastResetItemIndex = index;
}).bind(this);
if (this.lastResetItemIndex !== null && this.lastResetItemInfoHeight) {
if (this.lastResetItemIndex === index) {
func(this.lastResetItemIndex, -this.lastResetItemInfoHeight);
this.lastResetItemIndex = null;
this.lastResetItemInfoHeight = 0;
} else {
func(this.lastResetItemIndex, -this.lastResetItemInfoHeight);
func(index, infoHeight);
}
} else {
func(index, infoHeight);
}
this.updateContentHeigh(this.itemPosMap.get(this.itemData.length - 1).endPos);
},
});
3赞
手动捧场
建议搞个demo发布
大佬,有空弄个demo,学习学习
已经弄好了.
已经弄了一个简单的.
需要注意的几点,预制体根节点高度是用来排版的,预制体根节点的第一个组件必须是脚本.
用这个实现聊天还有战绩都挺方便的,
66666666666666666
没bug的话,mark下先
手动点赞
这个和layout组件的grid模式有什么不同?
这个主要是预制体复用的,应该说完全不同.
应该和官方示例listview相比,我这个功能强大一点.支持多个类型的预制体,支持聊天场景的增删,支持战绩场景的下拉列表.
删除后布局有点问题
这个必须得赞啊。
mark~~
方便发一下源码吗,我帮你看下.
删除有BUG