如何创建一个向用户显示一堆卡片的集合视图?

Posted

技术标签:

【中文标题】如何创建一个向用户显示一堆卡片的集合视图?【英文标题】:How to create a collection view that shows the user a bunch of cards? 【发布时间】:2018-09-08 10:09:01 【问题描述】:

我正在编写一个 ios 纸牌游戏。我想向用户展示他手中的卡片。我寻找了一个好看的 CocoaPods,但找不到,所以我决定自己使用水平的 UICollectionView 创建这样的视图。

以下是一些要求:

集合视图的高度由屏幕高度动态确定。我用一些自动布局约束做到了这一点 集合视图单元格的高度应等于集合视图的高度。我不知道该怎么做。我只找到了this question,这是关于如何使集合视图高度适合项目的高度。我想要反过来 - 项目的高度适合集合视图。 集合视图单元格的宽度应等于其高度 * 5 / 7。这是卡片的宽高比。我想我也可以通过约束来做到这一点。 每个单元格内都有一个图像视图。图像视图应完全填满整个单元格。

这是我的尝试:

我在情节提要的原型单元格中为集合视图和图像视图添加了约束。然后我添加了这段代码。

extension ViewController : UICollectionViewDataSource, UICollectionViewDelegate 
    func numberOfSections(in collectionView: UICollectionView) -> Int 
        return 1
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 15
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.addConstraint(NSLayoutConstraint(item: cell, attribute: .height, relatedBy: .equal, toItem: cell, attribute: .width, multiplier: 5.0 / 7.0, constant: 0))
        // here I am just setting all the cells to have the same image for testing purposes
        (cell.viewWithTag(1) as! UIImageView).image = someCardImage
        return cell
    

结果:

似乎只有集合视图的约束有效。其他一切都不是。我在上面以编程方式添加的纵横比约束显然与我不知道的其他一些约束冲突:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x604000290810 UICollectionViewCell:0x7fd536610300.height == 0.714286*UICollectionViewCell:0x7fd536610300.width   (active)>",
    "<NSLayoutConstraint:0x600000292390 'UIView-Encapsulated-Layout-Height' UICollectionViewCell:0x7fd536610300.height == 99   (active)>", <---- What is this constraint?
    "<NSLayoutConstraint:0x600000292340 'UIView-Encapsulated-Layout-Width' UICollectionViewCell:0x7fd536610300.width == 68   (active)>" <---- What is this constraint?
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000292390 'UIView-Encapsulated-Layout-Height' UICollectionViewCell:0x7fd536610300.height == 99   (active)>

并且图像视图并没有完全填满整个单元格,如 UI 层次结构所示:


如何创建这样的集合视图,以满足我的要求?

【问题讨论】:

即使有 0.001 的差距,它也会显示约束中断消息。最好将其设置为低优先级(999) 【参考方案1】:

我在网上多看了一下后才知道这一点。

显然,CollectionViewDelegateFLowLayout 中有这个方法叫collectionView(_:layout:sizeForItemAt:)。第一次知道有这种方法!

如果我重写该方法,我可以随意设置单元格的大小:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    let height = collectionView.height
    let width = height * 5 / 7
    return CGSize(width: width, height: height)

所以我以编程方式添加的约束毕竟是不需要的。

对于图像视图的框架问题,我通过反复试验解决了。我在约束的属性检查器中取消选中了这个“相对于边距”选项:

我的猜测是单元格的“边距”是 8 个像素,因此相对于边距设置它会留下 8 个像素的空间。

【讨论】:

以上是关于如何创建一个向用户显示一堆卡片的集合视图?的主要内容,如果未能解决你的问题,请参考以下文章

集合视图单元格内的表视图?

滚动和拖动单元格时集合视图抛出异常

重用集合视图的 XIB 视图作为其他视图的一部分?

如何在集合视图中显示广告

Swift UI集合视图 - 如何在Cell中显示“segued”用户输入?

根据用户输入在集合视图中创建新图像