iOS自动布局约束的UIScrollView:子视图的大小错误

iOS自动布局约束的UIScrollView:子视图的大小错误,ios,uiscrollview,autolayout,nslayoutconstraint,Ios,Uiscrollview,Autolayout,Nslayoutconstraint,我试图在代码中生成一个视图。这是我的视图对象的层次结构 UIScrollView UIView UIButton 滚动视图的大小应与窗口的大小相同。 按钮应该尽可能大。 我使用的是iOS自动布局,所以我所有对象的约束字符串如下所示 H:|[object]| V:|[object]| 我还为每个对象设置了translatesAutoResizengMaskintoConstraints为NO 问题是按钮只获得默认的按钮大小。其父视图对象(UIView)仅获取其子视图所需的大小 红色

我试图在代码中生成一个视图。这是我的视图对象的层次结构

  • UIScrollView
    • UIView
      • UIButton
滚动视图的大小应与窗口的大小相同。 按钮应该尽可能大。 我使用的是iOS自动布局,所以我所有对象的约束字符串如下所示

H:|[object]|
V:|[object]|
我还为每个对象设置了
translatesAutoResizengMaskintoConstraints
NO

问题是按钮只获得默认的按钮大小。其父视图对象(UIView)仅获取其子视图所需的大小

红色:UIScrollView/黄色:UIView

如何强制这些视图与scrollView一样大

当我使用UIView而不是UIScrollView时,一切都很好

下面是一些代码:

    - (void) viewDidLoad {

        [super viewDidLoad];

        // SCROLL VIEW
        UIScrollView* scrollView = [UIScrollView new];
        scrollView.backgroundColor=[UIColor redColor];
        scrollView.translatesAutoresizingMaskIntoConstraints = NO;

        //CONTAINER VIEW
        UIView *containerView = [UIView new];
        containerView.translatesAutoresizingMaskIntoConstraints = NO;
        containerView.backgroundColor = [UIColor yellowColor];
        [scrollView addSubview:containerView];

        // CONSTRAINTS SCROLL VIEW - CONTAINER VIEW
        [scrollView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[containerView]|"
                                                 options:0 metrics:nil
                                                   views:@{@"containerView":containerView}]];
        [scrollView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[containerView]|"
                                                 options:0 metrics:nil
                                                   views:@{@"containerView":containerView}]];

        // BUTTON
        UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        button.translatesAutoresizingMaskIntoConstraints = NO;
        [button setTitle:@"I'm way to small" forState:UIControlStateNormal];
        [containerView addSubview:button];

        // CONSTRAINTS CONTAINER VIEW - BUTTON
        [containerView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|"
                                                 options:0 metrics:nil
                                                   views:@{@"button":button}]];
        [containerView addConstraints:
         [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[button]|"
                                                 options:0 metrics:nil
                                                   views:@{@"button":button}]];
        self.view = scrollView;

    }
更新:
我真的不知道,为什么会这样。如果在IB中设置视图,连接插座并在代码中实例化视图,则scrollview的行为类似于普通视图(垂直反弹)。其contentSize计算不正确。更多但是如何正确地做呢?

有几个观察结果:

  • 滚动视图中的子视图约束与其他视图中的约束不同。它们用于设置滚动视图的
    contentSize
    。(请参阅。)这样,您可以在滚动视图上抛出一堆内容,为其中的内容设置约束,然后计算
    contentSize
    。这是一个非常酷的特性,但它与您在这里尝试做的相反

  • 更糟糕的是,除非为按钮的宽度和高度设置明确的约束,否则按钮将根据其内容调整大小

  • 这两个观察结果的最终效果是,您现有的约束条件是“(a)将我的容器设置为我的按钮的大小;(b)让我的按钮根据文本的大小动态调整自身大小;(c)根据我的容器的大小(即按钮的大小)设置我的scrollview的
    contentSize
    。”

    我不清楚商业问题是什么。但以下是实现我认为您的技术问题的一些限制条件:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        UIView *view = self.view;
    
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.backgroundColor = [UIColor redColor]; // just so I can see it
        scrollView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:scrollView];
    
        UIView *containerView = [[UIView alloc] init];
        containerView.backgroundColor = [UIColor yellowColor]; // just so I can see it
        containerView.translatesAutoresizingMaskIntoConstraints = NO;
        [scrollView addSubview:containerView];
    
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        button.translatesAutoresizingMaskIntoConstraints = NO;
        [button setTitle:@"I'm the right size" forState:UIControlStateNormal];
        [containerView addSubview:button];
    
        NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, button, view, containerView);
    
        // set the scrollview to be the size of the root view
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:views]];
    
        [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:views]];
    
        // set the container to the size of the main view, and simultaneously
        // set the scrollview's contentSize to match the size of the container
    
        [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[containerView(==view)]|"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:views]];
    
        [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[containerView(==view)]|"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:views]];
    
        // set the button size to be the size of the container view
    
        [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button(==containerView)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:views]];
    
        [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[button(==containerView)]"
                                                                              options:0
                                                                              metrics:nil
                                                                                views:views]];
    
    }
    

    坦白地说,我不理解你的UI的商业意图,因为这感觉像是为了实现一个非常简单的UI而对自动布局的扭曲。如果你有“屏幕大小”的内容,我不知道为什么你有一个滚动视图(除非你是通过按钮分页)。我不知道为什么你会有一个只有一个项目的内容视图。我不明白为什么要使用全屏按钮(我只是在根视图上点击了一下,然后就到此为止了)


    我假设您有充分的理由来解释所有这些,但是备份、询问您想要的用户体验是什么,然后重新处理这个问题,看看是否有更有效的方法来实现所需的效果。这是一个非常复杂的解决方案,只需显示一个全屏按钮。希望我能回答这个技术问题,但我仍然不清楚你为什么要这样做。请不要在帖子里写你的感谢——签名不属于这里。谢谢“我不理解你的UI的商业意图……”我正试图根据它的描述自动生成任何UI。示例中的按钮可以是任意一组子视图及其子视图。在某些情况下,描述中说,子视图必须与超级视图一样宽(没有解释宽度)@罗布,非常感谢你!!!!!!在我的示例中,内容大小的高度已经正确计算,所以垂直滚动是可行的。我正在搜索这样的contentSize:
    scrollView.contentSize=CGSizeMake(scrollView.frame.size.width,?)
    。要做到这一点,请从@Rob的示例中删除所有垂直约束:滚动仍在工作,并且所有子视图的宽度都可以与滚动视图的宽度相同,而无需为其指定明确的宽度。