当单元格具有动态宽度时,CollectionView中的间距不正确?

时间:2018-05-25 12:09:22

标签: ios swift uitableview uicollectionview

我想要实现TokenView(芯片视图)样式视图。为此我在UITableViewCell中使用集合视图,CollectionView具有自定义单元格。内部自定义单元格有UILabel。现在,单元格的宽度取决于UILabel的内容。

以下是自定义UITableViewCell Cell的代码

import UIKit

class LanguageTableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{

        var arr:[String] = ["English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate","English","Intermediate"]
    @IBOutlet weak var collectionView: UICollectionView!

    override func awakeFromNib() {
        super.awakeFromNib()
        collectionView.dataSource = self
        collectionView.delegate = self
        let layout = UICollectionViewFlowLayout()
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        layout.scrollDirection = .vertical
        self.collectionView.collectionViewLayout = layout
        // Initialization code
    }


    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arr.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "LanguageCollectionViewCell", for: indexPath) as! LanguageCollectionViewCell
        cell.setValue(lang: arr[indexPath.row],indexPath:indexPath)
        return cell
    }



    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let string = arr[indexPath.row]
        let width = (string.count * 10)
        return CGSize(width:width, height: 30)
    }

}

UICollectionViewCell

的课程
typealias Parameters = [String:Any]
import UIKit


class LanguageCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var languageLabel: UILabel!

    override func layoutSubviews() {
        super.layoutSubviews()

    }

    func setValue(lang:String ,indexPath:IndexPath) {

        if indexPath.row % 2 == 0 {
            languageLabel.backgroundColor = UIColor.gray

        }else {
            languageLabel.backgroundColor = UIColor.yellow

        }
            self.languageLabel.text = lang
    }
}

enter image description here

4 个答案:

答案 0 :(得分:7)

UITableViewCell Cell

中实施此功能
  1. 子类化UICollectionViewFlowLayout
  2. 添加类似的实现:
  3. 解决方案是减少单元格间距/对齐UICollectionView单元格布局。非常简单快速的性能。基于Olloqui

    给出的示例

    Class CustomViewFlowLayout

    class CustomViewFlowLayout: UICollectionViewFlowLayout {
    
    let cellSpacing:CGFloat = 4
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
                self.minimumLineSpacing = 4.0
                self.sectionInset = UIEdgeInsets(top: 10, left: 8, bottom: 10, right: 6)
                let attributes = super.layoutAttributesForElements(in: rect)
    
                var leftMargin = sectionInset.left
                var maxY: CGFloat = -1.0
                attributes?.forEach { layoutAttribute in
                    if layoutAttribute.frame.origin.y >= maxY {
                        leftMargin = sectionInset.left
                    }
                    layoutAttribute.frame.origin.x = leftMargin
                    leftMargin += layoutAttribute.frame.width + cellSpacing
                    maxY = max(layoutAttribute.frame.maxY , maxY)
                }
                return attributes
        }
    }
    

    其中cellSpacing可以设置为您喜欢的任何值。这个技巧保证了单元格之间的空间完全等于cellSpacing。

    UITableViewCell Cell / CollectionViewController的实现。

    import UIKit
    
    class ViewController: UIViewController , UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    var arr:[String] = ["English","Intermediate","English","English","arr","UICollectionViewFlowLayoutFlowFlowFlow","English","UICollectionViewDelegate","English","Intermediate","UIViewController","viewDidLoad","Intermediate","String","Intermediate","arr","Intermediate","UIKit","Intermediate","English","columnLayout","English","languageLabel"]
    
    let columnLayout = CustomViewFlowLayout()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.collectionViewLayout = columnLayout
        collectionView.contentInsetAdjustmentBehavior = .always
    }
    
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arr.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "chip", for: indexPath) as! LanguageCollectionViewCell
        cell.languageLabel.text = arr[indexPath.row]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
        let string = arr[indexPath.row]
    
        // your label font.
        let font = UIFont.systemFont(ofSize: 16)
        let fontAttribute = [NSAttributedStringKey.font: font]
    
        // to get the exact width for label according to ur label font and Text.
        let size = string.size(withAttributes: fontAttribute)
    
        // some extraSpace give if like so.
        let extraSpace : CGFloat = 8.0
        let width = size.width + extraSpace
        return CGSize(width:width, height: 30)
       }
    }
    

    UICollectionViewCell

    的课程
    class LanguageCollectionViewCell: UICollectionViewCell {
        @IBOutlet weak var languageLabel: UILabel!
    
    }
    

    enter image description here

答案 1 :(得分:4)

1 - 实施UICollectionViewDelegateFlowLayout协议,

添加以下代码:

var itemsPerRow:CGFloat = 3

让sectionInsets = UIEdgeInsets(上:10,左:10,下:10,右:10)

然后添加委托方法以确定如下所示的间距;

func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
        let availableWidth = view.frame.width - paddingSpace

        let widthPerItem = availableWidth / itemsPerRow

        return CGSize(width: widthPerItem, height: widthPerItem)
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        insetForSectionAt section: Int) -> UIEdgeInsets {
        return sectionInsets
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 10
    }

答案 2 :(得分:3)

我使用了一个pod用于相同的

pod 'AlignedCollectionViewFlowLayout'

在我使用UICollectionView的课程中,

import AlignedCollectionViewFlowLayout

并按如下方式配置collectionViewLayout

if let fl = myCollection.collectionViewLayout as? AlignedCollectionViewFlowLayout {          
  fl.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
  fl.horizontalAlignment = .left
  fl.verticalAlignment = .top
}
  

请注意,您可以使用此设置左/右和上/下对齐   荚!它对我来说就像一个魅力

我还确保将preferredMaxLayoutWidth添加到UICollectionViewCell中的标签中,以便我可以修复其中一个可能的错误(即单元格的宽度不能大于屏幕大小)

class MyCollectionViewCell: UICollectionViewCell {
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        myLabel.preferredMaxLayoutWidth = UIScreen.main.bounds.size.width * 0.8
    }
}

我收集的结果如下:

https://github.com/webpack-contrib/webpack-serve/issues/158

答案 3 :(得分:2)

你能试试吗

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let lb = UILabel()

    lb.text = arr[indexPath.row]

    lb.font = UIFont.init(name: "System", size: 17)

    lb.sizeToFit()

    return CGSize(width:lb.frame.size.width, height: 30 )
}

//

或设置此

layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize

并将标签基于0的前导,尾随,顶部和底部约束赋予单元格

注意:在这两种情况下都必须删除方法sizeForItemAt的实现