当前位置: 首页 > 知识库问答 >
问题:

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

暴向笛
2023-03-14

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

  • UIScrollView
    • UIView
      • UIButton

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

      H:|[object]|
      V:|[object]|
      

      我还为每个对象将translatesautorexingmaskintoconstraints设置为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计算不正确。这里有更多。但如何正确地做到这一点呢?

共有1个答案

夏侯自珍
2023-03-14

两个观察结果:

>

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

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

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

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

    - (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而扭曲了自动布局。我不知道如果你有“屏幕大小”的内容,为什么要有滚动视图(除非你是通过按钮分页)。我不知道你为什么要有一个包含单个项目的内容视图。我不明白你为什么要使用全屏按钮(那时我会在根视图上放一个点击手势,然后收工)。

    我假设你对所有这些都有很好的理由,但是备份一下,问问你想要的用户体验是什么,然后重新处理这个问题,看看是否有更有效的方法来达到预期的效果,这可能是有意义的。

  •  类似资料:
    • 许多有关自动布局约束动画的教程建议更新约束的常量属性,然后在动画块中调用。 我的处境有点棘手。我有一个包含3个子视图的视图。此超级视图的高度不是固定的-它是按其子视图的高度之和计算的。在某些情况下,我要求这3个子视图中的一个子视图切换其高度(它在0和30之间变化,即我希望平滑地隐藏和显示它)。代码类似于此: 不幸的是,这并不像我预期的那样有效。我可以看到子视图高度的平滑变化,但在为子视图高度约束设

    • 问题内容: 在将视图添加到我的应用程序之前,我创建了一个小演示场来使其工作。 我有一个滚动视图,该视图将包含许多按钮来水平滚动。我知道这些按钮需要进入滚动视图内的容器视图,并且也已经创建了。我最初使用自动布局约束创建所有这些内容,但是现在尝试使用常量来确保内容视图大于滚动视图。但是,按钮仍然不会滚动…我错过了什么吗?滚动视图不适用于自动布局吗? 我也在iPad上以编程方式进行了所有这些操作,因此不

    • 我花了两天时间尝试了混合和纯自动布局方法的各种解决方案,以实现在自动布局之前简单的滚动视图设置,现在它是正式的了——我一定太傻了。我主要是在故事板中设置这个(嗯,就是这样)。 所以我请求帮助。 视图树: 按钮应该水平滚动(从左到右,反之亦然)。有人能告诉我如何设置约束来使用纯自动布局实现这一点吗??? -- 我尝试了混合方法,如下所示: ...以及根据Apple的TechNote为< code>c

    • 我遇到了内容视图高度限制的问题。所有标签都有动态高度,即没有固定高度。我在某个地方读到将高度设置为等于滚动视图高度。 ViewController的高度目前是870px,scrollview的高度是757px。我不知道如何在AutoLayout中设置高度,因为我无法在某一点后滚动。 我首先设置了UIScrollView,然后添加UIView作为UIScroll View的子级,然后添加了2个UII

    • 我必须在屏幕上显示一个带有多个“开关”控件iPhone弹出窗口。并分别通过打开/关闭操作在弹出窗口上添加和删除子视图。有关情况的更好说明,请参见下面 就像上面一样,当“添加邮件”开关为“ON”时,弹出视图必须再次增加高度,再添加两个子视图。最后看起来像这样, 就是这样。我正在通过我的应用程序使用自动布局,这是我感到困惑的地方。我知道我可以删除弹出窗口,每次都可以再删除一个新的弹出窗口,但这似乎是新

    • 我遇到了自动布局的问题,似乎无法找到应该很容易实现的答案。 我有以下视图层次结构: 标签上的前导/尾随限制使它们在更薄的设备上更高(iPhone 4s vs iPhone 6)。 为了让UIScrollview正常工作,我需要在UIScrollView内部设置UIView的高度约束,以避免出现“不明确的高度”警告。 但在iPhone 4s上运行时,UIView不够高,无法容纳它的子视图。 到目前为