旋转的 UITableView 中的表格视图单元格未对齐

发布于 2025-01-05 01:47:49 字数 2125 浏览 3 评论 0原文

作为一个小背景,我构建了一个旋转的 UITableView 作为一种侧向“选择器”视图。为此,我采用 UITableView,对其应用旋转变换,然后再次旋转 tableview 内的 UITableViewCells。

我遇到的问题是某些表格单元格变得“未对齐” - 它们的框架是在与其他表格单元格一定距离的偏移(在 x 和 y 维度上)绘制的。

我已经缩小范围,在进行 [tableView reloadData] 调用后,此错误发生在完全超出可见 tableview 矩形的第一个表格单元格上。 (即,如果我有 4 个表格单元格,A 完全可见并绘制,B 半开/半离视图,C 和 D 完全离开屏幕且尚未渲染,当我滚动到 C 时,它是被窃听了,但是当我滚动到 D 时,却没有)。

现在来看一些代码 -

包含视图的 init

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        ...
        self.tableView = [[UITableView alloc] init];
        [self addSubview:_tableView];
        [_tableView setDelegate:self];
        [_tableView setShowsVerticalScrollIndicator:NO];
        [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
        CGAffineTransform transform = CGAffineTransformMakeRotation(-1.5707963);    
        _tableView.transform = transform;
        _tableView.frame = self.bounds;
        ...
    }
    return self;
}

相关委托方法

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    return [tableView.dataSource tableView:tableView cellForRowAtIndexPath:indexPath].frame.size.height;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    CGAffineTransform transform = CGAffineTransformMakeRotation(1.5707963);
    cell.transform = transform;
}

表格单元格的layoutSubviews
编辑:我根据单元格内容的长度手动设置单元格的大小(主要是宽度)

- (void)layoutSubviews {
    [super layoutSubviews];

    // some calculations and sizing of subviews

    // height and width are swapped here, because the table cell will be rotated.
    self.frame = (CGRect){self.frame.origin.x,self.frame.origin.y,calculatedHeight,calculatedWidth};
}

似乎有缺陷的表格单元格的frame.origin是当到达布局子视图时设置不正确。将框架的 origin.x 值设置为 0 可以修复 x 维度偏移问题,但显然我无法对 y 维度执行相同的操作,因为该值决定单元格在表格视图中的位置。

如果我可能遗漏了一些重要信息,请告诉我。谢谢!

As a little background, im building a rotated UITableView as a sort of sideways "picker" view. To do this, im taking a UITableView, appling a rotation transform to it, and then rotating again the UITableViewCells inside the tableview.

The problem im having is that some of the table cells become "misaligned" - their frame gets drawn at a certain distant offset (in both the x and y dimension) from the other table cells.

I've narrowed down that this bug occurs on the first table cell completely out of the visible tableview rect after a [tableView reloadData] call is made. (i.e. if I have 4 table cells, A which is completely visible and drawn, B which is half on/half off the view, and C and D which are completely off the screen and not yet rendered, when i scroll to C it is bugged, but when i scroll to D, it is not).

Now for some code -

the containing view's init

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        ...
        self.tableView = [[UITableView alloc] init];
        [self addSubview:_tableView];
        [_tableView setDelegate:self];
        [_tableView setShowsVerticalScrollIndicator:NO];
        [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
        CGAffineTransform transform = CGAffineTransformMakeRotation(-1.5707963);    
        _tableView.transform = transform;
        _tableView.frame = self.bounds;
        ...
    }
    return self;
}

the relevant delegate methods

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    return [tableView.dataSource tableView:tableView cellForRowAtIndexPath:indexPath].frame.size.height;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    CGAffineTransform transform = CGAffineTransformMakeRotation(1.5707963);
    cell.transform = transform;
}

the table cell's layoutSubviews
edit: I manually set the size of the cell (mainly the width) based on the length on the content of the cell

- (void)layoutSubviews {
    [super layoutSubviews];

    // some calculations and sizing of subviews

    // height and width are swapped here, because the table cell will be rotated.
    self.frame = (CGRect){self.frame.origin.x,self.frame.origin.y,calculatedHeight,calculatedWidth};
}

It would seem that the bugged tablecell's frame.origin is set incorrectly when it reaches layout subviews. Setting the frame's origin.x value to 0 fixes the x dimension offset problem, but obviously I can't do the same for the y dimension because this value determines the cell's position in the tableview.

Please let me know if there's some crucial info I might be leaving out. Thanks!

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

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

发布评论

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

评论(3

海螺姑娘 2025-01-12 01:47:49

您是否尝试过设置单元格图层的锚点,即图层旋转(变换)的点。它默认为 .5, .5,这是图层的中心,可能需要设置为 0, 0 (或 1, 1 - 我不记得图层坐标是否从我的头顶反转)

或者尝试在应用变换后立即在 willDisplayCell 中设置框架,而不是在布局子视图中进行设置

Have you tried to set the anchor point of the cells layer, which is the point the layer is rotated (transformed) about. It defaults to .5, .5 which is the centre of the layer, it may need to be set to 0, 0 (or 1, 1 - i can't remember if the layer coordinates are inverted off the top of my head)

or try setting the frame in willDisplayCell immediately after applying the transform instead of doing it in layout subviews

夏末染殇 2025-01-12 01:47:49

好消息 - 在花了很多个小时试图解决这个问题之后,我偶然发现了解决方案。

这段代码被“窃听”单元多次调用,显然由于 CALayer 和 CGAffineTranform 的一些复杂性,分配转换会产生附加影响。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    CGAffineTransform transform = CGAffineTransformMakeRotation(1.5707963);
    cell.transform = transform;
}

解决方案是将转换移至单元格的 init 方法中,以便保证每个单元格仅设置一次。

// ... init stuff  
self.transform = CGAffineTranformMakeRotation(1.5707963);
// ... more init stuff

Good news - after spending many many previous hours trying to figure this out, I just stumbled upon the solution.

This code was getting called multiple times for the 'bugged' cell, and apparently due to some intricacies of CALayer and CGAffineTranform's, assigning the tranform had an additive affect.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    CGAffineTransform transform = CGAffineTransformMakeRotation(1.5707963);
    cell.transform = transform;
}

The solution was to move the transform into the cell's init method, so that it is guaranteed to be set only once per cell.

// ... init stuff  
self.transform = CGAffineTranformMakeRotation(1.5707963);
// ... more init stuff
我三岁 2025-01-12 01:47:49

创建 UITableViewCell 的子类并覆盖其layoutSubviews,确保在那里设置转换:

class InvertedTableViewCell: UITableViewCell {
    override func layoutSubviews() {
            self.transform = CGAffineTranformMakeRotation(1.5707963)
        }
}

Make a subclass of UITableViewCell and it its layoutSubviews override make sure to set the transform there:

class InvertedTableViewCell: UITableViewCell {
    override func layoutSubviews() {
            self.transform = CGAffineTranformMakeRotation(1.5707963)
        }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文