2013-06-20 1 views
1

В представлении с ограничениями есть несколько ярлыков (сверху), кнопок (внизу) и подкласса UIView (шашки), который состоит из множества CALayers. Before animation Я пытаюсь оживить размер представления пути удаления и добавления ограничений:Автоматическая компоновка, анимация и слои в подвале

// self.containerWidth is a constraint instance 
// from Interface Builder Outlet, which is set to 
// constrain the width of the whole view. 
[self.calendarContainer removeConstraint:self.containerWidth]; 

[UIView animateWithDuration:4.0 animations:^{ 
    [self.calendarContainer addConstraint: 
     [NSLayoutConstraint constraintWithItem:self.calendarContainer 
     attribute:NSLayoutAttributeWidth 
     relatedBy:NSLayoutRelationEqual 
     toItem:self.view 
     attribute:NSLayoutAttributeWidth 
     multiplier:0 
     constant:700]]; 
    [self.calendarContainer layoutIfNeeded]; 
}]; 

После анимации, вид выглядит следующим образом: After animation

Во время анимации, метки (вверху) и кнопки (внизу) двигались плавно в соответствии с указанной выше продолжительностью, , однако, чек-представление быстро переходило в конечное состояние до того, как произошли какие-либо другие переходы.

Я подозреваю, что что-то неточно смешивалось с некоторыми CATransaction.

По мнению контролера, я переставил кадры слоев в -layoutSubviews:

- (void)layoutSubviews { 
    [super layoutSubviews]; 
    if (!self.layer.sublayers.count) { 
     [self prepareLayers]; 
    } 
    int rowCount = [self rowCount]; 
    CGFloat rowHeight = [self rowHeight]; 
    [self.layer.sublayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     CALayer *rowLayer = obj; 
     NSNumber *rowIndex = [rowLayer valueForKey:@"rowindex"]; 
     if (rowIndex) { 
      NSUInteger rowIndexValue = rowIndex.integerValue; 
      if (rowIndexValue < rowCount) { 
       rowLayer.hidden = NO; 
       rowLayer.frame = CGRectMake(0, rowHeight * rowIndexValue, self.frame.size.width, rowHeight); 
       [rowLayer.sublayers enumerateObjectsUsingBlock:^(id obj2, NSUInteger idx2, BOOL *stop2) { 
        CALayer *cellLayer = obj2; 
        NSUInteger colIndex = [[cellLayer valueForKey:@"cellindex"] integerValue] - rowIndexValue * 7 - 1; 
        cellLayer.frame = CGRectMake(colIndex*self.frame.size.width/7, 0, self.frame.size.width/7, rowHeight); 
       }]; 
      } else { 
       // hide 
       rowLayer.hidden = YES; 
      } 
     } 
    }]; 

} 

Как я могу исправить эти анимации?

BTW, где наиболее рекомендуемое место для вставки этого кода повторного позиционирования слоя?

ответ

2

Похоже, что эффект был получен из неявной анимации слоев.

Следующий код может исправить все несоответствия анимации.

NSTimeInterval duration = 4.0; 
[UIView animateWithDuration:duration animations:^{ 

    [CATransaction begin]; 
    [CATransaction setValue:@(duration) 
        forKey:kCATransactionAnimationDuration]; 
    CAMediaTimingFunction *func = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

    [CATransaction setAnimationTimingFunction:func]; 
    [self.calendarContainer removeConstraint:self.containerWidth]; 

    [self.calendarContainer addConstraint:[NSLayoutConstraint constraintWithItem:self.calendarContainer attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0 constant:700]]; 
    [self.calendarContainer layoutIfNeeded]; 
    [CATransaction commit]; 
}];