ios – 在方向更改时更新UICollectionView补充视图的约束

我在我的UICollectionView中使用标题(补充视图).在标题上,我有一个与左侧有一定距离的标签.我正在进行计算并设置约束的常量.一切都按预期工作.

如果现在更改方向,则标签具有旧位置.现在我需要更新所有标头的约束.调用invalidateLayout不会更新约束.如何手动触发重新计算?

编辑:

这就是我的layoutSubviews看起来的样子,重新计算的位置:

public override void LayoutSubviews ()
{
    this.width = this.collectionViewSize.Width;
    this.itemWidth  = (nfloat)Math.Round(this.width / numberOfItemsInRow);

    leftSpacing.Constant =  this.itemWidth * this.referencePoint;
    if (leftSpacing.Constant == 0)
        leftSpacing.Constant = SectionHeader.MIN_SPACING;

    base.LayoutSubviews ();
}

正如您所看到的,这不是Objective-C,但您应该能够看到我在做什么.我取集合视图的宽度(在补充视图的实例化时设置),然后我计算几乎对应于单元格实际大小的单元格宽度.使用referencePoint我确定位置.在这里,您可以看到我的约束的设置:

public SectionHeader (CGRect frame) : base (frame)
{
    this.width = frame.Size.Width;
    this.itemWidth  = (nfloat)Math.Round(width / numberOfItemsInRow);

    label = new UILabel (){
        BackgroundColor = UIColor.White,
        TextAlignment = UITextAlignment.Left
    };

    label.TranslatesAutoresizingMaskIntoConstraints = false;
    AddSubview (label);

    NSMutableDictionary viewsDictionary = new NSMutableDictionary();
    viewsDictionary["label"] = label;

    this.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[label]|",(NSLayoutFormatOptions)0,null,viewsDictionary));

    leftSpacing = NSLayoutConstraint.Create(label, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1, SectionHeader.MIN_SPACING);
    leftSpacing.Priority = 250;
    this.AddConstraint(leftSpacing);
    this.AddConstraint(NSLayoutConstraint.Create(label, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1, 0));
}

在此代码中,左边距离的计算几乎相同,只是框架具有set headerReferenceSize的高度.初始化的宽度应该可以.我正在使用标签的全高,我设置了前导空间,然后将其固定在右侧.

最佳答案 您需要在视图控制器的主视图上调用layoutIfNeeded,以便更新约束.这样的事情应该有效:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    // Update the constraints here for the new orientation - toOrientation
    // ...

    [UIView animateWithDuration:duration animations: ^{
        [self.view layoutIfNeeded];
    }];
}

这将在方向更改时设置布局更改的动画.

您可以在layoutIfNeeded调用之后添加断点,以查看帧是您期望的.

如果您的约束不在视图控制器中,而是在UIView子类中,则可以执行以下操作:

- (void)awakeFromNib {
    [super awakeFromNib];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateIntrinsicConstraints) name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)updateIntrinsicConstraints {
    // Update your constraints here
    [self.constraint setConstant:newValue];

    // You might need to call [self layoutIfNeeded] here, if you don't call it in another place
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

如果这对您有用,请告诉我!

更新

您不应手动更改SectionHeader的框架.您应该通过实现协议方法来执行此操作:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;

在将约束添加到标签后,可以在SectionHeader的init方法中调用layoutIfNeeded,之后添加断点以查看框架是否正确.

让我知道它是否适合你!

点赞