【问题标题】: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”相同的条件。我认为问题应该在这里。

标签: ios objective-c uitableview uiview


【解决方案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 并使用常量设置单元格视图,这样当元素被隐藏时,单元格的大小会更小。

【讨论】: