tableFooterView属性不修复表格视图底部的页脚

我在viewDidLoad方法中设置页脚视图:

UIView *fView = [[UIView alloc] initWithFrame:CGRectMake(0, 718, 239, 50)]; fView.backgroundColor =[UIColor yellowColor]; self.table.tableFooterView = fView; 

不幸的是,页脚并没有绘制上面指定的(x,y) ,而是粘在单元格上,所以如果表格视图有4个单元格,页脚将被绘制在第5个单元格中。

我什至尝试了协议方法, tableView:viewForFooterInSection

 - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{ UIView *fView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 239, 50)]; fView.backgroundColor =[UIColor yellowColor]; return fView; } 

问题没有解决,我相信tableFooterView属性应该fi在表视图底部的页脚视图,但我不知道我可能会在这里失踪? 提前感谢。

既然你的目标是有一个页脚,保持固定在屏幕的底部,而不是与表滚动,那么你不能使用表视图页脚。 事实上,你甚至不能使用UITableViewController

你必须实现你的视图控制器作为UIViewController 。 然后,将您自己的表格视图添加为子视图。 您还将页脚添加为视图控制器视图的子视图,而不是表视图。 确保调整表格视图的大小,使其底部位于页脚视图的顶部。

您将需要使您的视图控制器符合UITableViewDataSourceUITableViewDelegate协议,并钩住一切,以复制UITableViewController的function。

页脚视图将始终添加到内容的底部。
这意味着在页面的单元格下方会添加一个页脚,而不pipe在视图中设置的位置如何,页脚视图都位于所有部分的底部。

如果你想添加一个“静态”的内容,你应该考虑在表视图(超级视图)之外添加一个视图 – 如果你使用UITableViewController这是不可能的,或者你使用[self.table addSubView:view]并调整位置/转换为scrollViewDidScroll: delegate方法中的表视图的contentOffset属性( UITableViewUIScrollView的子类,因此您也可以获得委托调用),如下面的代码所示:

 @implementation YourTableViewController { __weak UIView *_staticView; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIView *staticView = [[UIView alloc] initWithFrame:CGRectMake(0, self.tableView.bounds.size.height-50, self.tableView.bounds.size.width, 50)]; staticView.backgroundColor = [UIColor redColor]; [self.tableView addSubview:staticView]; _staticView = staticView; self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0); } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { _staticView.transform = CGAffineTransformMakeTranslation(0, scrollView.contentOffset.y); } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // this is needed to prevent cells from being displayed above our static view [self.tableView bringSubviewToFront:_staticView]; } ... 

另一种方法是在故事板中使用UITableViewController ,并将其作为容器视图embedded到UIViewController中。 然后,您可以使用自动布局来设置页脚和包含UITableView的容器视图之间的关系

如果您的表视图或表格视图控制器被导航控制器包装,请考虑使用导航控制器的UIToolbar。 它会一直坚持到底。

 [self.navigationController setToolbarHidden:NO]; 

我能够得到一个标签被固定到我的静态UITableViewController的底部。 不是所有情况的完美解决scheme,但为我的简单需求工作。

 UIView* v = [[UIView alloc] initWithFrame:self.view.bounds]; CGFloat labelHeight = 30; CGFloat padding = 5; UILabel* l = [[UILabel alloc] initWithFrame:CGRectMake(0, v.frame.size.height - labelHeight - padding, self.view.frame.size.width, labelHeight)]; l.text = @"Hello World"; [v addSubview:l]; [self.tableView setBackgroundView:v]; 

以下是这个页脚问题的解决scheme,当我们不希望页脚始终粘在底部时,AKA。 当没有足够的行填充屏幕时,或者当用户一直向下滚动屏幕时,它只粘到底部。

添加self.footerView到你的self.tableView作为子视图在-viewDidLoad:或者类似的地方,然后设置self.tableView的委托,更新tableview的内容插入self.tableView.contentInset = UIEdgeInsetsMake(0, 0, CGRectGetHeight(self.footerView), 0); 并设置了以下方法:

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { [self updateFooterView]; } - (void)updateFooterView { CGRect sectionFrame = [self.tableView rectForSection:0]; CGFloat bottomSpace = self.tableView.contentOffset.y + CGRectGetHeight(self.tableView.frame) - CGRectGetMaxY(sectionFrame); CGFloat footerHeight = CGRectGetHeight(self.footerView.frame); CGFloat transformY = self.tableView.contentOffset.y + footerHeight - MIN(bottomSpace,footerHeight); CGRect footerFrame = self.footerView.frame; footerFrame.origin.y = self.tableView.bounds.size.height - footerFrame.size.height + transformY; self.footerView.frame = footerFrame; } 

每当你需要更新页脚(即添加一个新的行后),只需调用-updateFooterView ,你应该是好的

如果要将页脚固定在底部,则应在tableView内容大小更改时创build自定义的footerView并更改页脚框架:

 -(void)changeCustomTableFooterYPositionWithTableFrame:(CGRect)tableFrame tableContentSize: (CGSize) tableContentSize { CGFloat originalTableViewTopEdgeInset = self.tableView.contentInset.top; CGFloat originalTableViewBottomEdgeInset = self.tableView.contentInset.bottom - self.tableFooterView.frame.size.height; CGFloat footerViewYPositionByContentSize = tableContentSize.height; CGFloat footerViewYPositionByTableSize = tableFrame.size.height - self.tableFooterView.frame.size.height - originalTableViewTopEdgeInset - originalTableViewBottomEdgeInset; CGFloat tableFooterViewYPosition = MAX(footerViewYPositionByContentSize, footerViewYPositionByTableSize); self.tableFooterView.frame = CGRectMake(self.tableFooterView.frame.origin.x, tableFooterViewYPosition, self.customTableFooterView.frame.size.width, self.customTableFooterView.frame.size.height); } 

要检测contentSize是否已更改,请将观察者添加到contentSize:

  [self addObserver: self forKeyPath: @"tableView.contentSize" options: NSKeyValueObservingOptionNew + NSKeyValueObservingOptionOld context: ContentSizeContext]; 

插入页脚时不要忘记更改tableView.edgeInsets:

 self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, self.tableView.contentInset.bottom + self.customTableFooterView.frame.size.height, self.tableView.contentInset.right); 

您可以在下面的链接中看到inheritance的类和示例: TableViewWithFooterAtBottom

你可以使用这个来使表格看起来更小,这取决于你有多less行:

  let tblView = UIView(frame: CGRectZero) tableView.tableFooterView = tblView tableView.tableFooterView!.hidden = true tableView.backgroundColor = UIColor.clearColor() 

另一种方法是在索引path上更改行的高度,具体取决于您遇到问题的最小行数。

看起来像下面类似的东西很好:

 import PlaygroundSupport import UIKit let testVC = UITableViewController(style: .grouped) testVC.view.frame = CGRect(x: 0, y: 0, width: 400, height: 700) testVC.view.backgroundColor = .white class TableViewDataSourceDelegate : NSObject { var rows = 2 } extension TableViewDataSourceDelegate : UITableViewDataSource, UITableViewDelegate { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return rows } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = UITableViewCell(style: .default, reuseIdentifier: nil) cell.backgroundColor = .red return cell } func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { let tableViewHeight = tableView.bounds.size.height let varticalMargin: CGFloat if #available(iOS 11.0, *) { varticalMargin = tableView.directionalLayoutMargins.bottom + tableView.directionalLayoutMargins.top } else { varticalMargin = tableView.layoutMargins.bottom + tableView.layoutMargins.top } let verticalInset: CGFloat if #available(iOS 11.0, *) { verticalInset = tableView.adjustedContentInset.bottom + tableView.adjustedContentInset.top } else { verticalInset = tableView.contentInset.bottom + tableView.contentInset.top } let tableViewContentHeight = tableView.contentSize.height - varticalMargin let height: CGFloat if #available(iOS 11.0, *) { let verticalSafeAreaInset = tableView.safeAreaInsets.bottom + tableView.safeAreaInsets.top height = tableViewHeight - tableViewContentHeight - verticalInset - verticalSafeAreaInset } else { height = tableViewHeight - tableViewContentHeight - verticalInset } if (height < 0) { return 0 } else { return height } } func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { let extraButtonSpace = UIView() extraButtonSpace.backgroundColor = .clear return extraButtonSpace } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if indexPath.row == 0 { tableView.beginUpdates() rows += 1 tableView.insertRows(at: [indexPath], with: .automatic) tableView.endUpdates() } else if indexPath.row == 1 { tableView.beginUpdates() rows -= 1 tableView.deleteRows(at: [indexPath], with: .automatic) tableView.endUpdates() } else { tableView.beginUpdates() tableView.endUpdates() } } } let controller = TableViewDataSourceDelegate() testVC.tableView.delegate = controller testVC.tableView.dataSource = controller testVC.tableView.reloadData() let extraButtonSpace = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 80)) extraButtonSpace.backgroundColor = .yellow testVC.tableView.tableFooterView = extraButtonSpace PlaygroundPage.current.liveView = testVC.view 

操场上的屏幕