| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- import ListViewItem from "./ListViewItem";
-
- const {ccclass, property} = cc._decorator;
-
- /**
- * 实现scrollview item循环滚动 ,目前只支持垂直
- */
-
-
- /**
- * count: length of listview
- * listViewData: data of listview
- */
- type ListViewData = {
- count: number,
- listViewData: any
- }
-
- @ccclass
- export default class ListView extends cc.Component {
- // @property(cc.Label)
- // itemCountLabel: cc.Label = null;
-
- @property({
- type: cc.Prefab,
- tooltip: "listview单元格,仅支持大小相等的单元格"
- })
- prefabCell: cc.Prefab = null; // listview单元格,仅支持大小相等的单元格
-
- @property({
- type: cc.ScrollView,
- tooltip: "找到scrollview的控件"
- })
- scrollView:cc.ScrollView = null; // 找到scrollview的控件
-
- @property(cc.Integer)
- spacing: number = 0; // listview单元格间距
-
- // @property(cc.String)
- // cellScriptName: string = "";
-
- @property({
- type: cc.Node,
- tooltip: "找到scrollview的content"
- })
- content: cc.Node = null; // 找到scrollview的content, 搭配scrollview使用
-
- @property({
- type: cc.Integer,
- tooltip: "缓冲区总个数,即上下缓冲区分别bufferZoneCount / 2"
- })
- bufferZoneCount: number = 4; // 缓冲区总个数,即上下缓冲区分别bufferZoneCount / 2
-
- items: cc.Node[] = [];
-
- itemCount: number = 0;
- prefabCellHeight: number = 0;
- prefabCellWidth: number = 0;
-
- updateTimer: number = 0;
-
- updateInterval: number = 0.1;
-
- lastContentPosX: number = 0;
-
- lastContentPosY: number = 0;
-
- _bufferZone: number = 0; //when item is away from bufferZone, we relocate it
- _spawnCount: number = 0; // how many items we actually spawn
- _totalCount: number = 0; // how many items we need for the whole list
- _isUpdate: boolean = false;
- _itemData: any;
- // _listViewItem: ListViewItem = new ListViewItem();
-
- onLoad () {
- this._bufferZone = this.scrollView.node.height;
- this.content.anchorX = 0.5;
- this.content.anchorY = 1;
- if (this.scrollView.horizontal) {
- this._bufferZone = this.scrollView.node.width;
- this.content.anchorX = 0;
- this.content.anchorY = 0.5;
- }
- this.prefabCellHeight = this.prefabCell.data.height;
- this.prefabCellWidth = this.prefabCell.data.width;
- this.scrollView.node.on('scrolling', this.scrolling.bind(this), this);
- this.scrollView.node.on('scroll-ended', this.scrollEnded.bind(this), this);
- // this.init({count: 20, listViewData: null});
- }
-
- /**
- * 初始化ListView组件
- * @param listViewData ListViewData
- */
- public init (listViewData: ListViewData) {
- this.content.destroyAllChildren();
- this.items = [];
- this.lastContentPosY = 0;
- this.lastContentPosX = 0;
- this.itemCount = listViewData.count;
- this._itemData = listViewData.listViewData;
-
- if (this.scrollView.vertical && this.scrollView.horizontal) {
- return;
- }
-
- this._totalCount = this.itemCount;
- this._spawnCount = Math.floor(this._bufferZone / (this.prefabCellHeight + this.spacing)) + this.bufferZoneCount;
- if (this.scrollView.horizontal) {
- this._spawnCount = Math.floor(this._bufferZone / (this.prefabCellWidth + this.spacing)) + this.bufferZoneCount;
- }
-
- if (this._spawnCount > this._totalCount) {
- this._spawnCount = this._totalCount;
- }
-
- if (this.scrollView.vertical) {
- this.scrollView.scrollToTop();
- this.content.height = this._totalCount * (this.prefabCellHeight + this.spacing) + this.spacing; // get total content height
- } else if (this.scrollView.horizontal) {
- this.scrollView.scrollToLeft();
- this.content.width = this._totalCount * (this.prefabCellWidth + this.spacing) + this.spacing; // get total content width
- }
- for (let i = 0; i < this._spawnCount; ++i) { // spawn items, we only need to do this once
- let item = cc.instantiate(this.prefabCell);
- this.content.addChild(item);
- item.getComponent(ListViewItem).initData(i, this._itemData);
-
- if (this.scrollView.vertical) {
- item.setPosition(0, -item.height * (0.5 + i) - this.spacing * (i + 1));
- } else if (this.scrollView.horizontal) {
- item.setPosition(item.width * (i + 0.5) + this.spacing * (i + 1), 0);
- }
- this.items.push(item);
- }
- }
-
- /**
- * 获取item在scrollview中的位置
- * @param item item位置
- */
- private 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;
- }
-
- /**
- * 监听:滚动时更新
- */
- private scrolling(){
- this._isUpdate = true;
- }
-
- /**
- * 监听:滚动停止时不执行逻辑
- */
- private scrollEnded() {
- this._isUpdate = false;
- }
-
-
-
- update (dt) {
- // this.itemCountLabel.string = (this.content.childrenCount).toString();
-
- // scrolling excute or don't excute
- if (!this._isUpdate) return;
-
- this.updateTimer += dt;
- if (this.updateTimer < this.updateInterval) return; // we don't need to do the math every frame
- this.updateTimer = 0;
- let items = this.items;
- let buffer = this._bufferZone;
- if (this.scrollView.vertical) {
- let isDown = this.scrollView.content.y < this.lastContentPosY; // scrolling direction
- let offset = (this.prefabCellHeight + this.spacing) * items.length;
- for (let i = 0; i < items.length; ++i) {
- let viewPos = this.getPositionInView(items[i]);
- let item = items[i].getComponent(ListViewItem);
- if (isDown) {
- // if away from buffer zone and not reaching top of content
- if (viewPos.y < -buffer && items[i].y + offset < 0) {
- items[i].y = items[i].y + offset;
- items[i].getComponent(ListViewItem).initData(item.itemId -items.length, this._itemData);
- }
- } else {
- // if away from buffer zone and not reaching bottom of content
- if (viewPos.y > buffer / 2 + (this.prefabCellHeight + this.spacing) / 2 && items[i].y - offset > -this.content.height) {
- items[i].y = items[i].y - offset;
- items[i].getComponent(ListViewItem).initData(item.itemId + items.length, this._itemData);
- }
- }
- }
- // update lastContentPosY
- this.lastContentPosY = this.scrollView.content.y;
- } else if (this.scrollView.horizontal) {
- let isRight = this.scrollView.content.x > this.lastContentPosX; // scrolling direction
- let offset = (this.prefabCellWidth + this.spacing) * items.length;
- for (let i = 0; i < items.length; ++i) {
- let viewPos = this.getPositionInView(items[i]);
- if (isRight) {
- // if away from buffer zone and not reaching top of content
- if (viewPos.x > buffer / 2 + (this.prefabCellWidth + this.spacing) / 2 && items[i].x - offset > 0) {
- items[i].x = items[i].x - offset;
- }
- } else {
- // if away from buffer zone and not reaching bottom of content
- if (viewPos.x < -buffer / 2 - (this.prefabCellWidth + this.spacing) / 2 && items[i].x + offset < this.content.width) {
- items[i].x = items[i].x + offset;
- }
- }
- }
- // update lastContentPosX
- this.lastContentPosX = this.scrollView.content.x;
- }
- }
- };
|