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?
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()
}
}
}
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With