2017-04-10 104 views
1

我創建了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 –

回答

1

首先,你必須聲明你的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

由於您的問題沒有提供足夠的信息,但我仍然會爲它投票。

首先,您設置單元格的標籤行0和屬性「自動換行」。 其次,試試這個(運行並檢查它是否已完成,如果沒有,那麼請按照以下選項進行操作)。

接下來, 使用功能

label.intrinsicContentSize().height 

獲得在標籤文本的高度,然後設置它的高度,並通過添加其他空間計算單元格的高度。

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

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

希望這可以讓你的輸出。

謝謝。

+0

你缺少哪些信息? 標籤不需要調整大小。 UIView需要調整大小(屏幕截圖中的黑色視圖)。 – NoSixties