自动调整大小(动态高度)表格视图单元格的问题

Posted

技术标签:

【中文标题】自动调整大小(动态高度)表格视图单元格的问题【英文标题】:Problems with autoresizing (dynamic height) tableview cells 【发布时间】:2017-02-17 11:49:08 【问题描述】:

我在 UIViewController 中有一个 UITableView 作为视图的一部分。我正在尝试根据文本的长度自动调整表格单元格的大小。它没有设置 textview 的文本,并且单元格最终处于 idCellTextView-cell 的标准高度。我已经四处搜索并尝试在单元格内的文本视图中使用相对于内容视图和代码的自动布局中的固定,如下所示。 :

tableView.estimatedRowHeight = 70
tableView.rowHeight = UITableViewAutomaticDimension

与问题相关的视图控制器的其余部分如下所示:

class ExperimentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate 
var expId: String = ""
let experimentDescription: String = ""
var cellDescriptors: NSMutableArray!
var visibleRowsPerSection = [[Int]]()


let notificationCenter = NotificationCenter.default

override func viewDidLoad() 
    super.viewDidLoad()


    //TABLE CELLS
    loadCellDescriptors()
    tableView.tableFooterView = UIView()
    tableView.layoutMargins = UIEdgeInsets.zero
    tableView.separatorInset = UIEdgeInsets.zero
    tableView.delegate = self
    tableView.dataSource = self
    tableView.isHidden = true
    tableView.estimatedRowHeight = 70
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
    tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "idCellNormal")
    tableView.register(UINib(nibName: "HintCell", bundle: nil), forCellReuseIdentifier: "idCellTextView")


    //ADD VIEWS
    baseView.addSubview(backgroundImage)
    baseView.addSubview(foregroundImage)
    baseView.addSubview(nameLabel)
    baseView.addSubview(segmentedController)
    baseView.addSubview(descriptionText)
    baseView.addSubview(hint)
    baseView.addSubview(tableView)





/*
 Get property list for the different cells we want to have in the hint table
 */
func loadCellDescriptors() 
    if let path = Bundle.main.path(forResource: "CellDescriptor", ofType: "plist") 
        cellDescriptors = NSMutableArray(contentsOfFile: path)
        getIndicesOfVisibleRows()
        tableView.reloadData()
    


/*
 Returns number of rows in a given section
 */
func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int 
    return visibleRowsPerSection[section].count


/*
 Returns number of sections in table
 */
func numberOfSectionsInTableView(tableView: UITableView) -> Int 
    /*if cellDescriptors != nil 
        return cellDescriptors.count
    
    else 
        return 0
    */
    print(items.count)
    return 3


/*
 Sets up the cell contents
 */
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)
    let cell = tableView.dequeueReusableCell(withIdentifier: currentCellDescriptor["cellIdentifier"] as! String , for: indexPath) as! CustomCell

    if currentCellDescriptor["cellIdentifier"] as! String == "idCellNormal" 
        print("1")
        if currentCellDescriptor["primaryTitle"] != nil 
            cell.labelOfRow.text = "Hintet er"
            cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
        
     else if currentCellDescriptor["cellIdentifier"] as! String == "idCellTextView" 

        cell.textView.delegate = self
        cell.textView.isEditable = false
        cell.textView.isSelectable = false
        cell.textView.isScrollEnabled = true
        cell.textView.text = "orem Ipsum er rett og slett dummytekst fra og for trykkeindustrien. Lorem Ipsum har vært bransjens standard for dummytekst helt siden 1500-tallet, da en ukjent boktrykker stokket en mengde bokstaver for å lage et prøveeksemplar av en bok. Lorem Ipsum har tålt tidens tann usedvanlig godt, og har i tillegg til å bestå gjennom fem århundrer også tålt spranget over til elektronisk typografi uten vesentlige endringer. Lorem Ipsum ble gjort allment kjent i 1960-årene ved lanseringen av Letraset-ark med avsnitt fra Lorem Ipsum, og senere med sideombrekkingsprogrammet Aldus PageMaker som tok i bruk nettopp Lorem Ipsum for dummytekst.orem Ipsum er rett og slett dummytekst fra og f"
    
    cell.layoutMargins = UIEdgeInsets.zero

    return cell


/*
 Handles row selections
 Finds the index of the cell that was selected, checks if it is/can be expanded and animates in the additional rows
 */
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
    let cellDescriptor = cellDescriptors[indexPath.section] as! NSMutableArray
    let cell = (cellDescriptors[indexPath.section] as! NSMutableArray)[indexOfTappedRow]
    var shouldExpandAndShowSubRows: Bool = false

    //Checks if cell is expandable, if it is we check if cell isn't already expanded. If it isn't we can expand the cell
    if (cell as AnyObject)["isExpandable"] as! Bool == true 
        shouldExpandAndShowSubRows = false
        if (cell as AnyObject)["isExpanded"] as! Bool == false 
            shouldExpandAndShowSubRows = true
        
    

    (cell as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isExpanded")

    //Makes the cells inside the specific section visible
    for i in (indexOfTappedRow + 1)...(indexOfTappedRow + ((cell as AnyObject)["additionalRows"] as! Int)) 
        (cellDescriptor[i] as AnyObject).setValue(shouldExpandAndShowSubRows, forKey: "isVisible")
    

    //Update the overview of the currently visible rows
    getIndicesOfVisibleRows()
    //Reload the sections to see the changes
    tableView.reloadSections(NSIndexSet(index: indexPath.section) as IndexSet, with: UITableViewRowAnimation.fade)


/*
 Get overview of the rows that are currently visible
 */
func getIndicesOfVisibleRows() 
    visibleRowsPerSection.removeAll()

    for currentSectionCells in cellDescriptors.objectEnumerator().allObjects as! [[[String:AnyObject]]] 
        var visibleRows = [Int]()

        for row in 0...((currentSectionCells).count - 1) 
            if currentSectionCells[row]["isVisible"] as! Bool == true 
                visibleRows.append(row)
            
        

        visibleRowsPerSection.append(visibleRows)
    


/*
 Get cell descriptor from file for specific cell
 */
func getCellDescriptorForIndexPath(_ indexPath: IndexPath) -> [String: AnyObject] 
    let indexOfVisibleRow = visibleRowsPerSection[indexPath.section][indexPath.row]
    let cellDescriptor = (cellDescriptors[indexPath.section] as! NSMutableArray)[indexOfVisibleRow] as! [String: AnyObject]
    return cellDescriptor


【问题讨论】:

André 您的可扩展表格视图内容是否需要自动标注尺寸?您可以改用 (heightForRowAtIndexPath) 方法。 textview里面的文字长度会不一样,所以是的 André UITextView 类实现了可滚动的多行文本区域的行为。因此,随着内容长度的增加,它会自行滚动。 打算使用 heightforrowatindexpath 并手动计算。谢谢你:) @André - 这解决了吗 【参考方案1】:

试试这个:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return UITableViewAutomaticDimension


func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return UITableViewAutomaticDimension

Here Example

【讨论】:

【参考方案2】:

试试这个 -

确保首先在表格视图单元格中正确添加约束。

然后从情节提要的属性检查器部分设置 UILable 的这两个属性:

1 - 到 0 的行

2 - 换行换行

注意 - 不要固定 UILable 的高度。

对于 TextView -

您需要禁用滚动。它会起作用的。

【讨论】:

这是我要扩展的文本视图,而不是标签:| 对于 textview 只需添加顶部底部前导和尾随约束不固定高度..它应该工作 或者你可以附上你的手机屏幕截图我可以试试。【参考方案3】:

我建议使用 AutoLayout 而不是自动调整大小。设计 UI 元素既简单又好用。以下步骤将帮助您了解如何使用 AutoLayout 设计自动调整单元格大小。

要为行高和估计行高设置自动尺寸,请确保按照以下步骤制作,自动尺寸对单元格/行高布局有效。

分配和实现 dataSource 和委托 将UITableViewAutomaticDimension 分配给rowHeight 和estimatedRowHeight 实现委托/数据源方法(即heightForRowAt 并向其返回值UITableViewAutomaticDimension

-

@IBOutlet weak var table: UITableView!

override func viewDidLoad() 
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

   // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension





// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension

对于 UITableviewCell 中的标签实例

设置行数=0(&换行模式=截尾) 设置与其父视图/单元格容器相关的所有约束(顶部、底部、左右)。 可选:设置标签的最小高度,如果你想要标签覆盖的最小垂直区域,即使标签/文本没有数据。

【讨论】:

【参考方案4】:

您必须将 numberOfLines 设置为 0 以允许单元格内的 UILabel 增长

【讨论】:

这是我要扩展的文本视图,而不是标签:|

以上是关于自动调整大小(动态高度)表格视图单元格的问题的主要内容,如果未能解决你的问题,请参考以下文章

图像在表格视图单元格中下载后调整大小

调整单元格大小时如何使表格视图动画平滑

以编程方式动态调整多行 UILabel 和随附的表格视图单元格

具有动态调整单元格的可折叠表格视图

从自定义表格视图单元格类加载时如何调整单元格的高度?

使用自动布局自定义集合视图单元格的动态高度