【问题标题】:scrollView: how to create a pure auto layout scrollview with paging?scrollView:如何创建带有分页的纯自动布局滚动视图?
【发布时间】:2015-06-30 12:29:13
【问题描述】:

谁能告诉我我在这里做错了什么... - 将 UIScrollView 固定到其容器视图 - 将所有子视图固定到 UIScrollView

在阅读了有关它的 Apple TechNote 之后,我尝试了混合方法和纯自动布局方法。使用 NIB 的混合方法在分页时效果不佳,它看起来像滚动视图中的大图,而不是分页。

然后我在代码中创建了纯自动布局版本,UIScrollView 作为 UIView 的子视图。这次视图卡住了,并且 UIImage 是巨大的,就像它的全尺寸一样:

    //scroll view
    if (self.scrollView == nil)
    {
        self.scrollView = [[UIScrollView alloc] initWithFrame:self.frame];

        self.scrollView.translatesAutoresizingMaskIntoConstraints  = NO;

        [self.scrollView setClipsToBounds:NO];
        [self.scrollView setPagingEnabled:YES];

        [self addSubview: self.scrollView];
        [self addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView(300)]|"
                                                 options:0 metrics:nil
                                                   views:@{@"scrollView":self.scrollView}]];
        [self addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView(300)]|"
                                                 options:0 metrics:nil
                                                   views:@{@"scrollView":self.scrollView}]];

-(void) createContentView
{
    
    for (int i=0; i<self.pageImages.count; i++) {
        
        UILabel* topLabel = [[UILabel alloc] init];
        topLabel.text = [NSString stringWithFormat:@"topLabel %d", i+1];
        [topLabel sizeToFit];
        
        [self.topLabelArray insertObject:topLabel atIndex:i];
        [self.scrollView addSubview:topLabel];
        topLabel.translatesAutoresizingMaskIntoConstraints = NO;
        

        UILabel* bottomLabel = [[UILabel alloc] init];
        bottomLabel.text = [NSString stringWithFormat:@"bottomLabel %d", i+1];
        [bottomLabel sizeToFit];

        [self.bottomLabelArray insertObject:bottomLabel atIndex:i];
        [self.scrollView addSubview:bottomLabel];
        bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;

        UIButton* button = [[UIButton alloc] init];
        button.titleLabel.text = [NSString stringWithFormat:@"button %d", i+1];
        [button sizeToFit];

        [self.buttonArray insertObject:button atIndex:i];
        [self.scrollView addSubview:button];
        button.translatesAutoresizingMaskIntoConstraints = NO;
        
        UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.pageImages objectAtIndex:i]]];
        
        imageView.frame = CGRectMake(0,0,200,200);
        
        imageView.translatesAutoresizingMaskIntoConstraints = NO;
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        
            [self.pageViews insertObject:imageView atIndex:i];
        
        [self.scrollView addSubview:imageView];

        NSDictionary* viewsDictionary = @{@"topLabel":topLabel,
                                          @"bottomLabel":bottomLabel,
                                          @"button": button,
                                          @"imageView": imageView
                                          };

        [self.scrollView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(10)-[topLabel]-(10)-[imageView]-(10)-[bottomLabel]-(10)-|"
                                                 options:0 metrics:nil
                                                   views:viewsDictionary]];
        [self.scrollView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-(10)-|"
                                                 options:0 metrics:nil
                                                   views:viewsDictionary]];
        
        if (i==0)
        {
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[topLabel]"
                                                 options:0 metrics:nil
                                                       views:viewsDictionary]];
            
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[imageView]"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
              [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(10)-[bottomLabel]-(10)-[button]"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
        }
        else if (i == self.pageImages.count)
        {
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[topLabel]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[imageView]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];

            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[bottomLabel]-(10)-[button]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
        
        }
        else
        {
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:[prevTopLabel]-(10)-[topLabel]"
                                                     options:0 metrics:nil
                                                       views:@{@"prevTopLabel": [self.topLabelArray objectAtIndex: i-1],
                                                                @"topLabel": topLabel
                                                                   }]];
            
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:[prevImageView]-(10)-[imageView]"
                                                     options:0 metrics:nil
                                                       views:@{@"prevImageView": [self.pageViews objectAtIndex: i-1],
                                                               @"imageView": imageView
                                                               }]];
            
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:[prevButton]-(10)-[bottomLabel]-(10)-[button]"
                                                     options:0 metrics:nil
                                                       views:@{@"prevButton": [self.buttonArray objectAtIndex: i-1],
                                                               @"button":button,
                                                               @"bottomLabel": bottomLabel
                                                               }]];
        }
        [self.scrollView addConstraint:[NSLayoutConstraint
                                  constraintWithItem:topLabel
                                  attribute:NSLayoutAttributeCenterX
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:imageView
                                  attribute:NSLayoutAttributeCenterX
                                  multiplier:1
                                  constant:0.0]];
        
        [self.scrollView addConstraint:[NSLayoutConstraint
                             constraintWithItem:bottomLabel
                             attribute:NSLayoutAttributeCenterX
                             relatedBy:NSLayoutRelationEqual
                             toItem:imageView
                             attribute:NSLayoutAttributeCenterX
                             multiplier:0.8
                             constant:0.0]];
 
 //        [self.scrollView addConstraint:[NSLayoutConstraint
//          

【问题讨论】:

    标签: ios uiscrollview


    【解决方案1】:

    好的,这里有一些问题:

    else if (i == self.pageImages.count)

    这个子句永远不会运行,因为你的循环计数设置为在i == self.pageImages.count -1 时中断,这里是for (int i=0; i&lt;self.pageImages.count; i++)

    下一个

            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[topLabel]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[imageView]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
    
            [self.scrollView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:-(10)-[bottomLabel]-(10)-[button]-(10)-|"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
    

    这些也会产生无效的约束,特别是@"H:-(10)-[bottomLabel].... 没有将最左边的约束固定到任何东西上。所有连接视图的视觉格式字符串都需要以视图开始或结束。子视图 ([subview]) 或超级视图 (|)。要解决此问题,您需要在循环中保留对先前页面标签的引用,并将其添加到 VFL 字符串的开头。像这样的

       @"H:[prevBottomLabel]-(10)-[bottomLabel]....
    
       prevBottomLabel = bottomLabel;
       // Continue loop
    

    下一步:

       UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.pageImages objectAtIndex:i]]];
    
        imageView.frame = CGRectMake(0,0,200,200);
    
        imageView.translatesAutoresizingMaskIntoConstraints = NO;
        imageView.contentMode = UIViewContentModeScaleAspectFit;
    

    这不会产生预期的效果,因为您无法手动设置框架,然后打开自动布局。目前,框架值被忽略,高度和宽度由图像视图的内在内容大小设置,这将是图像的高度和宽度。如果你想设置高度和宽度,你需要用约束来做,如下:

       [imageView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"H:[imageView(200)]"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
    
       [imageView addConstraints:
             [NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageView(200)]"
                                                     options:0 metrics:nil
                                                       views:viewsDictionary]];
    

    这应该给你一些指导,那里可能还有其他错误,但修复这些是一个很好的起点。

    【讨论】:

    • 感谢您的解释...现在可以使用了。我正在尝试不同的方法来使其工作,代码有点混乱(而且是错误的)。我认为我遇到的最大问题是 VFL 没有以 UIView 结尾。我会注意的。另一个是图像视图大小。使用自动布局,看起来只能使用约束来设置大小。也注意到了。是否还使用约束而不是框架设置滚动大小(即此处的分页大小)?过去设置滚动视图框架对我有用。
    • 如果您能帮我确认一下,我还有一个问题:通过分页,滚动视图是否预期每个页面都包含在单个 UIView 中?我知道在语义上它看起来更干净,而且它可能也是一种首选方式。但是绝对有必要在滚动视图中添加五个 UIView,每个都包含 UIImageView、标签和按钮,作为子视图,并以这种方式进行页面吗?
    • 对于您的第一条评论,我相信分页大小是由滚动视图框架的宽度定义的,因此它会捕捉到宽度的倍数。滚动大小被定义为很大,因为它需要满足其内容的约束。您可以将其视为滚动视图内容推出以扩展可滚动区域。这就是为什么你必须在一条完整的线上从一个边到另一个边运行约束才能使其正常工作。
    • 对于您的第二条评论,答案是否定的,您不需要每个页面都拥有自己的 UIView,如上所述,分页只会导致滚动捕捉到多个滚动视图框架宽度
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多