103

我在调整 tableHeaderView 的大小时遇到​​问题。简单的不行。

1)创建一个UITableView和UIView(100 x 320 px);

2)将UIView设置为UITableView的tableHeaderView;

3) 构建并运行。一切都好。

现在,我想调整 tableHeaderView 的大小,所以我在 viewDidLoad 中添加了这段代码:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

tableHeaderView 的高度应该显示为 200,但显示为 100。

如果我写:

self.tableView.autoresizesSubviews = YES;


CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;


self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

然后它从 200 的高度开始,如我所愿。但我希望能够在运行时修改它。

我也试过这个,但没有成功:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

[self.tableView.tableHeaderView setNeedsLayout];
[self.tableView.tableHeaderView setNeedsDisplay];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];

这里的重点是:我们如何在运行时调整 tableHeaderView 的大小???

有没有人能做到这一点?

谢谢

4

19 回答 19

180

仅供参考:我已经通过修改 tableHeaderView 并重新设置它来实现这一点。在这种情况下,当 UIWebView 子视图完成加载时,我正在调整 tableHeaderView 的大小。

[webView sizeToFit];
CGRect newFrame = headerView.frame;
newFrame.size.height = newFrame.size.height + webView.frame.size.height;
headerView.frame = newFrame;
[self.tableView setTableHeaderView:headerView];
于 2009-02-09T01:01:11.097 回答
12

这个答案很旧,显然不适用于 iOS 7 及更高版本。

我遇到了同样的问题,我也想要动画的变化,所以我为我的标题视图创建了一个 UIView 的子类并添加了这些方法:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight{
    NSUInteger oldHeight = self.frame.size.height;
    NSInteger originChange = oldHeight - newHeight;

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.origin.x, 
                        self.frame.origin.y, 
                        self.frame.size.width, 
                        newHeight);

    for (UIView *view in [(UITableView *)self.superview subviews]) {
        if ([view isKindOfClass:[self class]]) {
            continue;
        }
        view.frame = CGRectMake(view.frame.origin.x, 
                            view.frame.origin.y - originChange, 
                            view.frame.size.width, 
                            view.frame.size.height);
    }

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}

这实质上为 UITableView 的所有子视图设置了动画,这些子视图与调用类的类类型不同。在动画结束时,它会在超级视图(UITableView)上调用 setTableHeaderView——如果没有这个,UITableView 的内容将在用户下次滚动时跳回。到目前为止,我发现的唯一限制是,如果用户在动画发生时尝试滚动 UITableView,则滚动将动画化,就好像标题视图没有调整大小一样(如果动画是快的)。

于 2010-02-01T18:42:50.390 回答
11

如果您想有条件地为更改设置动画,您可以执行以下操作:

- (void) showHeader:(BOOL)show animated:(BOOL)animated{

    CGRect closedFrame = CGRectMake(0, 0, self.view.frame.size.width, 0);
    CGRect newFrame = show?self.initialFrame:closedFrame;

    if(animated){
        // The UIView animation block handles the animation of our header view
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.3];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        // beginUpdates and endUpdates trigger the animation of our cells
        [self.tableView beginUpdates];
    }

    self.headerView.frame = newFrame;
    [self.tableView setTableHeaderView:self.headerView];

    if(animated){
        [self.tableView endUpdates];
        [UIView commitAnimations];
    }
}

请注意,动画分为两部分:

  1. 下方单元格的动画tableHeaderView。这是使用beginUpdatesendUpdates
  2. 实际标题视图的动画。这是使用UIView动画块完成的。

为了同步这两个动画,animationCurve必须将其设置为UIViewAnimationCurveEaseInOut,并将持续时间设置为0.3,这似乎是 UITableView 用于其动画的内容。

更新

我在 gihub 上创建了一个 Xcode 项目,它就是这样做的。查看besi/ios-quickiesResizeTableHeaderViewAnimated中的项目

截屏

于 2013-03-14T17:30:20.400 回答
10

I think it should work if you just set the height of myHeaderView like so:

CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;

self.tableView.tableHeaderView = myHeaderView;
于 2009-01-07T03:40:14.737 回答
6

在 iOS 7 之前使用上述@garrettmoon 解决方案。
这是基于@garrettmoon 的更新解决方案:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight animated:(BOOL)animated {

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:[CATransaction animationDuration]];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.origin.x,
                        self.frame.origin.y,
                        self.frame.size.width,
                        newHeight);

    [(UITableView *)self.superview setTableHeaderView:self];

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}
于 2013-09-24T15:57:39.737 回答
5

这在 iOS 7 和 8 上对我有用。此代码在表视图控制器上运行。

[UIView animateWithDuration:0.3 animations:^{
    CGRect oldFrame = self.headerView.frame;
    self.headerView.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldFrame.size.width, newHeight);
    [self.tableView setTableHeaderView:self.headerView];
}];
于 2014-11-27T00:29:27.097 回答
4

因为tableHeaderView的setter。

您必须在设置 tableHeaderView 之前设置 UIView 高度。(如果Apple开源这个框架会容易得多......)

于 2010-09-19T21:08:37.357 回答
4

在 iOS 9 及更低版本上,tableHeaderView调整大小后不会重新布局。此问题已在 iOS 10 中解决。

要解决此问题,只需使用以下代码即可:

self.tableView.tableHeaderView = self.tableView.tableHeaderView;
于 2017-01-23T12:37:23.993 回答
2

对于 swift 5 测试代码

override func viewDidLayoutSubviews() {
      super.viewDidLayoutSubviews()

        guard let headerView = self.tblProfile.tableHeaderView else {
            return
        }

        let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)

        if headerView.frame.size.height != size.height {
            headerView.frame.size.height = size.height
            self.tblProfile.tableHeaderView = headerView
            self.tblProfile.layoutIfNeeded()
        }
    }

注意:您需要给所有子视图的约束形式顶部、底部、前导、尾随。所以它会得到整个所需的大小。

参考取自: https ://useyourloaf.com/blog/variable-height-table-view-header/

于 2019-11-28T05:57:17.180 回答
2

在 iOS 9.x 上,这样做viewDidLoad效果很好:

var frame = headerView.frame
frame.size.height = 11  // New size
headerView.frame = frame

headerView被声明为@IBOutlet var headerView: UIView!并连接在故事板上,它被放置在 tableView 的顶部,以用作 tableHeaderView。

于 2016-06-06T17:31:47.133 回答
2

这仅适用于您使用自动布局并设置translatesAutoresizingMaskIntoConstraints = false为自定义标题视图时。

最好和最简单的方法是覆盖intrinsicContentSize. 内部UITableView用于intrinsicContentSize决定其页眉/页脚大小。在自定义视图中覆盖intrinsicContentSize后,您需要做的如下

  1. 配置自定义页眉/页脚视图的布局(子视图)
  2. 调用invalidateIntrinsicContentSize()
  3. 调用tableView.setNeedsLayout()tableView.layoutIfNeeded()

然后UITableView' 的页眉/页脚将根据需要更新。无需将视图设置为零或重置。

UITableView.tableHeaderView对or来说真正有趣的一件事.tableFooterView是它UIStackView失去了管理它的能力arrangedSubviews。如果要UIStackView用作 tableHeaderView 或 tableFooterView,则必须将 stackView 嵌入 aUIView并覆盖UIView's intrinsicContentSize

于 2018-11-21T21:45:20.287 回答
1

设置标题视图属性的高度似乎不起作用,标题视图高度仍然没有按预期改变。tableView.tableHeaderViewviewDidLoad

经过多次尝试与这个问题作斗争。我发现,您可以通过调用 - (void)didMoveToParentViewController:(UIViewController *)parent方法内部的标题视图创建逻辑来更改高度。

所以示例代码如下所示:

- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];

    if ( _tableView.tableHeaderView == nil ) {
        UIView *header = [[[UINib nibWithNibName:@"your header view" bundle:nil] instantiateWithOwner:self options:nil] firstObject];

        header.frame = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), HeaderViewHeight);

        [_tableView setTableHeaderView:header];
    }
}
于 2017-01-20T02:51:26.257 回答
1

如果自定义 headerView 是使用自动布局设计的,并且 headerView 需要在 web-fetch 或类似的惰性任务之后更新。然后在iOS-Swift中我这样做了,并使用以下代码更新了我的 headerView:

//to reload your cell data
self.tableView.reloadData()
DispatchQueue.main.async {
// this is needed to update a specific tableview's headerview layout on main queue otherwise it's won't update perfectly cause reloaddata() is called
  self.tableView.beginUpdates()
  self.tableView.endUpdates()
}
于 2016-06-06T09:19:49.123 回答
0

我发现 UIView 的 initWithFrame 初始化程序没有正确地尊重我传入的矩形。因此,我做了以下完美的工作:

 - (id)initWithFrame:(CGRect)aRect {

    CGRect frame = [[UIScreen mainScreen] applicationFrame];

    if ((self = [super initWithFrame:CGRectZero])) {

        // Ugly initialization behavior - initWithFrame will not properly honor the frame we pass
        self.frame = CGRectMake(0, 0, frame.size.width, 200);

        // ...
    }
}

这样做的好处是它可以更好地封装到您的视图代码中。

于 2010-12-05T16:34:56.333 回答
0

我已经实现了表格标题的动画高度变化,以便在点击时扩展到整个屏幕。但是,该代码可以在其他情况下提供帮助:

// Swift
@IBAction func tapped(sender: UITapGestureRecognizer) {

    self.tableView.beginUpdates()       // Required to update cells. 

    // Collapse table header to original height
    if isHeaderExpandedToFullScreen {   

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = 110   // original height in my case is 110
        })

    }
    // Expand table header to overall screen            
    else {      
        let screenSize = self.view.frame           // "screen" size

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = screenSize.height
        })
    }

    self.tableView.endUpdates()  // Required to update cells. 

    isHeaderExpandedToFullScreen= !isHeaderExpandedToFullScreen  // Toggle
}
于 2014-09-21T16:11:14.533 回答
0

UITableView 调整标题 - 带有范围栏的 UISearchBar

我想要 aUITableView作为UISearchBar表的标题,所以我有一个看起来像这样的层次结构

UITableView
  |
  |--> UIView
  |     |--> UISearchBar
  |
  |--> UITableViewCells

UISearchBarDelegate 方法

如其他地方所述,如果您在更改后不 setTableViewHeader ,则不会发生任何事情。

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = YES;
    [UIView animateWithDuration:0.2f animations:^{
        [searchBar sizeToFit];
        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:YES animated:YES];
    return YES;
}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = NO;
    [UIView animateWithDuration:0.f animations:^{
        [searchBar sizeToFit];

        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:NO animated:YES];
    return YES;
}
于 2015-06-06T12:23:59.827 回答
0

显然,到目前为止,Apple 应该已经为 tableHeaderView 和 tableFooterView 实现了 UITableViewAutomaticDimension ...

使用布局约束,以下内容似乎对我有用:

CGSize   s  = [ self  systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ];
CGRect   f  = [ self  frame ];

f.size   = s;

[ self  setFrame : f ];
于 2017-12-30T15:04:13.660 回答
0

如果您的 tableHeaderView 是内容可调整的 webView,您可以尝试:

[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    self.webView.height = self.webView.scrollView.contentSize.height;
    self.tableView.tableHeaderView = self.webView;
}

我在 iOS9 和 iOS11 上测试过,运行良好。

于 2018-09-27T09:37:22.323 回答
-3

[self.tableView reloadData]改变高度后你试过 了吗?

于 2008-12-05T01:11:23.060 回答