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

时间:2013-05-08 13:18:30

标签: ios uiscrollview autolayout nslayoutconstraint

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

  • 的UIScrollView
    • 的UIView
      • 的UIButton

ScrollView应与窗口大小相同。 按钮应尽可能大。 我使用iOS自动布局,因此所有对象的约束字符串都是这样的

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

我还为每个对象设置了translatesAutoresizingMaskIntoConstraintsNO

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

enter image description here

红色: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未正确计算。更多here。但是如何正确地做到这一点?

1 个答案:

答案 0 :(得分:24)

有几点意见:

  1. 滚动视图中子视图的约束不像其他视图中的约束。它们用于设置滚动视图的contentSize。 (参见TN2154。)这样,你在滚动视图上抛出一堆东西,设置其中的东西的约束,并为你计算contentSize。这是非常酷的功能,但它与你在这里尝试做的事情是对立的。

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

  3. 这两个观察的净效果是你现有的约束说“(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]];
    
    }
    

    坦率地说,我不了解你的用户界面的商业意图,因为这感觉就像一个自动布局的扭曲,以实现一个非常简单的用户界面。如果你有“屏幕大小”的内容,我不知道为什么你有滚动视图(除非你是通过按钮分页)。我不知道你为什么要有一个包含单个项目的内容视图。我不明白你为什么要使用全屏按钮(我只是在根视图上放了一个轻击手势并称之为一天)。

    我认为你有充分的理由解决所有这些问题,但是备份,询问你想要的用户体验是什么有意义,然后再解决问题,看看是否有更有效的方法来实现期望的效果。