iOS的自动布局垂直空间等于填补父视图 [英] iOS Autolayout Vertically equal space to fill parent view

查看:141
本文介绍了iOS的自动布局垂直空间等于填补父视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个视图控制器12 的UITextField 秒。

I have a view controller with 12 UITextFields.

它适合一个3.5的显示效果相当出色。

It fits a 3.5" display very well.

我需要将其设置为iPhone 5(4英寸显示屏),这样所有的的UITextField 封面全的UIView 通过在两者之间增加额外的空间。

I need to set it for iPhone 5 (4 inch display) such that all UITextFields cover the whole UIView by adding extra space in between.

我试图通过自动布局要做到这一点,但它不能正常工作。

I am trying to do this by auto layout but it is not working properly.

这是我的code:

- (void) viewWillLayoutSubviews
{
    int h = txt1.bounds.size.height * 12;

    float unusedHorizontalSpace = self.view.bounds.size.height - h ;

    NSNumber* spaceBetweenEachButton=  [NSNumber numberWithFloat: unusedHorizontalSpace / 13 ] ;

    NSMutableArray *constraintsForButtons = [[NSMutableArray alloc] init];

    [constraintsForButtons addObjectsFromArray: [NSLayoutConstraint constraintsWithVisualFormat: @"V:|-50-[txt1(==30)]-(space)-[txt2(==txt1)]-(space)-[txt3(==txt1)]-(space)-[txt4(==txt1)]-(space)-[txt5(==txt1)]-(space)-[txt6(==txt1)]-(space)-[txt7(==txt1)]-(space)-[txt8(==txt1)]-(space)-[txt9(==txt1)]-(space)-[txt10(==txt1)]-(space)-[txt11(==txt1)]-(space)-[txt12]-(space)-|"
                                                                                        options: NSLayoutFormatAlignAllCenterX
                                                                                        metrics: @{@"space":spaceBetweenEachButton}
                                                                                          views: NSDictionaryOfVariableBindings(txt1,txt10,txt11,txt12,txt2,txt3,txt4,txt5,txt6, txt7,txt8,txt9)]];

    [self.view addConstraints:constraintsForButtons];
}

如果我 [txt12(== TXT1)] 则显示一样的3.5液晶显示屏和下方留下空间。

If I do [txt12(==txt1)] then it displays the same as the 3.5" screen and leaves space below.

在哪里,我犯了一个错误?

Where I am making a mistake?

推荐答案

要自动布局做到这一点,必须创建额外的意见,以填补文本字段之间的空间。

To do this with auto layout, you must create extra views to fill the spaces between the text fields.

回想一下,自​​动布局约束基本上是线性方程 A = M * B + C A 是一个视图的属性和<$(例如,在Y viewA 的底部边缘的坐标) C $ C> B 是另一个视图的属性(例如,在Y viewB 的顶边的坐标)。 M C 是常数。因此,例如,奠定了 viewA viewB ,以便有底部之间的30分 viewA viewB ,我们可以创建一个约束条件,其中 M 被1和 C 为-30。

Recall that an auto layout constraint is basically the linear equation A = m * B + c. A is an attribute of one view (for example, the Y coordinate of viewA's bottom edge) and B is an attribute of another view (for example, the Y coordinate of viewB's top edge). m and c are constants. So, for example, to lay out viewA and viewB so that there are 30 points between the bottom of viewA and the top of viewB, we could create a constraint where m is 1 and c is -30.

您遇到的问题是,要在13个不同的限制使用相同的值c ,你想自动布局来计算<$ C $ ç> C 为你的价值。自动布局根本无法做到这一点。不直接。自动布局只能计算的看法的属性;它不能计算 M C 常量。

The problem you're having is that you want to use the same value for c across 13 different constraints, and you want auto layout to compute that c value for you. Auto layout simply can't do that. Not directly. Auto layout can only compute the attributes of views; it cannot compute the m and c constants.

有一种方法,使汽车的布局把你想要的看法:具体化文本字段之间的空间作为额外的(无形)的意见。这里只有3文本字段的例子:

There is a way to make auto layout put the views where you want: reify the spaces between the text fields as additional (invisible) views. Here's an example with just 3 text fields:

我们将创建一个约束至间隔的顶部边缘到脚它上面的文本字段的底边。我们还将创建一个约束至间隔的底部边缘引脚拉至低于其文本字段的顶部边缘。最后,我们将创建一个约束强制每个垫片具有相同的高度,最上面的垫片。

We'll create a constraint to pin each spacer's top edge to the bottom edge of the text field above it. We'll also create a constraint to pin each spacer's bottom edge to the top edge of the text field below it. And finally, we'll create a constraint to force each spacer to have the same height as the topmost spacer.

我们需要一个两个实例变量设置事情:文本字段(从上到下按顺序)一个数组,并以最上面的垫片视图的引用:

We'll need a two instance variables to set things up: an array of the text fields (in order from top to bottom), and a reference to the topmost spacer view:

@implementation ViewController {
    NSMutableArray *textFields;
    UIView *topSpacer;
}

,因为它很难显示在计算器回答一个厦门国际银行,我们将创建code中的文本字段和垫片。我们踢东西了在 viewDidLoad中

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    [self addTextFields];
    [self addSpacers];
}

由于我们要使用自动布局,我们需要将系统从创建额外的限制关闭 translatesAutoresizingMaskIntoConstraints 来prevent。

我们创建的每一个文本框,给它一些虚拟的文本,并为它的水平位置和大小的限制:

We create each text field, give it some dummy text, and set up constraints for its horizontal position and size:

- (void)addTextFields {
    textFields = [NSMutableArray array];
    for (int i = 0; i < 12; ++i) {
        [self addTextField];
    }
}

- (void)addTextField {
    UITextField *field = [[UITextField alloc] init];
    field.backgroundColor = [UIColor colorWithHue:0.8 saturation:0.1 brightness:0.9 alpha:1];
    field.translatesAutoresizingMaskIntoConstraints = NO;
    field.text = [field description];
    [self.view addSubview:field];
    [field setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [field setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[field]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(field)]];
    [textFields addObject:field];
}

我们将使用一个循环来太创建隔板,但我们从中间间隔件不同地创建的顶部和底部隔离件,因为我们需要针的顶部和底部隔离件的上海华:

We'll use a loop to create the spacers too, but we create the top and bottom spacers differently from the middle spacers, because we need to pin the top and bottom spacers to the superview:

- (void)addSpacers {
    [self addTopSpacer];
    for (int i = 1, count = textFields.count; i < count; ++i) {
        [self addSpacerFromBottomOfView:textFields[i - 1]
            toTopOfView:textFields[i]];
    }
    [self addBottomSpacer];
}

下面是我们如何建立顶部的垫片并设置其限制。它的顶部边缘被固定在上海华其底部边缘被固定在第一个(最上面的)文本字段。我们存储在实例变量上间隔 topSpacer ,所以我们可以限制其他垫片具有相同的高度上间隔。

Here's how we create the top spacer and set up its constraints. Its top edge is pinned to the superview and its bottom edge is pinned to the first (topmost) text field. We store the top spacer in the instance variable topSpacer so we can constrain the other spacers to have the same height as the top spacer.

- (void)addTopSpacer {
    UIView *spacer = [self newSpacer];
    UITextField *field = textFields[0];
    [self.view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:|[spacer][field]" options:0 metrics:nil
        views:NSDictionaryOfVariableBindings(spacer, field)]];
    topSpacer = spacer;
}

下面是我们如何真正创建一个间隔视图。这只是一个隐藏的视图。由于我们不关心它的水平大小和位置,我们只是将其固定到上海华的左右边缘。

Here's how we actually create a spacer view. It's just a hidden view. Since we don't care about its horizontal size or position, we just pin it to the left and right edges of the superview.

- (UIView *)newSpacer {
    UIView *spacer = [[UIView alloc] init];
    spacer.hidden = YES; // Views participate in layout even when hidden.
    spacer.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:spacer];
    [self.view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"|[spacer]|" options:0 metrics:nil
        views:NSDictionaryOfVariableBindings(spacer)]];
    return spacer;
}

要创建两个文本视图之间的中间隔板,我们将其固​​定到文本的底部边缘
以上字段和下面的文本字段的顶部边缘。我们也限制了其高度等于顶部隔离物的高度。

To create a "middle" spacer between two text views, we pin it to the bottom edge of the text field above and the top edge of the text field below. We also constrain its height to equal the height of the top spacer.

- (void)addSpacerFromBottomOfView:(UIView *)overView toTopOfView:(UIView *)underView {
    UIView *spacer = [self newSpacer];
    [self.view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:[overView][spacer(==topSpacer)][underView]" options:0 metrics:nil
        views:NSDictionaryOfVariableBindings(spacer, overView, underView, topSpacer)]];
}

要创建底部间隔,我们将其固​​定到最后的文本字段,并为上海华。我们也限制了其高度等于顶部隔离物的高度。

To create the bottom spacer, we pin it to the last text field and to the superview. We also constrain its height to equal the height of the top spacer.

- (void)addBottomSpacer {
    UIView *spacer = [self newSpacer];
    UITextField *field = textFields.lastObject;
    [self.view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:[field][spacer(==topSpacer)]|" options:0 metrics:nil
        views:NSDictionaryOfVariableBindings(spacer, field, topSpacer)]];
}

如果你这样做是正确的,你会得到这样的结果:

If you do it right, you will get a result like this:

您可以在这GitHub的库。

这篇关于iOS的自动布局垂直空间等于填补父视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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