UICollectionView 单元格不占用 UICollectionView 的宽度

UICollectionView cells do not take up width of UICollectionView

UICollectionView 宽度会因设备而异,因为它被限制为达到视图的水平边距。 collectionView 的布局是 Flow。我使用 UICollectionView 的唯一原因是 space 图像在不同尺寸的设备上均匀分布,并且所有这些图像都将具有点击手势识别器。行数是可变的,因为图像图标的数量会有所不同。显然这是我追求的方法:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: collectionViewWidth/6, height: collectionViewWidth/6);
}

我试过这样做:

var collectionViewWidth: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.dataSource = self
}

override func viewDidAppear(animated: Bool) {
    collectionViewWidth = collectionView.collectionViewLayout
        .collectionViewContentSize().width
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: collectionViewWidth/6, height: collectionViewWidth/6);
}

但是我在代码中尝试的任何事情都不会对最终输出产生任何影响,这就是最终输出(忘记不在 UICollectionView 中的图像 - 它们将被删除):

我在界面生成器中更改了单元格的大小,结果是这样的:

所以我有两个问题:

为什么上图中的单元格没有走到UICollectionView的边缘?

如何在 运行 时以编程方式设置单元格大小,使我的 UICollectionView 在所有设备尺寸上都有 6 列?

这是我的 ViewController 的所有代码,其中包含 UICollectionView:

import UIKit

class DressingRoomViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    let identifier = "cellIdentifier"
    let dataSource = DataSource()
    var collectionViewWidth: CGFloat = 0.0

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.dataSource = self
    }

    override func viewDidAppear(animated: Bool) {
        collectionViewWidth = collectionView.collectionViewLayout
            .collectionViewContentSize().width
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func prepareForSegue(  segue: UIStoryboardSegue,
                                    sender: AnyObject?) {
        if (segue.identifier == "dressingRoom2MyOutfits") {
            let myOutfitsViewController = segue.destinationViewController
                as! MyOutfitsViewController
        }
    }
}



// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {

    func numberOfSectionsInCollectionView(
        collectionView: UICollectionView) -> Int {
            return dataSource.groups.count
    }

    func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int {
            return dataSource.numbeOfRowsInEachGroup(section)
    }

    func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
            identifier,forIndexPath:indexPath) as! FruitCell

        let fruits: [Fruit] = dataSource.fruitsInGroup(indexPath.section)
        let fruit = fruits[indexPath.row]

        let name = fruit.name!

        cell.imageView.image = UIImage(named: name)
        cell.caption.text = name.capitalizedString

        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        return CGSize(width: collectionViewWidth/6, height: collectionViewWidth/6);
    }
}

可能值得一提的是,我的 UICollectionView 数据源被分组只是因为我正在做一个教程。这是数据源代码:

class数据源{

init() {
    populateData()
}

var fruits:[Fruit] = []
var groups:[String] = []

func numbeOfRowsInEachGroup(index: Int) -> Int {
    return fruitsInGroup(index).count
}

func numberOfGroups() -> Int {
    return groups.count
}

func gettGroupLabelAtIndex(index: Int) -> String {
    return groups[index]
}

// MARK:- Populate Data from plist

func populateData() {
    if let path = NSBundle.mainBundle().pathForResource(
        "Fruits", ofType: "plist") {
            if let dictArray = NSArray(contentsOfFile: path) {
                for item in dictArray {
                    if let dict = item as? NSDictionary {
                        let name = dict["name"] as! String
                        let group = dict["group"] as! String

                        let fruit = Fruit(name: name, group: group)
                        if !contains(groups, group){
                            groups.append(group)
                        }
                        fruits.append(fruit)
                    }
                }
            }
    }
}

// MARK:- FruitsForEachGroup

func fruitsInGroup(index: Int) -> [Fruit] {
    let item = groups[index]
    let filteredFruits = fruits.filter { (fruit: Fruit) -> Bool in
        return fruit.group == item
    }
    return filteredFruits
}

}

这是加载到数据源中的 plist:

编辑:我做了一些工作来删除不需要的组。我看到这些组导致新行开始得太早。我将代码更改为:

    // MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {

    func numberOfSectionsInCollectionView(
        collectionView: UICollectionView) -> Int {
            return 1
    }

    func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int {
            return 12
    }

    func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
            identifier,forIndexPath:indexPath) as! FruitCell

        let fruits: [Fruit] = dataSource.fruits
        let fruit = fruits[indexPath.row]

        let name = fruit.name!

        cell.imageView.image = UIImage(named: name)
        cell.caption.text = name.capitalizedString

        return cell
    }

    func collectionView(collectionView: UICollectionView,
        sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
            return CGSize(width: 200, height: 200);
    }
}

现在我只需要以某种方式使单元格宽度成为集合视图宽度的 1/6,然后剪掉刚刚浪费的 UICollectioview 底部 space

对于布局,我们基本上更喜欢创建一个 CustomflowLayout,继承自 UICollectionViewFlowlayout 并覆盖它的 2 个方法:

  • layoutAttributesForElementsInRect:(必需)
  • layoutAttributesForItemAtIndexPath:(必需)

然后设置

[self.collectionview setFlowlayout:CustomflowLayout];

如果您使用的是 UICollectionViewFlowLayout,则配置单元格宽度的方式是与 UICollectionViewFlowLayout 对话。设置其 itemSize.

您可以在viewDidLoad中设置collectionViewLayout的itemSize,如本例所示:

    override func viewDidLoad() {
        super.viewDidLoad()
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        let collectionViewSize = collectionView.frame.size
        let nrOfCellsPerRow = 6 
        let itemWidth = collectionViewSize.width/nrOfCellsPerRow
        let itemHeight = 80 // example
        layout.itemSize = CGSize(width: itemWidth, height: itemHeight) 
    }

如果您希望单元格之间有间距,则必须补偿 itemWidth 计算