mirror of
				https://github.com/568071718/creator-collection-view
				synced 2025-11-04 13:25:29 +00:00 
			
		
		
		
	增加一个 grid-layout 网格布局
This commit is contained in:
		
							
								
								
									
										140
									
								
								list-3x/assets/lib/grid-layout.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								list-3x/assets/lib/grid-layout.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
import { math, UITransform, warn } from "cc";
 | 
			
		||||
import { YXCollectionView, YXIndexPath, YXLayout, YXLayoutAttributes } from "./yx-collection-view";
 | 
			
		||||
 | 
			
		||||
export class GridLayout extends YXLayout {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 节点大小  
 | 
			
		||||
     */
 | 
			
		||||
    itemSize: math.Size = new math.Size(100, 100)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 垂直间距  
 | 
			
		||||
     */
 | 
			
		||||
    horizontalSpacing: number = 0
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 水平间距  
 | 
			
		||||
     */
 | 
			
		||||
    verticalSpacing: number = 0
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 整体对齐方式  
 | 
			
		||||
     * 0靠左 1居中 2靠右  
 | 
			
		||||
     */
 | 
			
		||||
    alignment: number = 1
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取每行最多可以容纳多少个节点  
 | 
			
		||||
     */
 | 
			
		||||
    protected getMaxItemsPerRow(collectionView: YXCollectionView): number {
 | 
			
		||||
        if (this._maxItemsPerRow == null) {
 | 
			
		||||
            let num = 1
 | 
			
		||||
            const width = collectionView.node.getComponent(UITransform).contentSize.width
 | 
			
		||||
            while ((num * this.itemSize.width + (num - 1) * this.horizontalSpacing) <= width) { num++ }
 | 
			
		||||
            num = Math.max(1, num - 1)
 | 
			
		||||
            this._maxItemsPerRow = num
 | 
			
		||||
        }
 | 
			
		||||
        return this._maxItemsPerRow
 | 
			
		||||
    }
 | 
			
		||||
    protected _maxItemsPerRow: number = null
 | 
			
		||||
 | 
			
		||||
    prepare(collectionView: YXCollectionView): void {
 | 
			
		||||
        if (collectionView.scrollDirection === YXCollectionView.ScrollDirection.VERTICAL) {
 | 
			
		||||
            this._prepare_vertical(collectionView)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        if (collectionView.scrollDirection === YXCollectionView.ScrollDirection.HORIZONTAL) {
 | 
			
		||||
            warn(`GridLayout 仅支持垂直方向排列`)
 | 
			
		||||
            this._prepare_vertical(collectionView)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected _prepare_vertical(collectionView: YXCollectionView) {
 | 
			
		||||
        collectionView.scrollView.horizontal = false
 | 
			
		||||
        collectionView.scrollView.vertical = true
 | 
			
		||||
 | 
			
		||||
        let attrs: YXLayoutAttributes[] = []
 | 
			
		||||
        let contentSize = collectionView.node.getComponent(UITransform).contentSize.clone()
 | 
			
		||||
 | 
			
		||||
        // 容器宽度
 | 
			
		||||
        const width = contentSize.width
 | 
			
		||||
 | 
			
		||||
        // 计算每行最多可以放多少个节点
 | 
			
		||||
        this._maxItemsPerRow = null
 | 
			
		||||
        let num = this.getMaxItemsPerRow(collectionView)
 | 
			
		||||
 | 
			
		||||
        // 根据设置的对齐方式计算左边距
 | 
			
		||||
        let left = 0
 | 
			
		||||
        if (this.alignment == 1) {
 | 
			
		||||
            let maxWidth = (num * this.itemSize.width + (num - 1) * this.horizontalSpacing) // 每行节点总宽度
 | 
			
		||||
            left = (width - maxWidth) * 0.5
 | 
			
		||||
        }
 | 
			
		||||
        if (this.alignment == 2) {
 | 
			
		||||
            let maxWidth = (num * this.itemSize.width + (num - 1) * this.horizontalSpacing) // 每行节点总宽度
 | 
			
		||||
            left = width - maxWidth
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const numberOfSections = collectionView.getNumberOfSections()
 | 
			
		||||
        if (numberOfSections > 1) { warn(`GridLayout 暂时不支持分区模式`) }
 | 
			
		||||
 | 
			
		||||
        const numberOfItems = collectionView.getNumberOfItems(0)
 | 
			
		||||
        for (let index = 0; index < numberOfItems; index++) {
 | 
			
		||||
 | 
			
		||||
            // 计算这个节点是第几行
 | 
			
		||||
            let row = Math.floor(index / num)
 | 
			
		||||
 | 
			
		||||
            // 计算这个节点是第几列
 | 
			
		||||
            let column = index % num
 | 
			
		||||
 | 
			
		||||
            // 计算节点 origin
 | 
			
		||||
            let x = left + (this.itemSize.width + this.horizontalSpacing) * column
 | 
			
		||||
            let y = (this.itemSize.height + this.verticalSpacing) * row
 | 
			
		||||
 | 
			
		||||
            let attr = YXLayoutAttributes.layoutAttributesForCell(new YXIndexPath(0, index))
 | 
			
		||||
            attr.frame.x = x
 | 
			
		||||
            attr.frame.y = y
 | 
			
		||||
            attr.frame.width = this.itemSize.width
 | 
			
		||||
            attr.frame.height = this.itemSize.height
 | 
			
		||||
            attrs.push(attr)
 | 
			
		||||
 | 
			
		||||
            // 更新内容高度
 | 
			
		||||
            contentSize.height = Math.max(contentSize.height, attr.frame.yMax)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.attributes = attrs
 | 
			
		||||
        this.contentSize = contentSize
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    initOffset(collectionView: YXCollectionView): void {
 | 
			
		||||
        collectionView.scrollView.scrollToTop()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[] {
 | 
			
		||||
        return this.visibleElementsInRect(rect, collectionView)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 抽出来一个方法用来优化列表性能  
 | 
			
		||||
     * 在优化之前,可以先看一下 @see YXLayout.layoutAttributesForElementsInRect 关于返回值的说明  
 | 
			
		||||
     */
 | 
			
		||||
    protected visibleElementsInRect(rect: math.Rect, collectionView: YXCollectionView) {
 | 
			
		||||
        if (this.attributes.length <= 100) { return this.attributes } // 少量数据就不查了,直接返回全部  
 | 
			
		||||
 | 
			
		||||
        // 根据当前范围直接计算出一个区间  
 | 
			
		||||
        const startRow = Math.floor(rect.y / (this.itemSize.height + this.verticalSpacing))
 | 
			
		||||
        const endRow = Math.ceil(rect.yMax / (this.itemSize.height + this.verticalSpacing))
 | 
			
		||||
 | 
			
		||||
        // 计算每行最多可以放多少个节点
 | 
			
		||||
        let num = this.getMaxItemsPerRow(collectionView)
 | 
			
		||||
 | 
			
		||||
        // 计算索引区间
 | 
			
		||||
        const startIdx = startRow * num
 | 
			
		||||
        const endIdx = endRow * num
 | 
			
		||||
 | 
			
		||||
        // 只返回区间节点的布局属性
 | 
			
		||||
        return this.attributes.slice(startIdx, endIdx)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								list-3x/assets/lib/grid-layout.ts.meta
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								list-3x/assets/lib/grid-layout.ts.meta
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "ver": "4.0.23",
 | 
			
		||||
  "importer": "typescript",
 | 
			
		||||
  "imported": true,
 | 
			
		||||
  "uuid": "02a96aac-8c52-4201-b8af-c7ed49aae6d4",
 | 
			
		||||
  "files": [],
 | 
			
		||||
  "subMetas": {},
 | 
			
		||||
  "userData": {}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user