UITableView设置为静态单元格。 是否有可能以编程方式隐藏一些单元格?
UITableView
设置为静态单元格。
是否有可能以编程方式隐藏一些单元格?
您正在寻找这个解决scheme:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
它可以显示/隐藏/重新加载任何静态单元格(有或无animation)!
[self cell:self.outletToMyStaticCell1 setHidden:hide]; [self cell:self.outletToMyStaticCell2 setHidden:hide]; [self reloadDataAnimated:YES];
注意只能使用(reloadDataAnimated:YES / NO)(不要直接调用[self.tableView reloadData])
隐藏UITable中的静态单元格:
- 添加这个方法 :
在你的UITableView控制器委托类中:
Objective-C的:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; if(cell == self.cellYouWantToHide) return 0; //set the hidden cell's height to 0 return [super tableView:tableView heightForRowAtIndexPath:indexPath]; }
迅速:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) if cell == self.cellYouWantToHide { return 0 } return super.tableView(tableView, heightForRowAtIndexPath: indexPath) }
这个方法将被调用UITable中的每个单元格。 一旦它调用它想要隐藏的单元格,我们将其高度设置为0.我们通过为它创build一个出口来识别目标单元格:
- 在devise师中,为要隐藏的单元格创build一个出口。 一个这样的单元格的出口被称为“cellYouWantToHide”上面。
- 在IB中检查“剪辑子视图”,查看要隐藏的单元格。 你隐藏的单元格需要有ClipToBounds = YES。 否则,文本将堆积在UITableView中。
我的解决scheme与Gareth类似,尽pipe我做了一些不同的事情。
开始:
1.隐藏细胞
没有办法直接隐藏细胞。 UITableViewController
是提供静态单元格的数据源,目前没有办法告诉它“不要提供单元格x”。 所以我们必须提供自己的数据源,这个数据源委托给UITableViewController
来获取静态单元格。
最简单的方法是UITableViewController
,并覆盖隐藏单元格时需要有不同行为的所有方法 。
在最简单的情况下(单节表,所有单元格高度相同),这将是这样的:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Recalculate indexPath based on hidden cells indexPath = [self offsetIndexPath:indexPath]; return [super tableView:tableView cellForRowAtIndexPath:indexPath]; } - (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath { int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row int offsetRow = indexPath.row + numberOfCellsHiddenAbove; return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection]; }
如果您的表格有多个部分,或者单元格的高度不同,则需要覆盖更多的方法。 同样的原则适用于这里:在委托给super之前,你需要偏移indexPath,section和row。
还要记住,像didSelectRowAtIndexPath:
这样的方法的indexPath参数对于同一个单元格是不同的,这取决于状态(即隐藏的单元数)。 所以总是偏移任何indexPath参数并使用这些值可能是一个好主意。
2.animation变化
正如Gareth已经指出的,如果使用reloadSections:withRowAnimation:
方法改变animation,则会出现重大故障。
我发现,如果你调用reloadData:
之后立即animation是大大改善(只有轻微的毛刺留下)。 animation后表格正确显示。
所以我正在做的是:
- (void)changeState { // Change state so cells are hidden/unhidden ... // Reload all sections NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])]; [tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic]; [tableView reloadData]; }
最好的方法是在下面的博客http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
在界面构build器中正常devise静态表视图 – 完成所有可能隐藏的单元。 但是你必须为每一个你想隐藏的单元格做一件事 – 检查单元格的“Clip subviews”属性,否则当你试图隐藏它时,单元格的内容不会消失(通过缩小它的高度 – 更晚)。
所以 – 你有一个单元格的开关,开关应该隐藏并显示一些静态单元格。 连接到一个IBAction,并在那里做到这一点:
[self.tableView beginUpdates]; [self.tableView endUpdates];
这给你很好的animation细胞出现和消失。 现在实现下面的表视图委托方法:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
就是这样。 翻转开关和细胞隐藏和重新出现一个很好,stream畅的animation。
我想出了一个替代scheme,实际上隐藏了部分并且不删除它们。 我尝试了@ henning77的方法,但是当我改变了静态UITableView的部分数时,我一直在遇到问题。 这种方法对我来说真的很好,但我主要是试图隐藏部分而不是行。 我正在成功移除一些行,但是它更加复杂,所以我试图将事物分成几部分,我需要显示或隐藏。 这里是我隐藏部分的一个例子:
首先我声明一个NSMutableArray属性
@property (nonatomic, strong) NSMutableArray *hiddenSections;
在viewDidLoad中(或在查询完数据后),可以将要隐藏的部分添加到数组中。
- (void)viewDidLoad { hiddenSections = [NSMutableArray new]; if(some piece of data is empty){ // Add index of section that should be hidden [self.hiddenSections addObject:[NSNumber numberWithInt:1]]; } ... add as many sections to the array as needed [self.tableView reloadData]; }
然后实现下面的TableView委托方法
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){ return nil; } return [super tableView:tableView titleForHeaderInSection:section]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){ return 0; } return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]]; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){ [cell setHidden:YES]; } }
然后将页眉和页脚高度设置为1,因为不能将高度设置为0.这会导致额外的2像素空间,但是我们可以通过调整下一个可见标题的高度来弥补它。
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { CGFloat height = [super tableView:tableView heightForHeaderInSection:section]; if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){ height = 1; // Can't be zero } else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil // Adjust height for previous hidden sections CGFloat adjust = 0; for(int i = (section - 1); i >= 0; i--){ if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){ adjust = adjust + 2; } else { break; } } if(adjust > 0) { if(height == -1){ height = self.tableView.sectionHeaderHeight; } height = height - adjust; if(height < 1){ height = 1; } } } return height; } -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){ return 1; } return [super tableView:tableView heightForFooterInSection:section]; }
然后,如果您确实有隐藏的特定行,您可以调整numberOfRowsInSection以及在cellForRowAtIndexPath中返回哪些行。 在这个例子中,我有一个有三行的部分,其中三个可以是空的,需要删除。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger rows = [super tableView:tableView numberOfRowsInSection:section]; if(self.organization != nil){ if(section == 5){ // Contact if([self.organization objectForKey:@"Phone"] == [NSNull null]){ rows--; } if([self.organization objectForKey:@"Email"] == [NSNull null]){ rows--; } if([self.organization objectForKey:@"City"] == [NSNull null]){ rows--; } } } return rows; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]]; }
使用此offsetIndexPath来计算您有条件删除行的行的indexPath。 如果你只是隐藏部分不需要
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath { int row = indexPath.row; if(self.organization != nil){ if(indexPath.section == 5){ // Adjust row to return based on which rows before are hidden if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){ row++; } else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){ row = row + 2; } else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){ row++; } else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){ row++; } } } NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section]; return offsetPath; }
有很多方法可以覆盖,但我喜欢这种方法是可重用的。 设置hiddenSections数组,添加到它,它会隐藏正确的部分。 隐藏行有点棘手,但可能。 如果我们使用分组的UITableView,我们不能只将我们要隐藏的行的高度设置为0,因为边框不能正确绘制。
是的,这绝对是可能的,虽然我现在正在同样的问题挣扎。 我已经设法隐藏单元格,一切正常,但是我现在不能使这个单元格整齐地动起来。 这是我发现的:
我在第一部分的第一行中根据ON / OFF开关的状态来隐藏行。 如果开关处于ON状态,则同一部分下面有一行,否则有两行。
当开关切换时,我有一个select器,我设置了一个variables来表示我在哪个状态。然后我打电话给:
[[self tableView] reloadData];
我重写tableView:willDisplayCell:forRowAtIndexPath:函数,如果单元格应该隐藏我这样做:
[cell setHidden:YES];
隐藏单元格及其内容,但不会删除占用的空间。
要删除空间,请覆盖tableView:heightForRowAtIndexPath:函数,并为应该隐藏的行返回0。
您还需要重写tableView:numberOfRowsInSection:并返回该部分中的行数。 你必须在这里做一些奇怪的事情,所以如果你的表是一个分组样式,圆angular会出现在正确的单元格上。 在我的静态表格中有一整组单元格,所以第一个单元格包含选项,然后是1个单元格用于ON状态选项,另外2个单元格用于OFF状态选项,共有4个单元格。 当选项为ON时,我必须返回4,这包括隐藏的选项,以便显示的最后一个选项有一个圆angular框。 当选项closures时,最后两个选项不显示,所以我返回2.这一切都感觉笨重。 对不起,如果这不是很清楚,它的棘手来形容。 为了说明设置,这是IB中表格部分的构build:
- 第0行:带有ON / OFF开关的选项
- 第1行:选项打开时显示
- 第2行:选项closures时显示
- 第3行:选项closures时显示
所以当选项为ON时,表格会报告两行:
- 第0行:带有ON / OFF开关的选项
- 第1行:选项打开时显示
当选项为OFF时,表格报告四行:
- 第0行:带有ON / OFF开关的选项
- 第1行:选项打开时显示
- 第2行:选项closures时显示
- 第3行:选项closures时显示
这种方法由于以下几个原因而感觉不正确,就目前为止我所做的实验一样,所以请让我知道如果你find更好的方法。 我目前观察到的问题是:
-
告诉表格的行数不同于底层数据中可能包含的行数。
-
我似乎无法动摇这一变化。 我试过使用tableView:reloadSections:withRowAnimation:而不是reloadData和结果似乎没有道理,我仍然试图得到这个工作。 目前看来发生的事情是tableView不会更新正确的行,所以应该显示一个隐藏,并在第一行下留下一个空白。 我认为这可能与底层数据的第一点有关。
希望有人能够build议替代方法,或者如何扩展animation,但也许这会让你开始。 我很抱歉缺lessfunction的超链接,我把它们放进去,但他们被垃圾邮件filter拒绝,因为我是一个相当新的用户。
事实certificate,你可以隐藏和显示单元格在一个静态的UITableView和animation。 这并不难完成。
演示项目
演示项目video
要旨:
-
Use tableView:heightForRowAtIndexPath:
根据某些状态dynamic指定单元格高度。 - 当状态通过调用
tableView.beginUpdates();tableView.endUpdates()
更改显示/隐藏的animation单元时, - 不要调用
tableView.cellForRowAtIndexPath:
在tableView:heightForRowAtIndexPath:
使用caching的indexPaths来区分单元格。 - 不要隐藏细胞。 改为在Xcode中设置“Clip Subviews”属性。
- 使用自定义单元格(而不是简单等)来获得一个很好的隐藏animation。 另外,当单元格高度== 0时,正确处理自动布局。
更多信息在我的博客(俄语)
- 在devise师中,为要隐藏的单元格创build一个出口。 例如,你想隐藏'cellOne',所以在viewDidLoad()这样做
cellOneOutlet.hidden = true
现在覆盖下面的方法,检查哪些单元格状态被隐藏,并返回这些单元格的高度0。 这是你可以用swift隐藏静态tableView中的任何单元格的许多方法之一。
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat { let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath) if tableViewCell.hidden == true { return 0 } else{ return super.tableView(tableView, heightForRowAtIndexPath: indexPath) } }
上述答案,隐藏/显示单元格,更改rowHeight,或混乱自动布局约束不适用于我,因为自动布局的问题。 代码变得无法容忍。
对于一个简单的静态表,最适合我的是:
- 为静态表中的每个单元格创build一个出口
- 只用单元格的出口创build一个数组来显示
- 重写cellForRowAtIndexPath以从数组中返回单元格
- 覆盖numberOfRowsInSection以返回数组的计数
- 实现一个方法来确定哪些单元格需要在该数组中,并在需要时调用该方法,然后重载数据。
这里是我的表视图控制器的一个例子:
@IBOutlet weak var titleCell: UITableViewCell! @IBOutlet weak var nagCell: UITableViewCell! @IBOutlet weak var categoryCell: UITableViewCell! var cellsToShow: [UITableViewCell] = [] override func viewDidLoad() { super.viewDidLoad() determinCellsToShow() } func determinCellsToShow() { if detail!.duration.type != nil { cellsToShow = [titleCell, nagCell, categoryCell] } else { cellsToShow = [titleCell, categoryCell] } } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return cellsToShow[indexPath.row] } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return cellsToShow.count }
我发现了静态表格中animation隐藏单元格的解决scheme。
// Class for wrapping Objective-C block typedef BOOL (^HidableCellVisibilityFunctor)(); @interface BlockExecutor : NSObject @property (strong,nonatomic) HidableCellVisibilityFunctor block; + (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block; @end @implementation BlockExecutor @synthesize block = _block; + (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block { BlockExecutor * executor = [[BlockExecutor alloc] init]; executor.block = block; return executor; } @end
只需要一个额外的字典:
@interface MyTableViewController () @property (nonatomic) NSMutableDictionary * hidableCellsDict; @property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch; @end
并看看MyTableViewController的实现。 我们需要两种方法来转换可见和不可见索引之间的indexPath …
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath { int rowDelta = 0; for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)]) { BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip]; if (ip.section == indexPath.section && ip.row <= indexPath.row + rowDelta && !executor.block()) { rowDelta++; } } return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section]; } - (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath { int rowDelta = 0; for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)]) { BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip]; if (ip.section == indexPath.section && ip.row < indexPath.row - rowDelta && !executor.block()) { rowDelta++; } } return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section]; }
一个关于UISwitch值变化的IBAction:
- (IBAction)birthdaySwitchChanged:(id)sender { NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]]; if (self.birthdaySwitch.on) [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; else [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; }
一些UITableViewDataSource和UITableViewDelegate方法:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { int numberOfRows = [super tableView:tableView numberOfRowsInSection:section]; for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys]) if (indexPath.section == section) { BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath]; numberOfRows -= (executor.block()?0:1); } return numberOfRows; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { indexPath = [self recoverIndexPath:indexPath]; return [super tableView:tableView cellForRowAtIndexPath:indexPath]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { indexPath = [self recoverIndexPath:indexPath]; return [super tableView:tableView heightForRowAtIndexPath:indexPath]; } - (void)viewDidLoad { [super viewDidLoad]; // initializing dictionary self.hidableCellsDict = [NSMutableDictionary dictionary]; [self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]]; } - (void)viewDidUnload { [self setBirthdaySwitch:nil]; [super viewDidUnload]; } @end
在swift中回答:
在你的TableViewController中添加下面的方法:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath) }
如果tableView试图绘制你想要隐藏的单元格,那么它将不会显示它,因为它的高度将被设置为0pt,这要归功于上面的方法,其他一切都保持不变。
请注意, indexPathOfCellYouWantToHide
可以随时更改:)
在> Swift 2.2中,我在这里合并了几个答案。
从故事板做出一个出口链接到您的staticCell。
@IBOutlet weak var updateStaticCell: UITableViewCell! override func viewDidLoad() { ... updateStaticCell.hidden = true } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { if indexPath.row == 0 { return 0 } else { return super.tableView(tableView, heightForRowAtIndexPath: indexPath) } }
我想隐藏我的第一个单元格,所以我把高度设置为0,如上所述。
对于隐藏表格视图底部的单元格的最简单的情况,您可以在隐藏单元格后调整tableView的contentInset:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections { CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right); }
这是使用https://github.com/k06a/ABStaticTableViewController执行此操作的新方法;
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1]; [self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
从k06a( https://github.com/k06a/ABStaticTableViewController )解决scheme是更好的,因为它隐藏整个部分,包括单元格页眉和页脚,在此解决scheme( https://github.com/peterpaulis/StaticDataTableViewController )隐藏除了页脚之外的所有内容。
编辑
我只是发现解决scheme,如果你想隐藏页脚在StaticDataTableViewController
。 这是你需要在StaticTableViewController.m文件中复制的内容:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { return nil; } else { return [super tableView:tableView titleForFooterInSection:section]; } } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { CGFloat height = [super tableView:tableView heightForFooterInSection:section]; if (self.originalTable == nil) { return height; } if (!self.hideSectionsWithHiddenRows) { return height; } OriginalSection * os = self.originalTable.sections[section]; if ([os numberOfVissibleRows] == 0) { //return 0; return CGFLOAT_MIN; } else { return height; } //return 0; return CGFLOAT_MIN; }
当然可以。 首先,返回你想要显示的tableView的单元格数量,然后调用super
从storyboard中获得某个单元格,并将其返回给tableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.mode.numberOfCells() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath)) return cell }
如果你的细胞有不同的回报,
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath)) }
除了@Saleh Masum解决scheme:
如果你得到自动布局错误 ,你可以从tableViewCell.contentView
删除约束
Swift 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath) if tableViewCell.isHidden == true { tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints) return 0 } else{ return super.tableView(tableView, heightForRowAt: indexPath) } }
这个解决scheme取决于你的应用程序的stream程 。 如果你想在同一个视图控制器实例中显示/隐藏单元格,这可能不是最好的select,因为它消除了约束 。
简单的iOS 11和IB / Storyboard兼容方法
对于iOS 11,我发现修改后的Mohamed Saleh的答案效果最好,基于苹果的文档进行了一些改进。 它animation很好,避免了任何丑陋的黑客或硬编码的值,并使用已在界面生成器中设置的行高 。
基本的概念是为任何隐藏的行设置行高为0。 然后使用tableView.performBatchUpdates
来触发一致的animation。
设置单元高度
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath == indexPathOfHiddenCell { if cellIsHidden { return 0 } } // Calling super will use the height set in your storyboard, avoiding hardcoded values return super.tableView(tableView, heightForRowAt: indexPath) }
你会想确保cellIsHidden
和indexPathOfHiddenCell
被设置为适合你的用例。 对于我的代码,他们是我的表视图控制器上的属性。
切换单元格
在任何方法控制可见性(可能是一个button操作或didSelectRow
),切换一个performBatchUpdates
块内的cellIsHidden状态:
tableView.performBatchUpdates({ // Use self to capture for block self.cellIsHidden = !self.cellIsHidden }, completion: nil)
苹果公司build议performBatchUpdates
beginUpdates
/ endUpdates
尽可能。