Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS animating UILabel expand

I have a UILabel that's initiated with 3 lines of text:

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

I then have a button that expands the label:

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

The desired behavior for the label is to have each extra line reveal itself one at a time. The label expands fine, but the transition isn't animated and all the lines just show up at once.

What am I missing?

like image 699
sheepgobeep Avatar asked Jan 06 '14 19:01

sheepgobeep


3 Answers

You can animate number of lines. It changes the intrinsicSize of the UILabel. You need to call layoutIfNeeded inside your animation block on the view containing the UILabel. Here I attach a tap gesture to the table to toggle it between having 0 (as many as you want) lines and 1 line.

 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

like image 74
Ray Fix Avatar answered Nov 19 '22 22:11

Ray Fix


UIView animateWithDuration's block object contains the changes to commit to the views. This is where you programmatically change any animatable properties of the views in your view hierarchy. But the property that you have specified, numberOfLines, is not animatable property.

The following properties of the UIView class which is parent class of UILabel are animatable:

 @property frame
 @property bounds
 @property center
 @property transform
 @property alpha
 @property backgroundColor
 @property contentStretch
like image 34
ldindu Avatar answered Nov 19 '22 23:11

ldindu


You can't animate number of lines, you should animate size, and set number of lines to be 0 from the very start.

I am not adding height calculation code as it would hide the real animation here.

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];

Then in the action, do

- (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];
    }];
}

Also, you should assign locationDescription to a property and access it with self. in front.

like image 32
coverback Avatar answered Nov 19 '22 21:11

coverback