UICollectionView

时间:2016-02-01 08:23:37

标签: ios objective-c swift uicollectionview uicollectionviewcell

我想实现这样的事情:

enter image description here

我使用具有水平流和自定义单元格的集合视图来设置大小(每个单元格根据文本具有不同的大小)。问题是集合视图就像一个矩阵,当同一列上有一个小元素和一个大元素时,同一行的元素之间会有更大的空间。 现在我有这样的事情: enter image description here

使用集合视图是否有任何解决方案?或者我应该使用滚动视图?

谢谢!

5 个答案:

答案 0 :(得分:1)

对于Flow布局Swift

override func viewDidLoad() {

    var flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    flowLayout.estimatedItemSize = CGSizeMake(view.frame.width - 10, 10)
    flowLayout.minimumLineSpacing = 2
    flowLayout.minimumInteritemSpacing = 2
    flowLayout.sectionInset = UIEdgeInsetsMake(2, 2, 0, 0)

    collectionView.dataSource=self
    collectionView.delegate=self
}



func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 90, height: 50) // The size of one cell
}


func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    return CGSizeMake(self.view.frame.width, 0)  // Header size
}



func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
    let frame : CGRect = self.view.frame
    let margin: CGFloat  = 0
    return UIEdgeInsetsMake(0, margin, 0, margin) // margin between cells
}

答案 1 :(得分:1)

您必须编写自己的自定义流布局子类或使用已编写的子类(第三方)。覆盖(来自UICollectionViewLayout)需要考虑的主要功能是:

-(void)prepareLayout
-(CGSize)collectionViewContentSize
-(UICollectionViewLayoutAttributes*) layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
-(UICollectionViewLayoutAttributes *) layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect

另请注意,当您使用UICollectionViewFlowLayout时,项目之间的水平空间主要来自以下控制器:

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;

答案 2 :(得分:0)

这是对我有用的解决方案:

class CustomHorizontalLayout: UICollectionViewFlowLayout 
{
    var _contentSize = CGSizeZero
    var itemAttibutes: NSMutableArray = NSMutableArray()
    var delegate: CustomHorizontalLayoutDelegate!

    override func prepareLayout() {
        super.prepareLayout()
        self.itemAttibutes = NSMutableArray()

        // use a value to keep track of left margin
        var upLeftMargin: CGFloat = self.sectionInset.left;
        var downLeftMargin: CGFloat = self.sectionInset.left;

        let numberOfItems = self.collectionView!.numberOfItemsInSection(0)
        for var item = 0; item < numberOfItems; item++ {

            let indexPath = NSIndexPath(forItem: item, inSection: 0)
            let refAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

            let size = delegate.collectionView(collectionView!, sizeTagAtIndexPath: indexPath)

            if (refAttributes.frame.origin.x == self.sectionInset.left) {
                upLeftMargin = self.sectionInset.left
                downLeftMargin = self.sectionInset.left
            } else {
                // set position of attributes
                var newLeftAlignedFrame = refAttributes.frame
                newLeftAlignedFrame.origin.x = (indexPath.row % 2 == 0) ? upLeftMargin :downLeftMargin
                newLeftAlignedFrame.origin.y = (indexPath.row % 2 == 0) ? 0 :40
                newLeftAlignedFrame.size.width = size.width
                newLeftAlignedFrame.size.height = size.height
                refAttributes.frame = newLeftAlignedFrame
            }
            // calculate new value for current margin
            if(indexPath.row % 2 == 0)
            {
                upLeftMargin += refAttributes.frame.size.width + 8
            }
            else
            {
                downLeftMargin += refAttributes.frame.size.width + 8
            }

            self.itemAttibutes.addObject(refAttributes)

        }

        _contentSize = CGSizeMake(max(upLeftMargin, downLeftMargin), 80)
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {

        return self.itemAttibutes.objectAtIndex(indexPath.row) as? UICollectionViewLayoutAttributes
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?  {

        let predicate = NSPredicate { (evaluatedObject, bindings) -> Bool in
            let layoutAttribute = evaluatedObject as! UICollectionViewLayoutAttributes
            return CGRectIntersectsRect(rect, layoutAttribute.frame)
        }
        return (itemAttibutes.filteredArrayUsingPredicate(predicate) as! [UICollectionViewLayoutAttributes])
    }

    override func collectionViewContentSize() -> CGSize {
        return _contentSize
    }

    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        return false
    }
}

答案 3 :(得分:0)

这是一个灵活宽度的解决方案。创建一个新的Swift.File粘贴代码 然后在ViewController中实现委托方法。

import UIKit

protocol CameraLayoutDelegate: class {

    func collectionView(_ collectionView:UICollectionView, widthForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat
}


class CameraLayout: UICollectionViewLayout {

    var delegate: CameraLayoutDelegate!
    var numberOfRows = 2

    private var cache = [UICollectionViewLayoutAttributes]()
    private var contentWidth: CGFloat = 0

    private var height: CGFloat {
        get {
            return (collectionView?.frame.size.height)!
        }
    }

    override var collectionViewContentSize: CGSize {
        return CGSize(width: contentWidth, height: height)
    }


    override func prepare() {
        if cache.isEmpty {
            let columumnsHeight = (height / CGFloat(numberOfRows))

            var yOffset = [CGFloat]()

            for column in 0..<numberOfRows {
                yOffset.append(CGFloat(column) * (columumnsHeight + 8))
            }

            var xOffset = [CGFloat](repeating: 0, count: numberOfRows)
            var column = 0

            for item in 0..<collectionView!.numberOfItems(inSection: 0) {
                let indexPath = IndexPath(item: item, section: 0)
                let width = delegate.collectionView(collectionView!, widthForPhotoAtIndexPath: indexPath)
                let frame = CGRect(x: xOffset[column], y: yOffset[column], width: width, height: columumnsHeight)
                let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
                attributes.frame = frame
                cache.append(attributes)
                contentWidth = max(contentWidth, frame.maxX)
                xOffset[column] = xOffset[column] + width + 8
                column = column >= (numberOfRows - 1) ? 0 : column + 1
               //
            }
        }
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var layoutAttributes =  [UICollectionViewLayoutAttributes] ()

        for attributes in cache {
            if attributes.frame.intersects(rect) {
                layoutAttributes.append(attributes)
            }
        }
        return layoutAttributes
    }

}

的ViewController:

    let layout = CameraLayout()
    layout.delegate = self
    collectionView.collectionViewLayout = layout



extension ViewController: CameraLayoutDelegate {

    func collectionView(_ collectionView: UICollectionView, widthForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {
        return .........
    }
}

答案 4 :(得分:-1)

尝试使用SKRaggyCollectionViewLayout。将collectionView布局类设置为SKRaggyCollectionViewLayout并连接它:

@property (nonatomic, weak) IBOutlet SKRaggyCollectionViewLayout *layout;

并设置它的属性:

self.layout.numberOfRows = 2;
self.layout.variableFrontierHeight = NO;

https://github.com/tralf/SKRaggyCollectionViewLayout

相关问题