如何使用自动布局在iOS 11中将UITextField添加到具有灵活宽度的UIToolbar

时间:2017-10-01 22:40:49

标签: objective-c uitextfield nslayoutconstraint uitoolbar ios11

我想将UITextField添加到UITooolbar并让UITextField根据需要扩展其宽度以填充该区域,就像UIBarButtonSystemItemFlexibleSpace那样。

下面是一个关于我如何在视图控制器中正常设置工具栏项的片段...

// two UIBarButtonItems
UIBarButtonItem *left = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:nil];
UIBarButtonItem *right = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:nil action:nil];

// the UIBarButtonItem with a UITextField as custom view
UITextField *textField = [[UITextField alloc] init];
textField.borderStyle = UITextBorderStyleRoundedRect;
UIBarButtonItem *text = [[UIBarButtonItem alloc] initWithCustomView:textField];

[self setToolbarItems:@[left, text, right]];

......然后会出现这样的情况。

ios11_toolbar

在iOS 11之前,我对UIToolbar进行了细分,并使用layoutSubviews方法获取所有“非灵活”项目的宽度(CGRectGetWidth(itemView.frame)),并计算文本字段视图框架的可用宽度。 在iOS 11中,Apple更改为自动布局WWDC2017 session 204中提到的所有条形图,现在CGRectGetWidth(itemView.frame)方式在视图可见之前不会提供有效宽度,{{3}也指出了}。

我现在如何使用约束和自动布局添加灵活大小的UIBarButtonItems和自定义,这将扩展以填充两个项目之间的完整空闲区域?

编辑1:

如果我只添加文本字段,则项目将按预期扩展其宽度。

iOS 11 UIBarButtonItem images not sizing

编辑2:

直接在UIToolbar中使用约束似乎是不可能的,因为项目视图不存在(直到它们被放置?)或者没有超级视图。

UIBarButtonItem *left = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:nil];
UIView *leftView = [left valueForKey:@"view"];
UIBarButtonItem *right = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:nil action:nil];
UIView *rightView = [right valueForKey:@"view"];

UITextField *textField = [[UITextField alloc] init];
textField.borderStyle = UITextBorderStyleRoundedRect;
UIBarButtonItem *text = [[UIBarButtonItem alloc] initWithCustomView:textField];

NSDictionary *views = NSDictionaryOfVariableBindings(leftView, textField, rightView);
NSString *formatString = @"|-[leftView]-[textField]-[rightView]-|";

NSArray *constraint = [NSLayoutConstraint constraintsWithVisualFormat:formatString options:NSLayoutFormatAlignAllCenterX metrics:nil views:views];
[NSLayoutConstraint activateConstraints:constraint];

[self setToolbarItems:@[left, text, right]];

编辑3:

有了检查ios11_toolbar_textfield_only的想法,我最后得到了以下代码来添加约束......

// _UIToolbarContentView
//   + _UIButtonBarStackView
//       + _UIButtonBarButton
//       + UIView
//       + _UITAMICAdaptorView
//       + UIView
//

UIView *contentView = nil;
for (UIView *view in self.navigationController.toolbar.subviews) {
    if ([view.description containsString:@"ContentView"]) {
        contentView = view;
    }
}

UIView *stackView = nil;
for (UIView *view in contentView.subviews) {
    if ([view.description containsString:@"ButtonBarStackView"]) {
        stackView = view;
    }
}

// constrain views on stack
UIView *uiButtonBarButton = [stackView.subviews objectAtIndex:0];
[uiButtonBarButton.leadingAnchor constraintEqualToAnchor:stackView.leadingAnchor].active = YES;

UIView *uiTAMICAdaptorView = [stackView.subviews objectAtIndex:2];
[uiTAMICAdaptorView.leadingAnchor constraintEqualToAnchor:uiButtonBarButton.trailingAnchor].active = YES;
[uiTAMICAdaptorView.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor].active = YES;

...这会改变这样的观点:

view hierarchy for UIToolbar

为什么UIBarButton会调整大小而不是UITextField又名UITAMICAdaptorView?

使用约束修复UIBarButton的大小......

[uiButtonBarButton.widthAnchor constraintEqualToConstant:CGRectGetWidth(uiButtonBarButton.frame)].active = YES;

......看起来像......

enter image description here

...但遗憾的是,UIButtonBarButton的框架在放置项目之前无效。

那么如何在不知道它的情况下约束UIButtonBarButton的宽度。像'notGreaterThanNecessary'之类的东西?

1 个答案:

答案 0 :(得分:2)

将单个UIView直接放入单个UIBarButtonItem中,这将成为UIToolBar的全宽。

现在,您可以正常使用布局约束添加所需的任何子视图。水平UIStackView在这里可以很好地工作。