搜索

首页  >  问答  >  正文

iOS:autolayout,多个label如何设置居中显示?

刚学autolayout,关于这个问题,一直没搞清楚!

c[backview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[lab_before][lab_middle][lab_after]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(lab_before,lab_middle,lab_after)]];

枚举类型参数中:

ctypedef NS_OPTIONS(NSUInteger, NSLayoutFormatOptions) {
    NSLayoutFormatAlignAllLeft = (1 << NSLayoutAttributeLeft),
    NSLayoutFormatAlignAllRight = (1 << NSLayoutAttributeRight),
    NSLayoutFormatAlignAllTop = (1 << NSLayoutAttributeTop),
    NSLayoutFormatAlignAllBottom = (1 << NSLayoutAttributeBottom),
    NSLayoutFormatAlignAllLeading = (1 << NSLayoutAttributeLeading),
    NSLayoutFormatAlignAllTrailing = (1 << NSLayoutAttributeTrailing),
    NSLayoutFormatAlignAllCenterX = (1 << NSLayoutAttributeCenterX),
    NSLayoutFormatAlignAllCenterY = (1 << NSLayoutAttributeCenterY),
    NSLayoutFormatAlignAllBaseline = (1 << NSLayoutAttributeBaseline),
    NSLayoutFormatAlignAllLastBaseline = NSLayoutFormatAlignAllBaseline,
    NSLayoutFormatAlignAllFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0) = (1 << NSLayoutAttributeFirstBaseline),

    NSLayoutFormatAlignmentMask = 0xFFFF,

参数中的NSLayoutFormatAlignAllCenterX,该如何使用?每次使用都回报错!

附上报错信息:

cNSInvalidArgumentException|Unable to parse constraint format: \nOptions mask required views to be aligned on a horizontal edge, which is not allowed for layout that is also horizontal. \nH:|[lab_before][lab_middle][lab_after]| \n                           ^|(\n    \"4   libc++abi.dylib                     0x0000000192c65bb4 <redacted> + 16\",\n    \"5   libc++abi.dylib                     0x0000000192c65478 <redacted> + 0\",\n    \"6   libobjc.A.dylib                     0x0000000193478204 <redacted> + 0\",\n    \"7   Foundation                          0x0000000183ce11cc <redacted> + 0\",\n    \"8   Foundation                          0x0000000183b6bf44 <redacted> + 1296\"\n)|iPhone OS|8.1|1.0.0|iPhone7,1";
}]

希望,各位大神指教!

高洛峰高洛峰2772 天前678

全部回复(4)我来回复

  • 高洛峰

    高洛峰2017-04-17 13:40:43

    刚刚算是勉强自己解决了:方法比较笨,即用一个backview来包含3个label,然后计算3个label的宽度并赋值给外层的backview,最后把backview居中显示,就完成了3个label的居中显示!如果有更好的方法,欢迎补充,讨论!

    层次结构是:

    c- view
        -backview
            -label1
            -label2
            -label3
    
    c// 设置水平布局
        [backview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[lab_before]-[lab_middle]-[lab_after]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(lab_before,lab_middle,lab_after)]];
    
    c// 设置backview宽度
        [view addConstraint:[NSLayoutConstraint constraintWithItem:backview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:dynaContentView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:before_width+middle_width+after_width]];
    
        // 设置backview居中显示
        [view addConstraint:[NSLayoutConstraint constraintWithItem:backview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:dynaContentView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
    
        // 设置backview的高度
        [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[backview(==34)]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(backview)]];
    

    问题来了:

    有没有方法不计算每个label的宽度并赋值给superview的宽度,而是自动填充superview!

    PS:我在测试的时候,发现不设置backview的宽度,就是整个屏幕的宽度!


    2015/03/01更新:

    c@interface CustomView1 : UIView
    @property(nonatomic, strong) UILabel *label1;
    @property(nonatomic, strong) UILabel *label2;
    @end
    
    c@implementation CustomView1
    
    -(id)init{
        self = [super init];
        if(self){
            _label1 = [UILabel new];
            _label1.text = @"AAAAAA121212121";
            _label1.textColor = [UIColor blackColor];
            _label1.translatesAutoresizingMaskIntoConstraints = NO;
            [self addSubview:_label1];
    
            _label2 = [UILabel new];
            _label2.text = @"BBBBBB";
            _label2.textColor = [UIColor orangeColor];
            _label2.translatesAutoresizingMaskIntoConstraints = NO;
            [self addSubview:_label2];
    
        }
        return self;
    }
    
    - (void)updateConstraints{
        NSDictionary *views = NSDictionaryOfVariableBindings(_label1,_label2);
    
        // label1的宽高
        [self addConstraint:[NSLayoutConstraint constraintWithItem:_label1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[_label1 intrinsicContentSize].width]];
    
        [self addConstraint:[NSLayoutConstraint constraintWithItem:_label1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[_label1 intrinsicContentSize].height]];
    
        // label2的宽高
        [self addConstraint:[NSLayoutConstraint constraintWithItem:_label2 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[_label2 intrinsicContentSize].width]];
    
        [self addConstraint:[NSLayoutConstraint constraintWithItem:_label2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[_label2 intrinsicContentSize].height]];
    
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_label1][_label2]|" options:NSLayoutFormatAlignAllBottom metrics:nil views:views]];
    
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_label1]|" options:0 metrics:nil views:views]];
    
        [super updateConstraints];
    }
    
    - (CGSize)intrinsicContentSize{
        CGSize l1size = [_label1 intrinsicContentSize];
        CGSize l2size = [_label2 intrinsicContentSize];
    
        return CGSizeMake(l1size.width + l2size.width, l1size.height);
    }
    
    @end
    

    回复
    0
  • 迷茫

    迷茫2017-04-17 13:40:43

    Q:有没有方法不计算每个label的宽度并赋值给superview的宽度,而是自动填充superview?
    A:重写superview的updateConstraints和intrinsicContentSize方法

    回复
    0
  • 高洛峰

    高洛峰2017-04-17 13:40:43

    1. 一个 containerview 包含3个 label

    2. 这3个 label 不要指定宽度,

    3. 约束 containerview 和 left+right 的边距约束

    4. 约束 left center right labels 的间距关系

    5. 约束 contrainerview 居中

    回复
    0
  • 怪我咯

    怪我咯2017-04-17 13:40:43

    我也一直被这个问题困扰, 多个view想要剧中需要外部套用一个View, 如果手动设置计算frame就不会出现这个问题, 可见autolaout也是有缺点的。

    回复
    0
  • 取消回复