AutoLayout不会将子视图固定到superview

时间:2013-06-15 19:01:00

标签: ios uitableview autolayout

我正在尝试将自定义UITableViewCell类内的子视图固定到单元格contentView的左侧。我正在将子视图添加到子类的contentView方法内的initWithStyle内,并在该方法中添加约束。不幸的是,我有两个问题:

  1. 子视图未固定到contentView的左边缘,即使我使用以下代码执行此操作:

    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_animatedView]-[_aTextField][_rightImageView]|"
                                                                             options:NSLayoutFormatDirectionLeftToRight
                                                                             metrics:nil views:viewDictionary]];
    

    对我来说,该格式字符串应该将_animatedView固定到contentView的左侧,然后将其他后续视图添加到尽可能接近的后面。相反,所有三个视图在contentView的中间以正确的顺序显示在一起,而不是在左边缘。我是新手使用autolayout,所以这可能会混淆我的格式字符串是如何工作的。

  2. 解决:感谢Guillaume的建议,我能够进行一些测试,并发现当我滚动表格时单元格内容被大幅移位的原因是我没有覆盖UITableViewCell方法,prepareForReuse。当UITableViewCell准备重用以显示UITableView中另一个对象的信息时会调用此方法,这在滚动发生时偶然发生。解决方案就像将以下代码插入到我的UITableViewCell子类中一样简单:

    -(void) prepareForReuse
     {
         [self setNeedsUpdateConstraints];
     }
    
  3. 另一个问题是,在我选择使用自定义单元格的TableView行之前,约束似乎不会被强制执行。是否有initWithStyle以外的其他地方我应该设置约束,还是这是一个不同的问题?

    更新

    CustomTableCell.m

    @interface ListTableCell ()
    {
        NSDictionary *_viewsForConstraints;    // Used inside updateConstraints method.
        NSArray *_animatedViewSizeConstraints;
        NSArray *_centeringConstraints;
        NSArray *_horizontalConstraints;
    }
    @end
    
     - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self)
        {
           // Set up the cell elements.
           self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
    
           self.animatedView = [[AnimatedView alloc] initWithFrame:CGRectZero];
           self.animatedView.translatesAutoresizingMaskIntoConstraints = NO;
           [self.contentView addSubview:self.animatedView];
    
           self.aTextField = [[UITextField alloc] initWithFrame:CGRectZero];
           self.aTextField.textColor = [UIColor whiteColor];
           self.aTextField.translatesAutoresizingMaskIntoConstraints = NO;
           [self.contentView addSubview:self.aTextField];
    
           self.rightImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
           self.rightImageView.translatesAutoresizingMaskIntoConstraints = NO;
           [self.contentView addSubview:self.rightImageView];
    
           _viewForConstraints = NSDictionaryOfVariableBindings(_animatedView,   
           _aTextField, _rightImageView);
    
           // Add height/width constraints to the animated view.
           NSLayoutConstraint *heightConstraint =
           [NSLayoutConstraint constraintWithItem:self.animatedView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1  constant:self.contentView.frame.size.height];
           NSLayoutConstraint *aspectRatioConstraint = [NSLayoutConstraint constraintWithItem:self.animatedView attribute:NSLayoutAttributeHeight relatedBy:0 toItem:self.animatedview attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
    
           _animatedViewSizeConstraints = @[heightConstraint, aspectRatioConstraint];
    
           // Center elements vertically.
    
           NSLayoutConstraint *animatedViewVerticalCenterConstraint =
           [NSLayoutConstraint constraintWithItem:self.animatedView
                                     attribute:NSLayoutAttributeCenterY
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:self.contentView
                                     attribute:NSLayoutAttributeCenterY
                                    multiplier:1.0
                                      constant:0.0];
            NSLayoutConstraint *aTextFieldVerticalCenterConstraint =
            [NSLayoutConstraint constraintWithItem:self.aTextField
                                     attribute:NSLayoutAttributeCenterY
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:self.contentView
                                     attribute:NSLayoutAttributeCenterY
                                    multiplier:1.0
                                      constant:0.0];
            NSLayoutConstraint *rightImageVerticalCenterConstraint =
            [NSLayoutConstraint constraintWithItem:self.rightImageView
                                     attribute:NSLayoutAttributeCenterY
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:self.contentView
                                     attribute:NSLayoutAttributeCenterY
                                    multiplier:1.0
                                      constant:0.0];
    
           _centeringConstraints = @[animatedViewVerticalCenterConstraint,
                                     aTextFieldVerticalCenterConstraint, rightImageVerticalCenterConstraint];
    
           _horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_animatedView]-[_aTextField][_rightImageView]|"
                    options:NSLayoutFormatDirectionLeftToRight metrics:nil views:viewDictionary]];
           self.backgroundColor = [UIColor greenColor];
           self.editingAccessoryType = UITableViewCellAccessoryNone;
           self.accessoryType = UITableViewCellAccessoryNone;
           self.selectionStyle = UITableViewCellSelectionStyleNone;
           self.aTextField.userInteractionEnabled = NO;
    
           [self setNeedsUpdateConstraints];
      }
    
    -(void) updateConstraints
    {
        [super updateConstraints];
    
        [self.contentView addConstraints:_animatedViewSizeConstraints];
        [self.contentView addConstraints:_centeringConstraints];
        [self.contentView addConstraints:_horizontalConstraints];
    }
    

    TableViewController.m

     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
     {
        static NSString *CellIdentifier = @"Cell";
        CustomTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
        // Configure the cell.
        cell.aTextField.text = @"Test Text";
        cell.aTextField.delegate = self;
    
        return cell;
    }
    

    我可以确认initWithStyle被调用了,因为背景总是绿色,子视图总是显示出来,它们最初只显示奇怪的间距。

    感谢您对此有任何帮助!

2 个答案:

答案 0 :(得分:2)

您应该在updateConstraints方法中设置约束。来自doc:

  

自行设置约束的自定义视图应该通过覆盖此方法来实现。

至少解决你的#2问题。

答案 1 :(得分:0)

请勿关闭工作台视图translatesAutoresizingMaskIntoConstraints的{​​{1}}。

我之前遇到过这个问题。

删除此行:contentView

基本上,您的视图 固定在self.contentView.translatesAutoresizingMaskIntoConstraints = NO;的左边缘,但内容视图不是单元格的整个宽度。您可以使用contentView或Reveal之类的内容来查看情况。