使用自动布局,设置动态的UIView匹配容器视图(Use autolayout to set dyn

2019-08-31 20:17发布

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

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

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]];  

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


************* 附加信息 **************


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

在AppDelegate.m didFinishLaunchingWithOptions,我创建这样MyViewController,

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

在viewDidLoad中在MyViewController.m,我创建mySubview并将其添加到我的containerView,创建这样它的限制,

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初始化我添加笔尖作为这样一个子视图,

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

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

在MyViewController.xib,我有我使用的containerView一个UIView。 它有一个IBOutlet到的UIView * containerView,是一个上面提到。 我有在IB的containerView唯一限制是,导致,拖尾和底部空间的SuperView和顶部空间的SuperView = 44。

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

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

我希望发生的是mySubview规模,以适应containerView因为限制已经创建并添加而是mySubview变得非常大,剪辑containerView。

下面是一些屏幕截图:

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

MySubview.xib

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

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

在iPhone 4,

在iPhone 5,

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

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

Answer 1:

一对夫妇的想法:

  1. 这基本上看起来不错,除了一些变量名的怪事:你的局部变量, containerView等于self.subView ,但所有其他行是指在不同的变量,类属性, self.containerView 。 你忽略你设置一个线containerView类的属性? 但是,当我固定的,你的代码为我工作的罚款。

  2. 确保你不是想看看frame设置限制后,为改变还不会在反射frame设置。 你可以做一个[containerView layoutIfNeeded]; 如果你想迫使它重新布局基于约束的一切。 另外,如果要确认frame的设置,最好推迟看着那些值,直到后viewDidAppear (即viewDidLoad在视图中施工过程中过早)。

  3. 在验证码的小调整(或无关的你的问题),但是当我在一个容器视图中设置的限制,我经常会设置不仅NSLayoutAttributeTopNSLayoutAttributeLeading ,像你这样,也NSLayoutAttributeBottomNSLayoutAttributeTrailing (而不是NSLayoutAttributeWidthNSLayoutAttributeHeight )。 它实现了同样的事情,你的代码,但使用非零值时,它是一个分数更直观。

    反正,我只是做了下面的代码,你的排列,并能正常工作:

     - (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` (eg 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)); } 
  4. 您可以使用简化代码有点视觉格式的语言 ,如:

     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]]; 

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

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

     - (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; } 


Answer 2:

在你的国家的问题“我的新子视图不调整来匹配容器视图” - 但我觉得他们的描述 - 问题是,你的容器视图没有固定的大小。

我认为,如果你设置你的容器视图有一个固定的宽度和高度,要做到这一点,你可能还需要调用

[self.containerView layoutSubviews]

给力更新约束条件之后,调整大小。

我也建议你换到使用基于文本格式,你可以换出你的线条上面的东西,如“H:| [newSubview] |” 和 “V:| [newSubview] |”



文章来源: Use autolayout to set dynamic UIView to match container view