UITableView 的 tableHeaderView height 属性在加载和旋转期间更改为奇怪的值

发布于 2025-01-04 14:20:31 字数 2284 浏览 4 评论 0原文

我有一个自定义 UIView,在 loadView 期间将其设置为 UITableView 的 tableHeaderView 属性:

headerView = [[MYViewClass alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 120)];
[headerView sizeToFit];

self.tableView.tableHeaderView = headerView;

视图绘制不正确,部分视图被剪切,表格上方有空白。旋转设备时,视图几乎消失。向后旋转时,视图现在大于标题的空间,并遮挡了表格中的一些单元格。

为了排除故障,我在自定义视图类中覆盖了 setFrame 方法:

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    NSLog(@"%@ - %@", NSStringFromSelector(_cmd), NSStringFromCGRect(frame));
}

我还在 NSLog 语句上放置了一个断点,这样我就可以看到所谓的 setFrame 的内容,并且得到了一些我无法解释的奇怪结果,希望有人能够摆脱一些阐明正在发生的事情及其原因。

在loadView期间

1. initWithFrame calls: setFrame: - {{0, 0}, {320, 120}}
2. sizeToFit calls: setFrame: - {{0, 0}, {320, 109}}
3. setTableHeaderView calls:  setFrame: - {{0, 0}, {320, 109}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 109}}
5. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 65}}
6. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 65}}
7. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 65}}

向左旋转设备

1. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {480, 0}}
2. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {480, 0}}
3. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {480, 12}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {480, 12}}

向右旋转设备

1. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 172}}
2. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 172}}
3. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 160}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 160}}

这解释了为什么我的视图最初看起来被截断,然后几乎消失,最后最终与单元格重叠。看来 _resizeWithOldSuperviewSize 是罪魁祸首,我不明白的是为什么调用它以及它从哪里获取这些奇怪的值。

我通过在 viewDidAppear:didRotateFromInterfaceOrientation: 中调用 [self.tableView.tableHeaderView sizeToFit] 来解决这个问题,这将框架放回到尺寸正确,但重绘很糟糕,因为两者都发生在视图可见之后或旋转动画之后。在视图可见之前尝试设置此值会导致 _resizeWithOldSuperViewSize 将框架设置回这些奇怪的尺寸。

I have a custom UIView which I set to the tableHeaderView property of a UITableView during loadView:

headerView = [[MYViewClass alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 120)];
[headerView sizeToFit];

self.tableView.tableHeaderView = headerView;

The view draws incorrectly, with part of the view clipped and white space above the table. When rotating the device the view almost disappears. On rotating back the view is now bigger that the space for the header and obscures some of the cells in the table.

To troubleshoot I have overrode the setFrame method in my custom view class:

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    NSLog(@"%@ - %@", NSStringFromSelector(_cmd), NSStringFromCGRect(frame));
}

I also put a break point on the NSLog statement so I could see what called the setFrame and I get some odd results that I can't explain and hope someone can shed some light on what is happening and why.

During loadView

1. initWithFrame calls: setFrame: - {{0, 0}, {320, 120}}
2. sizeToFit calls: setFrame: - {{0, 0}, {320, 109}}
3. setTableHeaderView calls:  setFrame: - {{0, 0}, {320, 109}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 109}}
5. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 65}}
6. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 65}}
7. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 65}}

Rotating the device left

1. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {480, 0}}
2. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {480, 0}}
3. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {480, 12}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {480, 12}}

Rotating the device right

1. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 172}}
2. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 172}}
3. _resizeWithOldSuperviewSize calls: setFrame: - {{0, 0}, {320, 160}}
4. _adjustTableHeaderAndFooterViews calls: setFrame: - {{0, 0}, {320, 160}}

Which explains why my view looks truncated initially, then almost disappears and finally ends up overlapping the cells. It appears that _resizeWithOldSuperviewSize is the culprit and what I don't understand is why it is being called and where it is getting these odd values from.

I have a really rubbish work around by calling [self.tableView.tableHeaderView sizeToFit] in viewDidAppear: and didRotateFromInterfaceOrientation: which puts the frame back to the correct size but the redrawing is awful as both happen after the view is visible or after the rotation animation. Trying to set this anytime before the view is visible causes _resizeWithOldSuperViewSize to set the frame back to these odd sizes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风情万种。 2025-01-11 14:20:31

您需要获得正确的内在大小和 autoresizingMask 。一旦你这样做了,UITableView 将停止与你的 tableHeaderView 发生冲突。

例如,如果您希望标头具有取决于其内容的固定高度,但希望标头使用整个表格宽度,则可以执行以下操作:

1. 使用以下自动调整大小掩码配置创建视图 (因此表格不会尝试增加标题视图高度):

在此处输入图像描述

2. 使用 AutoLayout 添加子视图,使顶部/底部锚点与您的视图匹配(这样子视图就可以定义标题视图的高度)

3. 添加标题视图,如下所示:

let headerView : CustomView? = CustomView.fromNib()
headerView?.sizeToFit()

tableView.tableHeaderView = headerView

You need to get the intrinsic size and autoresizingMask right. Once you do that, UITableView will stop screwing with your tableHeaderView.

For example, if you want your header to have a fixed height which depends on its contents, but you want your header to use the entire table width, this is what you would do:

1.Create your view with the following Autoresizing mask configuration (so the table won't try to increase the header view height):

enter image description here

2. Add your subviews using AutoLayout so the top/bottom anchors match your view (this is so your subviews define the height of your header view)

3. Add your header view like so:

let headerView : CustomView? = CustomView.fromNib()
headerView?.sizeToFit()

tableView.tableHeaderView = headerView
憧憬巴黎街头的黎明 2025-01-11 14:20:31

它将帮助您阅读 通过 UIViewautoresizingMask 属性了解 Apple 的视图调整大小方案。可能的值是:

enum {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;

我毫不怀疑,经过一些实验,您会找到正确的调整大小蒙版组合来解决您的问题。

另外,请注意 sizeToFit,根据相同的文档源“调整大小并移动接收器视图,使其仅包含其子视图”。在创建视图之后并将其放入表头之前调用它似乎不合适。

It will help you to read up on Apple's view resizing scheme through the autoresizingMask property of UIView. Possible values are:

enum {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;

I have no doubt that after some experimentation you will find the right resizing mask combination to solve your problem.

Also, please note that sizeToFit, according to the same documentation source "resizes and moves the receiver view so it just encloses its subviews." It seems inappropriate to call that just after creating the view and before putting it into the table header.

┾廆蒐ゝ 2025-01-11 14:20:31

当我想要带有 SearchBar 的表头视图和底部的一些自定义 UI 时,遇到了完全相同的问题。有趣的是,如果你只保留 SearchBar,它就会完美地工作。

所以我决定应用一个非常肮脏的黑客,将自定义 UIView 的重写框架设置器中的框架高度(您正在记录框架大小)重置为您需要的东西(在您的情况下为 120)。

- (void) setFrame:(CGRect)frame {
    frame.Height = 120;
    [super setFrame:frame];
}

之后,旋转时就不会出现奇怪的标题视图和表格重叠的情况。希望有帮助。

PS 顺便说一句,我在自定义 UIView 中使用自动布局。

Got totally the same problem when I wanted to have table header view with SearchBar and some custom UI at the bottom. The funny thing that if you keep only SearchBar it works just perfect.

So I decided to apply a really dirty hack, reseting Frame's Height in the overridden Frame setter of your custom UIView (there you're logging frame size) to something you need (in your case it's 120).

- (void) setFrame:(CGRect)frame {
    frame.Height = 120;
    [super setFrame:frame];
}

After that there is no weird header view and table overlapping on rotation. Hope it helps.

P.S. BTW I use Auto Layout inside my custom UIView.

夕嗳→ 2025-01-11 14:20:31

创建一个新的 xib 文件,然后在 xib 文件中自定义您的首选大小。假设 xib 名为 customHeader (.xib) 声明:

  IBOutlet UIView *customView;

将 customView 分配给 xib 中的该视图。

  -(UIView *)viewOfCategory;

在 .m 中:

   -(UIView *)viewOfCategory {

if (!customView) {

        [[NSBundle mainBundle] loadNibNamed:@"customHeader" owner:self options:nil];
}

return customView;
   }

然后调用这个 UITableView 方法:

  -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:        (NSInteger)section {

return [self customView];

}

然后最后也是最重要的将回答您的问题!实现另一个 UITableView 方法:

   -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

// You can just return default size of your xib: return [[self viewOfCategory]          bounds].size.height;


       // Or you can return custom size using  CGRect or whatever. 
     }

Create a new xib file and then customize your preferred size in the xib file. Say the xib is called customHeader (.xib) Declare:

  IBOutlet UIView *customView;

Assign customView to that view in your xib.

  -(UIView *)viewOfCategory;

In .m:

   -(UIView *)viewOfCategory {

if (!customView) {

        [[NSBundle mainBundle] loadNibNamed:@"customHeader" owner:self options:nil];
}

return customView;
   }

Then call this UITableView method:

  -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:        (NSInteger)section {

return [self customView];

}

THEN FINALLY AND MOST IMPORTANT THAT WILL ANSWER YOUR QUESTION! Implement this other UITableView method:

   -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

// You can just return default size of your xib: return [[self viewOfCategory]          bounds].size.height;


       // Or you can return custom size using  CGRect or whatever. 
     }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文