【问题标题】:How can I fix or workaround this tableView textField autolayout glitch?如何修复或解决此 tableView textField 自动布局故障?
【发布时间】:2016-12-08 01:32:37
【问题描述】:

我认为根本原因是estimatedRowHeight 被用来对底层UIScrollView.contentOffset 做出假设,但这在定义上总是错误的,因为它是一个估计值。实际行高完全不同,具体取决于单元格内容和设备方向。

即使我实施estimatedHeightForRowAtIndexPath 以提供更精确的估计,故障仍然存在。

因此,当您从顶部开始并向下滚动时,一切都很好,因为 TableView 在保持 contentOffset 与单元格位置同步时会学习实际的单元格高度。但是,一旦您旋转所有真实的单元格高度,UITableView 现在就会不同步,它不知道滚动到哪里。

但也有更奇怪的事情发生,有时UITextField 单元格最终会位于另一个单元格的顶部,并一直卡在那里......

不管怎样,我已经把它归结为一个简单的例子。

https://github.com/trapper-/autolayout-glitch

  • 使用 iPhone 进行测试,如果使用模拟器,则启用软件键盘。
  • 您会在滚动、选择字段和旋转时看到许多视觉故障。
  • 举一个简单的可重复示例。
  • 向下滚动到底部。
  • 选择最后一对UITextField's 之一,以便UITableView 需要滚动以确保该字段可见。
  • 旋转设备。

【问题讨论】:

  • 虽然不理想,但对 tableView 实例的 reloadData 调用应该会有所帮助。你试过了吗?
  • 自动布局不适用于 UITableView。考虑使用 CollectionView。这是一篇关于 UITableView 限制的好帖子:pspdfkit.com/blog/2017/the-case-for-deprecating-uitableview
  • 您是说UICollectionView 没有这些相同类型的故障吗?如果是这样,那将是一个很好的解决方案。

标签: ios objective-c uitableview autolayout


【解决方案1】:

我玩弄了您的代码几分钟,因为我遇到了类似的问题。我希望我能提供帮助,但我没有完全解决。

我可以提供的是我确实取得了一些的进步。

当设备旋转时,您应该实现 UIViewcontroller 方法,告诉您它会发生,并且确实发生了。当它发生时,缓存可见行。然后在它完成之后,重新加载表格并滚动到那些可见的行。

看起来像这样:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    // Save the visible row position
    self.visibleRows = [self.tableView indexPathsForVisibleRows];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    [self.tableView reloadData];
    // Scroll to the saved position prior to screen rotate
    [self.tableView scrollToRowAtIndexPath:[self.visibleRows objectAtIndex:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}

visibleRows 是 ViewController 上的一个数组 @property。

这使它进入了正确的位置(我怀疑如果您实际上存储了用户正在操作的单个单元格,这将使您每次都 100% 到达正确的单元格。

这没有做的是,仍然有跳舞的 UITextFields 布局不正确(有时)与几个设备旋转。

同样,不是解决方案 - 但我想分享我所看到的,希望这可以帮助您找到解决方案。

祝你好运!

【讨论】:

  • 关于可见行跟踪不是一个坏主意,但我也有很多关于 scrollToRowAtIndexPath 方法的问题。它不知道滚动到哪里。即没有正确地将 indexPath 转换为正确的 contentOffset。
  • 是的,我怀疑这与细胞一开始就松松垮垮地布局有关。
【解决方案2】:

我很确定您的问题与线路有关:

self.tableView.estimatedRowHeight = 44;

这会导致 tableview 围绕这个估计的高度进行一些优化。我不太明白为什么在选择文本字段时会中断,但这就是我设法缩小范围的原因。如果您确实明确计算了每一行的高度,问题似乎就消失了(请注意,这只是一个粗略的示例,您需要在实际实现中多加考虑):

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row % 2) {

        return 44.f;

    } else {

        NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

        CGRect frame = [text boundingRectWithSize:CGSizeMake(350.f, CGFLOAT_MAX)
                                          options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:14.f] }
                                          context:nil];

        return frame.size.height;
    }
}

【讨论】:

    【解决方案3】:

    我看了一下那个项目。减轻某些问题的最佳建议是改进您的估计高度计算。如果文本视图单元格要大,那么估计的高度需要更接近单元格的平均高度,因此在旋转时,调整大小的可能性会较小。

    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath (NSIndexPath *)indexPath 
    {
        if (indexPath.row % 2) {
            return 44.0f;
        } else {
            return 175.0f;
        }
    }
    

    现在关于 UITextField 的奇怪问题,我认为您可能需要考虑这些单元格即使在旋转时也会被重用,所以如果即使单元格已被重用,UITextField 仍然是第一响应者,那么这就是键盘无法跟踪文本字段。

    您可以通过在单元格上设置标签来查看此结果,并观察它如何随机更改旋转顺序,如下所示:

    NSString* cellID = @"TextFieldCell";
    TextFieldCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
    NSLog(@"cell %@, changing to %@", @(cell.tag), @(indexPath.row));
    cell.tag = indexPath.row;
    return cell;
    

    我的建议是 1) 不要在表格视图单元格中使用文本字段,或者 2) 想出一种新方法让用户在滚动项上输入文本。例如,将文本字段副本放在表格视图顶部的视图中,并在输入文本时手动管理它,然后在文本完成后将文本复制回单元格。 3) 选项 3 是尝试查看键盘管理器库是否有帮助。我真的很喜欢使用IQKeyboardManager。解决键盘管理问题真的很方便。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-29
      • 2020-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多