animateWithDuration in UITableViewCell's setSelected method has no effect - ios

I'm trying a simple animation for selection/deselection of a UITableViewCell like this:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[UIView animateWithDuration: 0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
tabConstraint.constant = selected ? 40 : 20;
} completion:nil];
}
The code inside the animations block will be called, but it's not animating. Everything works fine, but there's not any animation at all. How could I make the cell selection animated?

Every time you update a autolayout constraint, you have to call layoutIfNeeded,
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[UIView animateWithDuration: 0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
tabConstraint.constant = selected ? 40 : 20;
[self layoutIfNeeded];
} completion:nil];
}

You need to call layoutIfNeeded in your animations block. Check out the accepted answer on this question for more details: How do I animate constraint changes?

You need to call layoutIfNeeded() inside the animation block :-)
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
tabConstraint.constant = selected ? 40 : 20;
[UIView animateWithDuration: 0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
whateverTabYouHaveHere.layoutIfNeeded()
} completion:nil];
}

Related

AnimateWithDuration doesn't work as expected

I'm trying to run an example to test this function. I have a label an a button in the storyBoard and I have referenced the bottom constraint of the label in the view controller. When I use the button I want the label to move with an animation but it moves without it. Here's the code of the button:
- (IBAction)sd:(id)sender {
[UIView animateWithDuration:0.5f animations:^{
self.constraint.constant += 50;
}];
}
I know how to use it in swift but I'm having problems in objective c and I know it will be just for a little mistake... Any help?
This is not the right way of animating a UI component constrained with Autolayout. You should first update the constraint, then call layoutIfNeeded within the animation block:
self.constraint.constant += 50;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
Use this
self.constraint.constant += 50;
[UIView animateWithDuration:0.5f
animations:^{
[self.view layoutIfNeeded];
}];
Try this setNeedsLayout helps in some cases.
self.constraint.constant += 50;
[UIView animateWithDuration:0.5f
animations:^{
[self.view setNeedsLayout];
}
completion:^(BOOL finished) {
}];

How can I animate NSLayoutConstraint when GMSMapView will move?

I want to animate buttons moving when user scrolls map (that has type GMSMapView) in my iOS application:
- (void)setButtonHidden:(bool)hidden
[UIView animateWithDuration:1 animations:^{
[_myButton setAlpha:hidden ? 0 : 1];
// or so:
[_myButtonConstraint setConstant:hidden ? -40 : 92];
[[self view] layoutIfNeeded];
}
}
Button showing animation works perfectly, but hiding is not animated.
I think than it's because of I calls [self setButtonHidden:YES] from mapView:willMove: method after which map view will be animated.
How can I combine different animations, in this case my animation and GMSMapView animation?
I found solution. Reason is GMSMapView bug
Solution is:
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1 animations:^{
[_myButton setAlpha:hidden ? 0 : 1];
// or so:
[_myButtonConstraint setConstant:hidden ? -40 : 92];
[[self view] layoutIfNeeded];
// or any other animation
}];
});
Thanks all for help!
You can combine animations, but hidden can just turn on/off.
Adjust alpha first (as you did, but not with hidden), and set hidden in completion block.
[UIView animateWithDuration:1
animations:^{
_myButton.alpha = hidden ? 0 : 1;
// or so:
[_myButtonConstraint setConstant:hidden ? -40 : 92];
[[self view] layoutIfNeeded];
} completion:^(BOOL finished) {
_myButton.hidden = hidden ? YES : NO;
}];

UIView doesn't animate

I want to animate the center of a UIView, and I did this in viewDidLoad:
_test.center = CGPointMake(100.0,100.0);
[UIView animateWithDuration:10.0
delay:5
options:UIViewAnimationOptionCurveLinear
animations:^{_test.center = CGPointMake(100.0,-100.0);}
completion:^(BOOL finished) {
}];
But when I run the code, the center of test view is already at 100,-100. Why it doesn't animate?
Move the code from your viewDidLoad to your viewDidAppear. In viewDidLoad, the UIView has been loaded, but it is not visually present yet.
I guess you are using auto constraints which prevent animating views the way you are doing.
In order to fix this issue try these steps:
First:
Move your code to - (void)viewDidLayoutSubviews.
Second:
Do these steps before and after doing any animation to your view:
- (void)viewDidLayoutSubviews{
_test.translatesAutoresizingMaskIntoConstraints = YES;
_test.center = CGPointMake(100.0,100.0);
[UIView animateWithDuration:10.0
delay:5
options:UIViewAnimationOptionCurveLinear
animations:^{_test.center = CGPointMake(100.0,-100.0);}
completion:^(BOOL finished) {
}];
[_test updateConstraints];
}

Fade between text in a UILabel with delay

I want to animate the text of a UILabel so that it shows one text for a couple of seconds and after that fades into a default text.
I'm currently using the following code:
-(void)tapOnBalance:(id)sender{
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hola!";
} completion:nil];
// Pause the function - act as a 'delay'
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hallo!";
} completion:nil];
}
This works, but the [NSRunLoop currentRunLoop] is pausing the entire app, blocking everything for 3 seconds.
How do I get rid of the block on the main thread and still get the same result?
A simple fade (not a cross-fade) can go like this:
// change a label's text after some delay by fading
// out, changing the text, then fading back in
- (void)fadeLabel:(UILabel *)label toText:(NSString *)toText completion:(void (^)(BOOL))completion {
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
label.text = toText;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
label.alpha = 1.0;
} completion:completion];
}];
}
// simpler signature that can be done on a perform
- (void)changeLabelText:(NSString *)toText {
[self fadeLabel:self.myLabel toText:toText completion:nil];
}
// set the label to something, then change it with a fade, then change it back
self.myLabel.text = #"text";
[self performSelector:#selector(changeLabelText:) withObject:#"hola!" afterDelay:4];
[self performSelector:#selector(changeLabelText:) withObject:#"text" afterDelay:8];
You could also nest the calls' completion blocks (and add a delay param) to do something similar without the performs. To do a cross-fade, apply a similar technique with two labels (that have the same frame) where one's alpha is zero and the other's alpha is one.

UITableView setEditing doesn't animate label constraint change

So, I have a custom tableview cell in tableview and when I set the editing mode on with the [self.tableView setEditing:YES animated:YES]; code.
It sets the editing mode but the problem is that my label on the cell just teleports to it's new location as it is pushed left when the reorder control shows itself. How can I animate the constraint change when the editing happens?
Picture of the my tableview cell:(The right constraint clearly increases when the editing goes on but it's not animated and I want it to be)
Edit: Here is my cell's setEditing.
I have tried to do it in many ways but the animation just doesn't work for some reason, the change happens instantly.
-(void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
if (editing) {
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationOptionCurveEaseIn
animations:^{
self.labelConstraint.constant = 100;
[self layoutIfNeeded];
}
completion:^(BOOL finished)
{
}];
}
}
Worked for me if I change constraint before animation block
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[self layoutIfNeeded];
self.containerLeftConstraint.constant = editing ? EditingIndent : 0.0f;
[UIView animateWithDuration:0.3
animations:^{
[self layoutIfNeeded];
}];
}

Resources