表格视图单元格高度

Posted

技术标签:

【中文标题】表格视图单元格高度【英文标题】:Table View Cell Height 【发布时间】:2017-07-27 08:18:17 【问题描述】:

我的表格视图中有多个单元格;例如猫细胞、狗细胞、鸡细胞。在 Cat Cell 中,我有两个视图:图形视图和图像视图。

如果图形视图被隐藏而图像视图可见,那么我想将单元格高度设置为 200,在相反的情况下设置为 350。

我将如何实现这一目标?我正在表格视图的heightForRowAt 委托方法中注册我的 nib 文件,但我尝试了不同的方法无济于事。这是我单元格中的两个视图:

@property (weak, nonatomic) IBOutlet UIView *imagesView;
@property (weak, nonatomic) IBOutlet UIView *graphView;

...这是我的heightForRowAt 方法:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    TrainingImageCell *cell = (TrainingImageCell*)[self.tableView dequeueReusableCellWithIdentifier:@"TrainingImageCell"];
    if (cell.isGraphViewOnTop == YES) 
        return 350;
    
    else 
        return 200;
    
    return 200;

【问题讨论】:

为什么要在 heightForRowAt 中注册 nib 文件。您正在注册新单元格,因此无法访问现有单元格。如果您希望它以您的风格工作,而不是在 IndexPath 处为行注册高度的新单元格,您可以使用 indexPath 作为 TrainingImageCell currentCell = (TrainingImageCell)[tableView cellForRowAtIndexPath:indexPath]; 访问现有单元格并检查属性。 在 heightForRowAtIndexPath 中使用 dequeueReusableCellWithIdentifier 方法是无效的。因为首先调用 heightForRowAtIndexPath 方法,然后调用 cellForRowAtIndexPath 方法。如果你给我看一些 cellForRowAtIndexPath 方法的代码,我可以帮助你吗? 我得到了那部分@YagneshDobariya 我必须像答案中提到的那样使用它,但我现在遇到了重新加载表格视图的问题。我已经定义了一个布尔属性 isShowingGraphView 并在注册笔尖后在 cellForRowAt 中隐藏和取消隐藏我的视图。我在 heightforRowAt 中调用此属性并反对 bool 返回高度,但如果我调用 reload TableView 整个视图就会消失。 @UsamabinAttique 你为什么使用 TrainingImageCell cell = (TrainingImageCell)[self.tableView dequeueReusableCellWithIdentifier:@"TrainingImageCell"];在 heightForRowAtIndexPath 中。直接使用与在 cellForRowAtIndexPath 中设置“isGraphViewOnTop”相同的条件。我认为问题应该在这里。 【参考方案1】:

您需要访问tableView 中已有的内容,而不是启动一个新单元格。

而不是

TrainingImageCell *cell = (TrainingImageCell*)[self.tableView dequeueReusableCellWithIdentifier:@"TrainingImageCell"];

TrainingImageCell *currentCell = (TrainingImageCell*)[tableView cellForRowAtIndexPath:indexPath];

然后看看房产。

编辑: 看看我们的冗长讨论,这里有一个非常可靠的例子,说明您可以在 Swift 中使用一种方法。

import UIKit

class RightAlignedCell: UITableViewCell 
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var subLabel: UILabel!
    // Your boolean property you would like to map
    var randomBool: Bool = false


class RightAlignedTableViewController: UIViewController 
    // This is just an example for the dataSource, you should have this somewhere already
    lazy var dataSource: [Bool] = 
        var dataSource: [Bool] = []
        for index in 0..<10 
            dataSource.append(index % 2 == 0)
        
        return dataSource
    () 

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
    

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)
        tableView.reloadData()
    


extension RightAlignedTableViewController: UITableViewDelegate 

extension RightAlignedTableViewController: UITableViewDataSource 

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

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        // Take a look in the !!!dataSource!!!, what is value for isHidden
        let isHidden = self.dataSource[indexPath.row]
        // return the right height
        return isHidden ? 60 : 100
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell: RightAlignedCell = tableView.dequeueReusableCell(withIdentifier: "RightAlignedCell", for: indexPath) as! RightAlignedCell
        cell.titleLabel.text = "Something"
        cell.subLabel.text = "Nothing"
        cell.randomBool = self.dataSource[indexPath.row]

        return cell
    

【讨论】:

是的,我可以访问这样的属性,我想做的是 if (currentCell.graphView setHidden:YES) return 350; 其他 返回 200;但它给了我一个错误, ps isGraphViewOnTop 只是一个布尔值,所以如果设置为是或否,它本身不知道该怎么做。我在某处的函数中使用它。请原谅我的无知,但这是实现我想要实现的目标的正确方法吗? 不,这不是正确的方法。在这里,您应该做的就是查看标志是否为truefalse 并返回一个值。做某处-> [currentCell.graphView setHidden:YES] 然后重新加载tableview([tableView realodData]),所以会再次询问高度。 我在我的 cellForRowAt 中调用 ([tableView realodData]) 但问题是我的整个视图在我取消注释时都会消失。我还尝试了使用 0,0 的 reloadRowsatindexpath,因为此单元格仅在 indexPath =0 时执行,但如果我这样做,应用程序将崩溃。 不要从cellForRowAtIndexPath 调用[tableView reload],这会导致无限循环。你在哪里设置[currentCell.graphView setHidden:YES] 我在类中定义了一个 bool 属性 isShowingGraph,我正在针对 cellForRowAt 中的 bool 值设置 setHidden。我正在使用重用标识符注册单元格。如果我使用您规定的方法,我应该在哪里重新加载数据?因为如果我在 heightforRowAt 中这样做,整个视图就会消失。【参考方案2】:

为什么要在 heightForRowAt 中注册 nib 文件。您正在注册新单元,因此无法访问现有单元。如果您希望它以您的风格工作,而不是在 IndexPath 处为行注册新的高度单元格,您可以使用 indexPath as 访问现有单元格

TrainingImageCell *currentCell = (TrainingImageCell*)[tableView cellForRowAtIndexPath:indexPath];

并访问检查属性。

 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 TrainingImageCell *currentCell = (TrainingImageCell*)[tableView cellForRowAtIndexPath:indexPath];
  if (cell.isGraphViewOnTop == YES) 
  return 350;
  
return 200;

【讨论】:

是的,我可以访问这样的属性,我想做的是 if (currentCell.graphView setHidden:YES) return 350; 其他 返回 200;但它给了我一个错误, ps isGraphViewOnTop 只是一个布尔值,所以如果设置为是或否,它本身不知道该怎么做。我在某处的函数中使用它。请原谅我的无知,但这是实现我想要实现的目标的正确方法吗? 你在哪里使用它??您必须在 cellForRowAtIndexPath 中将标志值设置为 isGraphViewOnTop,然后才能在此处使用。 您可以为 Row 的高度设置适当的 AutoLayout 和 UIAutomatic Dimension。 如果你想根据 Graph View 是否可见来操作 tableVieCells 的高度,我建议在你的单元格中使用 UIStackView。它只对可见的组件进行管理。检查此链接atomicbird.com/blog/uistackview-table-cells。 我在我的单元格类中的一个函数中使用它,当我使用 UIView transitionWithView 并没有在 cellForRowAt 中的任何位置设置标志时,我正在翻转图形视图和图像视图。 ps 该项目非常庞大,并且在单元格中调用了很多功能,因此目前使用 UIStackView 走这条路可能不是最好的选择。【参考方案3】:

如果你dequeueReusableCellWithIdentifier你只是得到一个新单元格,它不会有任何数据来检查isGraphViewOnTop

我的建议是返回UITableViewAutomaticDimension 并使用常量设置单元格视图,这样当元素被隐藏时,单元格的大小会更小。

【讨论】:

以上是关于表格视图单元格高度的主要内容,如果未能解决你的问题,请参考以下文章

表格视图单元格高度

仅针对一种原型单元格的自动表格视图单元格高度

当单元格的高度不同时,如何在表格视图中获取所有单元格的高度?

如何在表格视图中更改一个单元格的高度? [复制]

表格视图单元格高度动态 + 从 .xib 加载

更新图像高度约束后更新表格视图单元格高度