用 5 种不同的布局绘制 UITableViewCell

Posted

技术标签:

【中文标题】用 5 种不同的布局绘制 UITableViewCell【英文标题】:Draw UITableViewCell with 5 different layout 【发布时间】:2018-07-23 07:37:06 【问题描述】:

我需要在 UITableView 中绘制 5 种不同风格的单元格,我需要你的一点帮助!我向你展示我在 ViewController 中写的内容:

var selfHeightCell : CGFloat? // for custom rowHeight

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    self.UITableView.estimatedRowHeight = 200.00;
    self.selfHeightCell = UITableViewAutomaticDimension;


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 10


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cardCell", for: indexPath) as! CardCell
    switch indexPath.row  // this is for test my code
    case 0:
        selfHeightCell = cell.workTest(drawCard: .verySmallCard)
    case 1:
        selfHeightCell = cell.workTest(drawCard: .smallCard)
    case 2:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 3:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 4:
        selfHeightCell = cell.workTest(drawCard: .bigCard)
    case 5:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 6:
        selfHeightCell = cell.workTest(drawCard: .mediumCard)
    case 7:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 8:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    case 9:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    default:
        selfHeightCell = cell.workTest(drawCard: .basiqCard)
    
    return cell


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    return selfHeightCell!

现在是我的 CardCell 的代码:

func workTest(drawCard: state) -> CGFloat
    var heightOfCardRow : CGFloat = 0
    switch drawCard 
    case .verySmallCard:
        heightOfCardRow = self.drawCard(height : 60)
    case .smallCard:
        heightOfCardRow = self.drawCard(height : 100)
    case .mediumCard:
        heightOfCardRow = self.drawCard(height : 140)
    case .basiqCard:
        heightOfCardRow = self.drawCard(height : 200)
    case .bigCard:
        heightOfCardRow = self.drawCard(height : 280)
    
    return heightOfCardRow


func drawCard(height : CGFloat) -> CGFloat
    if(cardView.subviews.count == 0)
        self.addSubview(cardView)
        cardView.frame = CGRect(marginCardWidth,
                                marginCardHeight,
                                self.bounds.size.width - (marginCardWidth*2),
                                height - (marginCardHeight*2))
        cardView.layer.cornerRadius = 10
    
    if(self.ShadowLayerCard == nil)
        let shadowLayer = CAShapeLayer()
        self.ShadowLayerCard = shadowLayer
        shadowLayer.path = UIBezierPath(roundedRect: cardView.bounds, cornerRadius: 10).cgPath
        shadowLayer.fillColor = UIColor(rgb: 0xffcc00).cgColor
        shadowLayer.shadowPath = shadowLayer.path
        shadowLayer.shadowColor = UIColor.black.cgColor
        shadowLayer.shadowRadius = 5
        shadowLayer.shadowOpacity = 0.2
        shadowLayer.shadowOffset = CGSize(width: 0, height: 0)
        cardView.layer.insertSublayer(shadowLayer, at: 0)
    
    return cardView.bounds.size.height + (marginCardHeight*2)

我给你看一张模拟器的图片:

抱歉所有代码,但我认为有必要解决我的问题。我认为错误是因为我以编程方式绘制或者我以错误的方式自定义单元格的高度!

我的问题是:产生这些问题的坏方法是什么?

【问题讨论】:

代码中有很多错误,UITableViewAutomaticDimension 需要约束,heightForRowAt cellForRowAt 之前被调用,所以这里覆盖高度是错误的,cardView 可以在情节提要中创建或使用约束,只需要一种细胞类型,.... @Tj3n 好的,为了修改我的cardView,我在情节提要中添加了这个之后,我在 CardCell 类中编辑了高度的约束?因为在我添加卡片后,我需要根据卡片状态枚举以编程方式添加几个按钮 UIImageView 和其他组件 【参考方案1】:

当使用动态单元格高度时,不要实现 heightForRowAt ,而是让 contentView 根据其内容自行布局,或者给它一个高度约束并在 cellForRowAt 中更改它

考虑那个单元类

class MyCell : UITableViewCell 

    let redView = UIView()

    var redViewHCon:NSLayoutConstraint!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        redView.translatesAutoresizingMaskIntoConstraints = false

        self.contentView.addSubview(redView)

        redView.backgroundColor = .red

        NSLayoutConstraint.activate( [

            redView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 20),

            redView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 0),

            redView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: 0),

            redView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -20)

            ])

        redViewHCon =  redView.heightAnchor.constraint(equalToConstant: 300)

        redViewHCon.isActive = true

    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


//

cellForRowAt

let cell = tableView.dequeueReusableCell(withIdentifier:"pp") as! MyCell 
cell.redViewHCon.constant = CGFloat((indexPath.row + 1) * 100)

//

viewDidLoad中添加这一行

 tableView.register(MyCell.self, forCellReuseIdentifier: <#setIdentifier#>)

【讨论】:

感谢您的回复,但我以编程方式绘制卡片,请问如何“让 contentView 根据其内容自行布局”? 当你向它添加元素时,从上到下正确地钩住约束,然后它将根据没有任何常量的内容进行拉伸,但这对于标签和按钮等内在元素来说,如果你添加一个视图说那么你应该为它定义一个高度 对不起,但我不明白我需要做什么,首先我删除我的 heightForRowAt 函数,这是一个坏主意,但我需要以编程方式添加 cardView 的约束就是它? 我只是在我初始化我的自定义单元格时遇到了问题。我有这个错误Fatal error: init(coder:) has not been implemented。我用你的代码 我使用故事板。并注册什么?

以上是关于用 5 种不同的布局绘制 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

用 pandas 在同一个图中绘制 5 个不同的时间序列数据集

具有不同角半径的可绘制形状背景的布局上的标高

QCustomPlot之层和布局(四)

自动布局 UITableViewCells 覆盖底部

检测视图是不是重叠

将风味图放在布局的ImageView中