iOS анимация UILabel развернуть

у меня есть UILabel, который начинается с 3 строк текста:

locationDescription = [[UILabel alloc]init];
locationDescription.numberOfLines = 3;
[locationDescription setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:locationDescription];

затем у меня есть кнопка, которая расширяет метку:

- (void)buttonPressed:(UIButton *)sender{
    NSLog(@"Pressed");
    [UIView animateWithDuration:1
                     animations:^{locationDescription.numberOfLines = 0;}
     ];
}

желаемое поведение для метки состоит в том, чтобы каждая дополнительная строка раскрывалась по одному за раз. Метка расширяется нормально, но переход не анимирован, и все линии просто появляются сразу.

что я упустил?

3 ответов


Вы можете анимировать количество линий. Он меняет intrinsicSize из UILabel. Вам нужно вызвать layoutIfNeeded внутри вашего блока анимации в представлении, содержащем UILabel. Здесь я прикрепляю жест крана к таблице, чтобы переключить его между 0 (столько, сколько вы хотите) линиями и 1 линией.

 func tapLabel(tapGesture: UITapGestureRecognizer)
 {
    if let label = tapGesture.view as? UILabel {
      label.numberOfLines = label.numberOfLines == 0 ? 1 : 0
      UIView.animateWithDuration(0.5) {
        label.superview?.layoutIfNeeded()
      }
    }
 }

enter image description here


вы не можете анимировать количество строк, вы должны анимировать размер и установить количество строк равным 0 с самого начала.

Я не добавляю код расчета высоты, поскольку он скрывает реальную анимацию здесь.

self.locationDescription = [[UILabel alloc] init];
self.locationDescription.numberOfLines = 0;
[locationDescription setTranslatesAutoresizingMaskIntoConstraints:NO];

// Say, it starts with 50. In your real code, height should be calculated
// to fit the size you want, rounded to lines
NSDictionary *viewsDict = @{@"locationDescription": self.locationDescription};
[self.locationDescription addConstraints:
 [NSLayoutConstraint constraintsWithVisualFormat:@"V:[locationDescription(50)]"
                                         options:0 metrics:nil
                                           views:viewsDict];

тогда в действии сделайте

- (void)buttonPressed:(UIButton *)sender
{
    NSLog(@"Pressed");
    // Assuming there is only one constraint. If not, assign it to another property
    // I put 500, but, again, real size rounded to line height should be here
    self.locationDescription.constraints[0].constant = 500;
    [UIView animateWithDuration:1 animations:^{
        // Layouting superview, as its frame can be updated because of a new size
        [self.locationDescription.superview layoutIfNeeded];
    }];
}

кроме того, вы должны назначить locationDescription в собственность и доступ к нему с self. перед.


объект блока UIView animateWithDuration содержит изменения для фиксации в представлениях. Здесь программно изменяются все анимируемые свойства представлений в иерархии представлений. Но указанное свойство numberOfLines не является анимируемым свойством.

следующие свойства класса UIView, который является родительским классом UILabel, являются анимируемыми:

 @property frame
 @property bounds
 @property center
 @property transform
 @property alpha
 @property backgroundColor
 @property contentStretch