Answers:
在动态单元格上,rowHeight
在UITableView上设置的值始终会覆盖单个单元格的rowHeight。
但是在静态单元格上,rowHeight
在单个单元格上设置可以覆盖UITableView的。
不确定是否是bug,Apple可能有意这样做吗?
UITableView
内容从更改Dynamic Prototypes
为Static Cells
,我这样做了,我的整个项目都炸毁了..差点就自杀了。
如果使用UITableViewController,请实现此方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
在行功能中,您可以选择高度。例如,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 100;
}
else {
return 60;
}
}
在此示例中,第一行高度为100像素,其他行高度为60像素。
希望这个可以对您有所帮助。
对于动态单元格,rowHeight
在上设置UITableView
总是会覆盖单个单元格的rowHeight
。
IMO,此行为是一个错误。每当您必须在两个位置管理UI时,都容易出错。例如,如果您在情节提要中更改单元格大小,则还必须记住在情节提要中进行更改heightForRowAtIndexPath:
。在Apple修复该错误之前,当前的最佳解决方法是重写heightForRowAtIndexPath:
,但使用情节提要中的实际原型单元来确定高度,而不是使用幻数。这是一个例子:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* In this example, there is a different cell for
the top, middle and bottom rows of the tableView.
Each type of cell has a different height.
self.model contains the data for the tableview
*/
static NSString *CellIdentifier;
if (indexPath.row == 0)
CellIdentifier = @"CellTop";
else if (indexPath.row + 1 == [self.model count] )
CellIdentifier = @"CellBottom";
else
CellIdentifier = @"CellMiddle";
UITableViewCell *cell =
[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell.bounds.size.height;
}
这将确保对原型单元格高度的任何更改都将在运行时自动被拾取,并且您只需要在一个地方(即情节提要)中管理UI。
我已经构建了各种答案/注释提示的代码,因此该代码适用于使用原型单元的情节提要。
这段代码:
感谢Answerbot,Brennan和lensovet。
- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = nil;
switch (indexPath.section)
{
case 0:
cellIdentifier = @"ArtworkCell";
break;
<... and so on ...>
}
return cellIdentifier;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
static NSMutableDictionary *heightCache;
if (!heightCache)
heightCache = [[NSMutableDictionary alloc] init];
NSNumber *cachedHeight = heightCache[cellIdentifier];
if (cachedHeight)
return cachedHeight.floatValue;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
CGFloat height = cell.bounds.size.height;
heightCache[cellIdentifier] = @(height);
return height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
<... configure cell as usual...>
实际上,您需要在两个地方更改行高,首先是单元格(您已经做了更改),然后选择“表格视图”并检查“大小”检查器
如果您使用的是swift,请像这样使用。不要使用情节提要选择行高。像这样以编程方式设置表格行高,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 || indexPath.row == 1{
let cell = self.tableView.dequeueReusableCellWithIdentifier("section1", forIndexPath: indexPath) as! Section1TableViewCell
self.tableView.rowHeight = 150
cell.label1.text = "hiiiiii"
cell.label2.text = "Huiiilllllll"
return cell
} else {
let cell = self.tableView.dequeueReusableCellWithIdentifier("section2", forIndexPath: indexPath) as! Section2TableViewCell
self.tableView.rowHeight = 60
cell.label3.text = "llll"
return cell
}
}
cell.sizeToFit(); self.tableView.rowHeight = cell.frame.height
您可以在以下几行的帮助下从情节提要中获取UITableviewCell的高度(在UITableviewController-静态单元格中)。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];
return height;
}
在XML视图中打开情节提要,然后尝试编辑 rowHeight
所需元素属性。
当我尝试为原型行设置自定义rowHeight时,它对我有用。它不能通过检查器运行,但是可以通过XML运行。
您可以将原型cells
与自定义一起使用height
,然后调用cellForRowAtIndexPath:
并返回其frame.height
。:。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView
cellForRowAtIndexPath:indexPath];
return cell.frame.size.height;
}
如果要设置静态行高,则可以执行以下操作:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 120;
}
我最近一直在为此而努力。我的问题是上面使用heightForRowAtIndexPath:
方法适用于Simulator中的iOS 7.1,但是只需切换到iOS 8.1,就可以完全。
我开始阅读有关自定义单元的更多信息(在iOS 8中引入,请点击此处)。显然,UITableViewAutomaticDimension
在iOS 8中使用会有所帮助。我尝试使用该技术并删除了对heightForRowAtIndexPath:
和voila 的使用,现在它在iOS 8中运行良好。但是后来不是iOS 7。我该怎么办?我需要heightForRowAtIndexPath:
iOS 7,而不是iOS 8。
这是我的解决方案(为简洁起见,已整理好),它是从上面发布的答案@JosephH中借用的:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 50.;
self.tableView.rowHeight = UITableViewAutomaticDimension;
// ...
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
return UITableViewAutomaticDimension;
} else {
NSString *cellIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
static NSMutableDictionary *heightCache;
if (!heightCache)
heightCache = [[NSMutableDictionary alloc] init];
NSNumber *cachedHeight = heightCache[cellIdentifier];
if (cachedHeight)
return cachedHeight.floatValue;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
CGFloat height = cell.bounds.size.height;
heightCache[cellIdentifier] = @(height);
return height;
}
}
- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath {
NSString * reuseIdentifier;
switch (indexPath.row) {
case 0:
reuseIdentifier = EventTitleCellIdentifier;
break;
case 2:
reuseIdentifier = EventDateTimeCellIdentifier;
break;
case 4:
reuseIdentifier = EventContactsCellIdentifier;
break;
case 6:
reuseIdentifier = EventLocationCellIdentifier;
break;
case 8:
reuseIdentifier = NotesCellIdentifier;
break;
default:
reuseIdentifier = SeparatorCellIdentifier;
break;
}
return reuseIdentifier;
}
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@“ 8.0”)实际上来自我在某处使用的一组宏定义(非常有帮助)。它们定义为:
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
使用Swift 4在XCode 9上工作时,发生了相同的问题。
为单元格内的UI元素添加自动布局,自定义单元格行高将按照指定的方式工作。
我能找到的唯一真正的解决方案是
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...; // Instantiate with a "common" method you'll use again in cellForRowAtIndexPath:
return cell.frame.size.height;
}
这可以正常工作,并且不会造成可怕的切换/如果复制了StoryBoard中已经存在的逻辑。不确定性能,但我猜想是什么时候进来的cellForRow:
已经初始化的单元,速度就一样快。当然,这里可能会有附带损害赔偿,但看起来对我来说很好。
我也在这里发布了此内容:https : //devforums.apple.com/message/772464
编辑:奥尔特温·根茨提醒我,heightForRowAtIndexPath:
将被称为所有 TableView的单元,而不仅仅是可见的单元格。听起来合乎逻辑,因为iOS需要知道总高度才能显示正确的滚动条。这意味着在较小的TableViews(例如20个单元格)上可能还不错,但在1000个Cell TableView上却忘了它。
同样,使用XML的先前技巧:与对我的第一条评论相同。正确的值已经在那里。
鉴于我没有通过Interface Builder找到任何解决方案,所以即使最初的问题要求通过Interface Builder解决,我还是决定使用两个动态单元格在Swift中发布程序化解决方案。无论如何,我认为这对于Stack Overflow社区可能会有所帮助:
import UIKit
enum SignInUpMenuTableViewControllerCellIdentifier: String {
case BigButtonCell = "BigButtonCell"
case LabelCell = "LabelCell"
}
class SignInUpMenuTableViewController: UITableViewController {
let heightCache = [SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell : CGFloat(50),
SignInUpMenuTableViewControllerCellIdentifier.LabelCell : CGFloat(115)]
private func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> SignInUpMenuTableViewControllerCellIdentifier {
if indexPath.row == 2 {
return SignInUpMenuTableViewControllerCellIdentifier.LabelCell
} else {
return SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.heightCache[self.cellIdentifierForIndexPath(indexPath)]!
}
...
}
您可以做的另一件事是转到文档大纲,选择嵌套了原型单元的表格视图。然后在“大小”检查器上,将表格视图的“行高”更改为所需的值,然后取消选中“自动”框。