故事板中的自定义单元格行高度设置没有响应
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了故事板中的自定义单元格行高度设置没有响应相关的知识,希望对你有一定的参考价值。
我正在尝试调整表格视图中其中一个单元格的单元格高度。我正在从相关单元格的“尺寸检查器”中的“行高”设置中调整大小。当我在iPhone上运行应用程序时,单元格的默认大小设置为表格视图中的“行大小”。
如果我更改表视图的“行大小”,则所有单元格的大小都会更改。我不想这样做,因为我只想要一个单元格的自定义大小。我已经看到很多帖子都有针对该问题的程序化解决方案,但我更愿意通过故事板来实现,如果可能的话。
在动态单元格上,在UITableView上设置的rowHeight
总是覆盖单个单元格的rowHeight。
但是在静态单元格上,在单个单元格上设置的rowHeight
可以覆盖UITableView。
不确定这是不是一个bug,Apple可能是故意这样做的?
您可以使用原型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:
方法发布的解决方案适用于模拟器中的ios 7.1,但是通过简单地切换到iOS 8.1完全搞砸了结果。
我开始阅读更多关于自我调整细胞的信息(在iOS 8中引入,read here)。很明显,在iOS 8中使用UITableViewAutomaticDimension
会有所帮助。我尝试使用该技术并删除了heightForRowAtIndexPath:
和voila的使用,它现在在iOS 8中运行完美。但后来iOS 7却没有。我该怎么办?我需要适用于iOS 7的heightForRowAtIndexPath:
而不适用于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)
对于动态单元格,UITableView上设置的rowHeight始终会覆盖单个单元格的rowHeight。如果行内的内容,只需计算动态高度。
使用Swift 4在XCode 9上工作时出现同样的问题。
为单元格内的UI元素添加AutoLayout,自定义单元格行高度将按指定的方式相应地工作。
我能找到的唯一真正的解决方案就是这个
- (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
编辑:Ortwin Gentz提醒我,将为TableView的所有单元格调用heightForRowAtIndexPath:
,而不仅仅是可见的单元格。听起来合乎逻辑,因为iOS需要知道能够显示正确滚动条的总高度。这意味着它可能适用于小型TableView(如20个单元格)但在1000 Cell TableView上忘记了它。
此外,XML的前一个技巧:与我的第一个评论相同。正确的价值已经存在。
添加为评论,但发布为可见性的答案:
如果您最初将表视图设置为“静态单元”,然后将其更改为“动态原型”,则似乎也存在问题。我有一个问题,甚至heightForRowAtIndexPath
的委托方法被忽略了。我首先通过直接编辑故事板XML来解决它,然后最终从头开始重建故事板场景,从一开始就使用动态原型。
鉴于我没有通过Interface Builder找到任何解决这个问题的方法,我决定使用两个动态单元在Swift中发布一个程序化解决方案,即使最初的问题是通过Interface Builder要求解决方案。无论我认为它对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)]!
}
...
}
您可以做的另一件事是转到文档大纲,选择嵌套原型单元格的表格视图。然后在“大小”检查器上,将表格视图“行高”更改为所需的值,并取消选中“自动”框。
如果您使用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,一个bug。任何时候你必须在两个地方管理你的UI很容易出错。例如,如果您在故事板中更改单元格大小,则必须记住在heightForRowAtIndexPath:
中更改它们。在Apple修复bug之前,目前最好的解决方法是覆盖heightForRowAtIndexPath:
,但是使用故事板中的实际原型单元来确定高度而不是使用magic numbers。这是一个例子:
- (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以上是关于故事板中的自定义单元格行高度设置没有响应的主要内容,如果未能解决你的问题,请参考以下文章