使用自动布局,设置动态的UIView匹配容器视图 [英] Use autolayout to set dynamic UIView to match container view

查看:149
本文介绍了使用自动布局,设置动态的UIView匹配容器视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在IB一个UIView有内它的另一个UIView的,这我使用一个容器视图。在code,我创建三个不同的意见,然后根据不同的应用程序的状态,动画一个合适的放入容器中的观点。只有三个不同视图中的一个将在任何特定时间有效。问题是,当我在模拟器上不同的iPhone的运行,我的新子视图不调整来匹配容器视图。我使用的自动布局。出于测试目的,我已经建立了我的子视图只是一个大按钮具有约束到上海华所有它的边缘。和容器观点也有它的边缘约束到它的上海华。我想是的子视图以匹配容器的视图。即按钮拉伸容器视图的整体尺寸。当在不同的iPhone手机上运行的容器视图,因此子视图的大小应该按比例缩放相对于不同的iPhone的屏幕尺寸。

I have a UIView in IB that has another UIView within it, which I am using as a container view. In code, I create three different views and then animate the appropriate one into the container's view depending on the state of the app. Only one of the three different views will be valid at any given time. The problem is, when I run on different iPhone's in the simulator, my new subviews are not scaled to match the container view. I am using autolayout. For testing purposes, I've set up my subviews to just be a big button that has all it's edges constrained to the superview. And the container view also has it's edges constrained to it's superview. What I want is for the subview to match the container's view. i.e the button stretches the entire size of the container view. When run on different iPhones the size of the container view and therefore the subview should scale proportionally relative to the different iPhone's screen sizes.

下面是code我用我的初始化和子视图相对于容器视图中设置它的约束。

Below is the code I use to init my subview and set up it's constraints relative to the container view.

UIView *containerView = self.subView;
UIView *newSubview = [[mySubview alloc] init];
[newSubview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.containerView addSubview:newSubview];

[self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]];

[self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]];

[self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];

[self.containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]];  

我只是似乎无法得到这个工作。我是相当新的自动版式,我不知道我做错了,想停下敲打我的头靠在这堵墙。任何帮助将是了不起的。 :)

I just can't seem to get this to work. I'm fairly new to autolayout and am not sure what I am doing wrong and would like to stop banging my head against this wall. Any help would be terrific. :)

的**的 * 的** 其他信息 * 的**的 * **

***** ADDITIONAL INFO ******

对不起,我不会很清楚,因为我可以说有我的问题。因此,这里是用屏幕截图一些更多的信息。首先,我将介绍我做了什么code-明智的。

Sorry, I've not stated my problem as clearly as I could have. So here is some more info with screen shots. First, I'll describe what I've done code-wise.

在AppDelegate.m didFinishLaunchingWithOptions,我创造这样的MyViewController,

In didFinishLaunchingWithOptions in AppDelegate.m, I create MyViewController like this,

self.myViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];

在viewDidLoad中在MyViewController.m,我创建mySubview并将其添加到我的containerView创造约束它像这样,

In viewDidLoad in MyViewController.m, I create mySubview and add it to my containerView and create constraints for it like this,

UIView *containerView = self.containerView;
UIView *mySubview = [[MySubview alloc] init];
[mySubview setTranslatesAutoresizingMaskIntoConstraints:NO];
[containerView addSubview:mySubview];

NSDictionary *views = NSDictionaryOfVariableBindings(mySubview);
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[mySubview]|"
                                                                 options:0
                                                                 metrics:nil
                                                                   views:views]];
[containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mySubview]|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:views]];

最后在MySubview.h初始化我加笔尖为这样一个子视图,

And finally in init in MySubview.h I add the nib as a subview like this,

- (id)init
{
    if(self = [super init])
    {
        NSArray *nibArray = [[NSBundle mainBundle]loadNibNamed:@"MySubview" owner:self options:nil];
        [self addSubview:[nibArray objectAtIndex:0]];
    }
    return self;
}

几件事情要注意,可能会有帮助,

A couple of things to note that may help,

在MyViewController.xib,我有我使用的containerView一个UIView。它有一个IBOutlet到的UIView * containerView并且是所述一个以上引用。我在IB的containerView唯一的限制是,领导,拖尾和底部空间,上海华和顶部空间的SuperView = 44。

In MyViewController.xib, I have a UIView that I am using as the containerView. It has an IBOutlet to UIView* containerView and is the one referenced above. The only constraints I have for the containerView in IB are, leading, trailing and bottom space to Superview and top space to Superview = 44.

有关MySubview.xib,高度和宽度是300,(无约束用于高度或宽度)。我觉得这些大小,因为mySubview应该接受约束containerView不应该的问题。

For MySubview.xib, the height and width are 300, (no constraints are used for height or width). I feel like these sizes should not matter since mySubview is supposed to get constrained to containerView.

在MySubview.xib我有3个对象,topButton:高= 29,middleView:高= 242和bottomButton:高= 29(见附件图片)TopButton有领导,拖尾和顶部的SuperView约束和一个底部middleView约束。 MiddleView已经开头和结尾,以上海华约束和一个顶部topButton约束和底部bottomButton约束。最后bottomButton一直领先,尾随和底部的SuperView约束和一个顶部middleView约束。

In MySubview.xib I have 3 objects, topButton: height = 29, middleView: height = 242 and bottomButton: height = 29. (see attached image) TopButton has leading, trailing and top to Superview constraints and a bottom to middleView constraint. MiddleView has leading and trailing to Superview constraints and a top to topButton constraint and a bottom to bottomButton constraints. And finally bottomButton has leading, trailing and bottom to Superview constraints and a top to middleView constraint.

我希望发生的是mySubview扩展到适合containerView因为限制已经创建并添加,而是,mySubview变得非常大,剪辑containerView。

What I want to happen is for mySubview to scale to fit the containerView since constraints have been create and added but instead, mySubview gets very large and clips containerView.

下面是一些屏幕截图:

MyViewController.xib,标题下的蓝色长方形是我的容器视图,并有IBOutlet中containerView。

MyViewController.xib, the blue rectangle below the title is my container view and has the IBOutlet containerView.

MySubview.xib

MySubview.xib

最后,结果,这是不正确的。

And finally, the result, which are incorrect.

相反,我想这一点,这是我伪造的目的只是为了让屏幕截图。

Instead I would want this, which I have faked just to get the screen shot.

在iPhone 4,

在iPhone 5,

正如你在假屏幕截图看到,mySubview缩放以适应containerView,甚至containerView扩展位调整为不同的手机的屏幕尺寸。

As you can see in the fake screen shots, mySubview scales to fit the containerView, even as containerView scales a bit to adjust for the different phone screen sizes.

希望我没有与信息太过火。任何帮助将是了不起的。我觉得我很接近,但必须缺少一个关键的一步。 Grrrrr。

Hope I did not go overboard with the info. Any help would be terrific. I feel like I am close but must be missing one key step. Grrrrr.

推荐答案

一对夫妇的想法:


  1. 这基本上看起来不错,其他比一些变量名怪事:你的局部变量, containerView 等于 self.subView ,但所有其他行引用不同的变量,类属性, self.containerView 。你有没有忽略你设置了 containerView 类物业的线?但是,当我固定的,你的code为我工作得很好。

  1. This basically looks fine, other than some variable name weirdness: Your local variable, containerView is equal to self.subView, but all of your other lines refer to a different variable, a class property, self.containerView. Did you omit a line where you set that containerView class property? But when I fixed that, your code worked fine for me.

请确保你不是想看看后立即设置的制约,改变还不会在<$ C反映$ C>架设置。你可以做一个 [containerView layoutIfNeeded]; 如果你想迫使它重新布局基于约束的一切。另外,如果你想确认设置,最好推迟看着那些值,直到后 viewDidAppear (即 viewDidLoad中是鉴于施工过程中太早)。

Make sure you're not trying to look at the frame immediately after setting the constraints, as the change will not yet be reflected in the frame settings. You can do a [containerView layoutIfNeeded]; if you want to force it to relayout everything based upon the constraints. Also, if you want to confirm frame settings, it's better to defer looking at those values until after viewDidAppear (i.e. viewDidLoad is too early in the view construction process).

在您的code一个小调整(并无关你的问题),但是当我在一个容器视图中设置的限制,我经常会设置不仅 NSLayoutAttributeTop NSLayoutAttributeLeading ,像你这样,也 NSLayoutAttributeBottom NSLayoutAttributeTrailing (而不是 NSLayoutAttributeWidth NSLayoutAttributeHeight )。它实现了同样的事情,你的code,但使用非零值时,它是一个分数更直观。

A minor tweak on your code (and unrelated to your problem), but when I'm setting the constraints within a container view, I often will set not only NSLayoutAttributeTop and NSLayoutAttributeLeading, like you did, but also NSLayoutAttributeBottom and NSLayoutAttributeTrailing (rather than NSLayoutAttributeWidth and NSLayoutAttributeHeight). It accomplishes the same thing as your code, but when using non-zero values, it is a fraction more intuitive.

反正,我只是做了以下code,你的排列,并能正常工作:

Anyway, I just did the following code, permutation of yours, and it works fine:

- (IBAction)didTouchUpInsideAddView:(id)sender
{
    UIView *containerView = self.containerView;
    UIView *newSubview = [[UIView alloc] initWithFrame:CGRectZero]; // initializing with CGRectZero so we can see it change
    newSubview.translatesAutoresizingMaskIntoConstraints = NO;
    newSubview.backgroundColor = [UIColor lightGrayColor];
    [containerView addSubview:newSubview];

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview
                                                              attribute:NSLayoutAttributeTop
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeTop
                                                             multiplier:1.0
                                                               constant:0.0]];

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview
                                                              attribute:NSLayoutAttributeLeading
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeLeading
                                                             multiplier:1.0
                                                               constant:0.0]];

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview
                                                              attribute:NSLayoutAttributeBottom
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeBottom
                                                             multiplier:1.0
                                                               constant:0.0]];

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:newSubview
                                                              attribute:NSLayoutAttributeTrailing
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeTrailing
                                                             multiplier:1.0
                                                               constant:0.0]];

    // the frame is still `CGRectZero` at this point

    NSLog(@"newSubview.frame before = %@", NSStringFromCGRect(newSubview.frame));

    // if not doing this in `viewDidLoad` (e.g. you're doing this in
    // `viewDidAppear` or later), you can force `layoutIfNeeded` if you want
    // to look at `frame` values. Generally you don't need to do this unless
    // manually inspecting `frame` values or when changing constraints in a
    // `animations` block of `animateWithDuration`.

    [containerView layoutIfNeeded];

    // everything is ok here

    NSLog(@"containerView.bounds after = %@", NSStringFromCGRect(containerView.bounds));
    NSLog(@"newSubview.frame after = %@", NSStringFromCGRect(newSubview.frame));
}


  • 您可以简化使用code稍微<一个href=\"https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Articles/formatLanguage.html#//apple_ref/doc/uid/TP40010853-CH3-SW1\">visual格式语言,例如:

    NSDictionary *views = NSDictionaryOfVariableBindings(newSubview);
    
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newSubview]|"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:views]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[newSubview]|"
                                                                          options:0
                                                                          metrics:nil
                                                                            views:views]];
    

    我觉得它更容易使用权视觉形式语言获得的制约。少一点容易出错(对我来说,至少)。还有,虽然一些限制,不能再以视觉形式语言psented $ P $,在这种情况下,我回落到您勾勒的语法。

    I find it easier to get the constraints right using visual format language. A little less error-prone (for me, at least). There are, though, some constraints that cannot be represented in visual format language, in which case I fall back to the syntax you outline.

    在你修改的问题,你告诉我们,一个的init 为您的子视图,其中确实方法的其他 addSubview 。你必须有设置的限制了。底线,无论你做 addSubview ,你必须设置你的约束,例如

    In your revised question, you show us an init method for your subview, which does another addSubview. You have to set constraints there, too. Bottom line, wherever you do addSubview, you have to set your constraints, e.g.

    - (id)init
    {
        if(self = [super init])
        {
            NSArray *nibArray = [[NSBundle mainBundle]loadNibNamed:@"MySubview" owner:self options:nil];
            UIView *subview = [nibArray objectAtIndex:0];
            subview.translatesAutoresizingMaskIntoConstraints = NO;
    
            [self addSubview:subview];
    
            NSDictionary *views = NSDictionaryOfVariableBindings(subview);
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview]|"
                                                                         options:0
                                                                         metrics:nil
                                                                           views:views]];
            [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview]|"
                                                                         options:0
                                                                         metrics:nil
                                                                           views:views]];
        }
        return self;
    }
    


  • 这篇关于使用自动布局,设置动态的UIView匹配容器视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆