使用类似“标签”的单元格设置 collectionView

Posted

技术标签:

【中文标题】使用类似“标签”的单元格设置 collectionView【英文标题】:Setup a collectionView with "tag"-like cells 【发布时间】:2018-10-03 13:41:05 【问题描述】:

我一直在使用自定义UICollectionViewFlowLayout 来调整单元格之间的空间,以便在我的collectionView 中获得良好的流程。但是使用我当前的代码,我无法弄清楚如何在不“破坏”行数的情况下调整单元格大小。这使得一些单元格认为它们可以容纳一行,但实际上不能。

我的自定义流程布局

class UserProfileTagsFlowLayout: UICollectionViewFlowLayout 
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
        let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
        var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
        
        var leftMargin: CGFloat = 0.0;
        
        for attributes in attributesForElementsInRect! 
            if (attributes.frame.origin.x == self.sectionInset.left) 
                leftMargin = self.sectionInset.left
             else 
                var newLeftAlignedFrame = attributes.frame
                newLeftAlignedFrame.origin.x = leftMargin
                attributes.frame = newLeftAlignedFrame
            
            leftMargin += attributes.frame.size.width + 8 // Makes the space between cells
            newAttributesForElementsInRect.append(attributes)
        
        
        return newAttributesForElementsInRect
    

所以在我的ViewController 中我已经扩展了

extension myViewController: UICollectionViewDelegateFlowLayout 
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        let tag = tagsArray[indexPath.row]
        let font = UIFont(name: "Raleway", size: 14)!
        let size = tag.value.size(withAttributes: [NSAttributedString.Key.font: font])
        let dynamicCellWidth = size.width

        /*
          The "+ 20" gives me the padding inside the cell
        */
        return CGSize(width: dynamicCellWidth + 20, height: 35)
    
    
    // Space between rows
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat 
        return 5
    
    
    // Space between cells
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat 
        return 10
    

当我尝试这段代码时,我在 iPhone X 的结果部分中得到了结果。您可以看到标签“机器学习”跳到新行,因为它认为它可以适合该行多于。如果我在sizeForItem 函数中删除单元格的“填充”,那么我就不会有这个问题。但它看起来很糟糕。

所以我的问题是:如何在不破坏 flowLayout 的情况下在单元格上使用填充?

到目前为止,我目前的结果如下所示:

iPhone X:

【问题讨论】:

我还需要创建这个标签列表,但我有点困惑如何使用它。能否请您提供完整的文章代码。 @KishorPahalwani 我无法再访问这段代码了。我没有关注任何文章,我自己编的。所以我建议要么多谷歌,要么尝试自己构建它:) 为每个单元格构建 UI 不会有问题。然后您可以使用答案中的代码来获得正确的布局。 ***.com/questions/70618239/… 你能帮我吗? 【参考方案1】:

也许它会帮助你。我认为你应该检查你的项目是否突出了集合视图的右插图。 在layoutAttributesForElements 方法中检查这个:

        let collectionViewWidth = self.collectionView?.frame.width - (self.sectionInset.right + self.sectionInset.left)

        if (attributes.frame.origin.x + attributes.frame.size.width > collectionViewWidth) 
            var newLeftAlignedFrame = attributes.frame
            newLeftAlignedFrame.origin.x = self.sectionInset.left
            attributes.frame = newLeftAlignedFrame 
        

更新了我的答案,它对我有用,你可以在屏幕截图上看到它

【讨论】:

我试过你的代码,但它仍然给我同样的结果。我也尝试使用collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10),但它似乎也不起作用。 @JacobAhlberg 对不起,一个小错字。更新了我的答案。 您先生,帮了我很多忙!非常感谢您的回答!它也可以在所有设备上完美运行! 可以分享全文吗?【参考方案2】:

我也在实现标签布局。 我尝试使用以下方法,但它不适合我。

我该如何纠正这个问题?

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
            guard let attributesForElementsInRect = super.layoutAttributesForElements(in: rect) else  return nil 
            guard var newAttributesForElementsInRect = NSArray(array: attributesForElementsInRect, copyItems: true) as? [UICollectionViewLayoutAttributes] else  return nil 
            
            var leftMargin: CGFloat = 0.0;
            let collectionViewWidth = self.collectionView?.frame.width ?? 0 - (self.sectionInset.right + self.sectionInset.left)
            for attributes in attributesForElementsInRect 
                if (attributes.frame.origin.x == self.sectionInset.left) 
                    leftMargin = self.sectionInset.left
                
                else if (attributes.frame.origin.x + attributes.frame.size.width > collectionViewWidth) 
                    var newLeftAlignedFrame = attributes.frame
                    newLeftAlignedFrame.origin.x = self.sectionInset.left
                    attributes.frame = newLeftAlignedFrame
                 
                
                else 
                    var newLeftAlignedFrame = attributes.frame
                    newLeftAlignedFrame.origin.x = leftMargin
                    attributes.frame = newLeftAlignedFrame
                
                leftMargin += attributes.frame.size.width + 8 // Makes the space between cells
                newAttributesForElementsInRect.append(attributes)
            
            
            return newAttributesForElementsInRect
        

【讨论】:

以上是关于使用类似“标签”的单元格设置 collectionView的主要内容,如果未能解决你的问题,请参考以下文章

设置单元格的高度等于标签内容

HTMLHTML 表格 ② ( 表头单元格标签 | 表格标题标签 )

iOS - 单元格根据元素可见性调整约束

错误:无法使用自定义单元格类设置 UITableViewCell 标签和图像!只能加载单元格样式的数据:字幕不是自定义的

使用情节提要的tableview自定义单元格标签不起作用

设置表格视图单元格的高度以匹配底部到标签栏顶部