使用自动布局在自定义 UITableViewCell 上分页 UIScrollView

Posted

技术标签:

【中文标题】使用自动布局在自定义 UITableViewCell 上分页 UIScrollView【英文标题】:Paging UIScrollView on custom UITableViewCell with Autolayout 【发布时间】:2014-12-29 22:00:26 【问题描述】:

我正在尝试使用自动布局在我的自定义UITableViewCell 中使用水平分页UIScrollView。我已经成功地将UIScrollView 添加到具有所有适当约束的单元格中。

当我尝试使用视图加载 UIScrollView 时,出现了我的问题。我正在覆盖自定义单元格的 layoutSubviews 方法并在那里加载 ScrollView 的视图,因为这是我能找到加载 Autolayout 约束的唯一方法。因此,为我提供了 ScrollView 大小的准确参考。

-(void)layoutSubviews 

    [super layoutSubviews];

    for(int i=0; i<self.scrollArray.count; i++) 
        CGRect frame;
        CGFloat width = self.theScrollView.frame.size.width;
        frame.origin.x = width * i;
        frame.origin.y = 0;
        frame.size = self.theScrollView.frame.size;

        UIView *subview = [[UIView alloc] initWithFrame:frame];
        [subview addSubview:[self.scrollArray objectAtIndex:i]];
        [self.theScrollView addSubview:subview];
    

    CGSize contentSize = CGSizeMake(self.theScrollView.frame.size.width * self.scrollArray.count, self.theScrollView.frame.size.height);
    self.theScrollView.contentSize = contentSize;
    self.theScrollView.contentOffset = CGPointMake(0, 0);
 

但是,layoutSubviews 在我的单元格上被多次调用,因此向我的UIScrollView 添加了不必要的子视图。有没有更好的方法来加载我不知道的子视图?或者有没有办法使用layoutSubviews,但要确保我的子视图只加载一次到UIScrollView

【问题讨论】:

一个简单的解决方案是存储一个布尔属性,您在第一次添加子视图时设置该属性。如果在后续调用布局子视图时此属性为 YES,则不要再次添加它们。或者将滚动视图添加到单元格并通过属性将其公开,然后在cellForRowAtIndexPath 中添加子视图 @Paulw11 - 感谢您的回复。据我所知,约束仅在对layoutSubviews 的最终调用中设置,这意味着我需要某种方法来检测最终调用,或者是否设置了约束。另外,我尝试在cellForRowAtIndexPath 中添加子视图,但那里也没有设置约束。 如果子视图已经存在,那么您仍然可以调用layoutIfNeeded 和/或调整子视图的大小,您只需要确保只添加一次 将子视图添加到滚动视图和设置它们的框架的逻辑分开。在 layoutsubviews 中,最好只设置框架逻辑。 【参考方案1】:

将您添加子视图的部分移动到滚动视图到您设置滚动数组并将子视图添加到子视图数组属性的位置。在 layoutsubviews 中,你应该只处理设置框架。

- (void)layoutSubviews

    [super layoutSubviews];

    //    self.theScrollView.frame = Make sure you set the scroll view frame;
    for(int i=0; i<self.scrollArray.count; i++) 
    
        UIView *aView = [self.scrollArray objectAtIndex:i];
        aView.frame = CGRectMake(self.theScrollView.frame.size.width * i, 0, self.theScrollView.frame.size.width, self.theScrollView.frame.size.height);
    

    self.theScrollView.contentSize = CGSizeMake(self.theScrollView.frame.size.width * self.scrollArray.count, self.theScrollView.frame.size.height);
    self.theScrollView.contentOffset = CGPointMake(0, 0);



- (void)partWhereYouSetScrollArray

    for(int i=0; i<self.scrollArray.count; i++)
    
        [self.theScrollView addSubview:[self.scrollArray objectAtIndex:i]];
    


- (void)prepareForReuse

   [super prepareForReuse];
   [[self.theScrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
   [self.scrollArray removeAllObjects];

【讨论】:

感谢您的回复。我认为这是在正确的轨道上。不幸的是,partWhereYouSetScrollArray 也会被多次调用。在具有可重用单元格的 tableView 中,每次在 scrollArray 中设置 cellForRowAtIndexPath 时都会调用该方法,给我们留下同样的问题。 我明白了。然后移除prepareForReuse中的所有子视图。 我添加了 prepareForReuse。 是的,我也试过了。它产生了一些意想不到的后果。正在删除其他单元格的子视图。 如果你告诉我你添加滚动视图和cel的子视图的部分,它会更有帮助。

以上是关于使用自动布局在自定义 UITableViewCell 上分页 UIScrollView的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 UITableViewCell 中忽略自动布局

在自定义 UIView 中为部分自动调整 UITableView

动画未在自定义布局中显示

在自定义 UITableViewCell 中调整 UITextView 的大小

找不到有关如何在自定义小部件中使用 ListView 的正确布局选项

在自定义布局管理器中使用SectionList组件