UITableCell高度尺寸不正确

问题描述:

我创建了xib代表UITableViewCell,在某些情况下会添加视图。UITableCell高度尺寸不正确

它需要做的是根据添加到单元格的视图数量正确调整高度。

我做什么是以下 enter image description hereUIImageUILabel有被设置为的UIView

UIViewtop有一个height constraint这是一个equal to or greater then 0bottom constraint。所以当没有视图被添加到单元格时,它需要为0.当单元格被添加到单元格时,它需要适当地调整大小。

我的细胞中的代码看起来像这样

struct MenuTableCellContents { 
    var identifier: cellIdentifier 
    var cellImage: UIImage 
    var cellText: String 
    //var cellFont: UIFont 
    var cellTextColor: UIColor 
    var subCells: [MenuTableCellContents]? 

    /// Normal cells without subcells 
    init(identifier: cellIdentifier, cellImage: UIImage, cellText: String, /*cellFont: UIFont,*/ cellTextColor: UIColor) { 
     self.identifier = identifier 
     self.cellImage = cellImage 
     self.cellText = cellText 
     self.cellTextColor = cellTextColor 
     //self.cellFont = cellFont 
    } 

    /// Cells with subcells 
    init(identifier: cellIdentifier, cellImage: UIImage, cellText: String, /*cellFont: UIFont,*/ cellTextColor: UIColor, subCells: [MenuTableCellContents]) { 
     self.identifier = identifier 
     self.cellImage = cellImage 
     self.cellText = cellText 
     self.cellTextColor = cellTextColor 
     //self.cellFont = cellFont 
     self.subCells = subCells 
    } 

    enum cellIdentifier { 
     case standard 
     case noIcon 
     case subcell 
    } 
} 

class MenuTableCell: UITableViewCell { 

    @IBOutlet var cell_icon: UIImageView! 
    @IBOutlet var cell_label: UILabel! 
    @IBOutlet var cell_contentView: UIView! 
    @IBOutlet var cell_contentView_height: NSLayoutConstraint! 


    var cellImage: UIImage? 
    var cellText: String? 
    var cellTextColor: UIColor? 
    //var cellFont: UIFont? 

    var subCells: [MenuTableCellContents]? 

    private var contentViewHeight: CGFloat? 

    override func draw(_ rect: CGRect) { 
     drawSubCells() 
     cell_label.text = cell_label.text?.uppercased() 

     super.draw(rect) 
    } 

    /// draw the subcells when needed 
    func drawSubCells() { 
     // Check if there are subcells 
     if let cells = subCells { 
      let count = CGFloat(cells.count) 

      // Set the height for the subcells 
      contentViewHeight = 40 * count 
      let contentViewFrame = CGRect(x: self.frame.width, y: self.cell_contentView.frame.origin.y, width: self.frame.width, height: contentViewHeight!) 
      cell_contentView?.frame = contentViewFrame 

      var i = 0 
      for cell in cells { 

       // create a view for each cell 
       let cellView = UIView() 
       let cellFrame = CGRect(x: 0, y: CGFloat(i * 40), width: contentViewFrame.width, height: 40) 
       cellView.frame = cellFrame 

       // add a image view to each cell 
       let imageView = UIImageView(image: cell.cellImage) 
       let imageViewFrame = CGRect(x: 0, y: (cellFrame.height - cellFrame.height/2)/2, width: cellFrame.width * 0.2, height: cellFrame.height/2) 
       imageView.frame = imageViewFrame 
       imageView.contentMode = .scaleAspectFit 

       // add a button to each cell 
       let cellLabel = UILabel() 
       let cellLabelFrame = CGRect(x: imageViewFrame.width, y: 0, width: cellFrame.width - imageViewFrame.width, height: 40) 
       cellLabel.frame = cellLabelFrame 
       //cellLabel.font = cell.cellFont 

       cellLabel.text = cell.cellText.uppercased() 
       cellLabel.textColor = cell.cellTextColor 
       cellLabel.minimumScaleFactor = 15 


       // add the imageview and button to the subcell view 
       cellView.addSubview(imageView) 
       cellView.addSubview(cellLabel) 

       // add the subcell to the cell 
       cell_contentView?.addSubview(cellView) 
       i += 1 
      } 

      setupConstraints(height: contentViewHeight!) 
     } 
    } 

    /// Set the height constraint for the cell content view in which the subcells reside 
    func setupConstraints(height: CGFloat) { 
     cell_contentView.frame.size.height = height 
    } 
} 

然后我的桌子方法如下所示

class MenuViewController: UIViewController, UITableViewDelegate { 
    @IBOutlet var menu_table: MenuTableView! 

    var cellContent: [MenuTableCellContents] = [] 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     setupCells() 


     let menuCell = UINib(nibName: "MenuTableCell", bundle: nil) 
     menu_table.register(menuCell, forCellReuseIdentifier: "menuCell") 

     menu_table.delegate = self 
     menu_table.dataSource = self 
     menu_table.rowHeight = UITableViewAutomaticDimension 
     menu_table.estimatedRowHeight = 50 

     self.revealViewController().frontViewShadowRadius = 0 
     self.revealViewController().frontViewShadowOffset = CGSize.zero 
    } 

    /// setup the required cells for the menu 
    func setupCells() { 
     let normal1 = MenuTableCellContents(identifier: .standard, cellImage: UIImage(named: "icn_pin")!, cellText: "normal1", cellTextColor: UIColor.black) 
     let normal2 = MenuTableCellContents(identifier: .standard, cellImage: UIImage(named: "icn_pin")!, cellText: "normal2", cellTextColor: UIColor.black) 
     let normal3 = MenuTableCellContents(identifier: .standard, cellImage: UIImage(named: "icn_pin")!, cellText: "normal3", cellTextColor: UIColor.black) 

     let sub1 = MenuTableCellContents(identifier: .subcell, cellImage: UIImage(named: "icn_pin")!, cellText: "sub1", cellTextColor: UIColor.black) 
     let sub2 = MenuTableCellContents(identifier: .subcell, cellImage: UIImage(named: "icn_pin")!, cellText: "sub2", cellTextColor: UIColor.black) 
     let sub3 = MenuTableCellContents(identifier: .subcell, cellImage: UIImage(named: "icn_pin")!, cellText: "sub3", cellTextColor: UIColor.black) 
     let subs = MenuTableCellContents(identifier: .standard, cellImage: UIImage(named: "icn_pin")!, cellText: "subs", cellTextColor: UIColor.black, subCells: [sub1, sub2, sub3]) 


     let normal4 = MenuTableCellContents(identifier: .standard, cellImage: UIImage(named: "icn_pin")!, cellText: "normal4", cellTextColor: UIColor.black) 


     cellContent = [normal1, normal2, normal3, subs, normal4] 
    } 
} 

/// required methods for the uitableview 
extension MenuViewController: UITableViewDataSource { 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return cellContent.count 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let content = cellContent[indexPath.item] 

     let cell = menu_table.dequeueReusableCell(withIdentifier: "menuCell", for: indexPath) as! MenuTableCell 

     cell.cell_icon.image = content.cellImage 
     cell.cell_label.text = content.cellText 
     cell.cell_label.textColor = content.cellTextColor 
     //cell.cell_label.font = content.cellFont 

     if let subCells = content.subCells { 
      cell.subCells = subCells 
     } 

     return cell 
    } 

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    } 

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 
     return UITableViewAutomaticDimension 
    } 
} 

没有人知道我要去哪里错了吗? 当添加视图时,它的大小将不正确。高度将保持为零。

UPDATE

我上传这个问题到GitHub的一个测试项目。 https://github.com/MaikoHermans/tableCellDynamicHeightProblem

更新2

对于任何人面对我已经更新在更新1提到的工作溶液中的GitHub的项目同样的问题。

+0

你的标签增长?或他的身高是固定的,如果是固定的,你可以计算你的细胞高度为40 * subViews数量+标签heigth –

首先,你必须声明你的UIView一个自定义的类,它包含你内心的细胞,并定义固有大小属性​​是这样的

class CustomAutoresizableView: UIView { 

    var subCells : [MenuTableCellContents 
] = []{ 
     didSet 
     { 
      ///Your code for add cells 
      self.invalidateIntrinsicContentSize() 
     } 
    } 

    override var intrinsicContentSize: CGSize 
    { 
     get 
     { 
      return CGSize(width: self.frame.width, height: CGFloat(self.arrayOfValues.count * 40)) 
     } 
    } 

} 

,那么你必须提供正确的约束你的主要细胞,并设置在垂直内容压缩性的高值,我用的1000,之后,你必须添加此两行您MenuViewControllerviewDidLoad

self.menu_table.rowHeight = UITableViewAutomaticDimension 
    self.menu_table.estimatedRowHeight = 40 
在你的cellForRowAtIndexPathÿ

OU需要通过这个

cell.yourCustomAutoresizableViewProperty.subCells = content.subCells 

编辑替换此

if let subCells = content.subCells { 
     cell.subCells = subCells 
    } 


更换

var subCells: [MenuTableCellContents] = [] {    
    willSet { 
     addSubCells() 
     self.invalidateIntrinsicContentSize() 
    } 

有了这个

var subCells: [MenuTableCellContents] = [] { 
    didSet{ 
     addSubCells() 
     self.invalidateIntrinsicContentSize() 
    } 
} 

您还需要这种方法之前执行添加新的细胞,因为你可以在另一

func cleanSubViews() 
{ 
    for view in self.subviews { 
     view.removeFromSuperview() 
    } 
} 

我希望这可以帮助你,如果你有任何问题,增加了许多细胞一个这请让我知道

+0

我觉得我们快到了。目前仍有一个问题。当我将它放在'willSet'或'didSet'中时,由于表视图的工作原理,视图将重新绘制。你可以看到它这样做。 – NoSixties

+0

看起来它只会在模拟器中做到这一点。但是,当我在手机上运行它时,它将不会绘制它,直到单元格在视图之外。我会上传一个测试项目到GitHub,这样你就能明白我的意思了 – NoSixties

+0

用GitHub链接更新了我的文章 – NoSixties

由于您的问题没有提供足够的信息,但我仍然会为它投票。

首先,您设置单元格的标签行0和属性“自动换行”。 其次,试试这个(运行并检查它是否已完成,如果没有,那么请按照以下选项进行操作)。

接下来, 使用功能

label.intrinsicContentSize().height 

获得在标签文本的高度,然后设置它的高度,并通过添加其他空间计算单元格的高度。

在返回以下功能新细胞的高度

tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) 

希望这可以让你的输出。

谢谢。

+0

你缺少哪些信息? 标签不需要调整大小。 UIView需要调整大小(屏幕截图中的黑色视图)。 – NoSixties