1

Im trying to make a custom view where one of it's elements(a UILabel) has animation that when a button of the custom view is tapped the label should expand and then contract. The first part of the animation happens correctly but not the second. Im using this method.

[UIView animateWithDuration:1.3 animations:^{
    CGRect frame = CGRectMake(50, 15, 140, 20);
    [labelFav setFrame:frame];
} completion:^(BOOL finished) {
    //[labelFav setHidden:YES];
    [UIView animateWithDuration:1.3 animations:^{
        CGRect frame = CGRectMake(50, 15, 0, 20);
        [labelFav setFrame:frame];
    }];

}];

I believe it's a problem with how the methods Refresh and LayoutSubviews are implemented. I did it following this tutorial, ray wenderlinch

The problem comes when after the first animation is called, LayoutSubviews is called, so all the items are set to the initial position, and when the first animation is finished the second one starts but the items are set to the original state, so I believe the animation doesnt happen because there's been a change between animations.

I would like to know how to implement this correctly, can you lend me a hand?

Thanks.

PS: This is a second question about the same problem but with a different angle.my previous question

[UPDATE]

This is my code for LayoutSubviews:

- (void)layoutSubviews {
[super layoutSubviews];

if(_idEvent == 0) return;

_buttonFav = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 40, 40)];
[_buttonFav setImage:[UIImage imageNamed:@"fav.png"] forState:UIControlStateNormal];
[_buttonFav addTarget:self action:@selector(pressedFavButton:) forControlEvents:UIControlEventTouchDown];

_labelButton = [[UILabel alloc]initWithFrame:CGRectMake(0, 45, 0, 20)];
_labelButton.text = @"LABEL";

[self addSubview:_labelButton];
[self addSubview:_buttonFav];

}

Which is called right before the second animation. My refresh method is:

- (void)refresh {
if(selected){

    [_buttonFav setImage:[UIImage imageNamed:@"fav_sel.png"] forState:UIControlStateNormal];
}
else{
    [_buttonFav setImage:[UIImage imageNamed:@"fav.png"] forState:UIControlStateNormal];
}

}

Where I just set the image for the button depending on an attribute that lets me know if the button was tapped.

Community
  • 1
  • 1
subharb
  • 3,374
  • 8
  • 41
  • 72

3 Answers3

1

use SetTransform and CGAffineTransform

try this out

[UIView animateWithDuration:1.3 animations:^{

    [labelFav setTransform:CGAffineTransformMakeScale(0.5,0.5)];
} completion:^(BOOL finished) {

    [UIView animateWithDuration:1.3 animations:^{

        [labelFav setTransform:CGAffineTransformMakeScale(1.0,1.0)];
    }];

}];
Raon
  • 1,266
  • 3
  • 12
  • 25
1

I do, how to make an animation with Auto-layout then? With the new XCode you dont have an a option to disable it.

Add a width constraint to a label. Then create IBOutlet to this constraint in your implementation file (see the section 3. here, if you don't know how to do that), let's say something like:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *buttonWidthConstraint;

Then you can animate it this way:

[UIView animateWithDuration:1.3 animations:^{
    self.buttonWidthConstraint.constant = 140;
    [self.view layoutIfNeeded];
} completion:^(BOOL finished) {

    [UIView animateWithDuration:1.3 animations:^{
        self.buttonWidthConstraint.constant = 0;
        [self.view layoutIfNeeded];
    }];

}];
Arek Holko
  • 8,966
  • 4
  • 28
  • 46
  • I don't beleive it's a Auto-layout issue, since I tried to change the animation to a "fade in" "fade out" animation and event though it does fadout it's not animated, I think it's because LayoutSubview is called before the second layout is called. I will show you the code for LayoutSubviews – subharb Oct 14 '13 at 13:23
  • It is an Auto Layout issue. You shouldn't set frames manually when using Auto Layout. Just google: auto layout change frame. [Here's a video of how my code works](https://www.dropbox.com/s/dppsmr6vu4nju5g/auto_layout_resize.mov) (button title is hiding, but it's an another issue :)). – Arek Holko Oct 14 '13 at 13:28
  • I will try that, but im not setting my UIView by Interface Builder but by code, how do I set that NSLayoutConstraint by code? Thanks for your help – subharb Oct 14 '13 at 13:43
  • 1
    `[NSLayoutConstraint constraintWithItem:self.label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:40];` – Arek Holko Oct 14 '13 at 13:45
  • Where should I place this? I placed it in LayoutSubviews labelConstraint = [NSLayoutConstraint constraintWithItem:_labelButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:40]; [self addConstraint:labelConstraint]; After I add it LayoutSubview is called again, so an infinite loop happens. – subharb Oct 14 '13 at 14:50
  • See this answer: http://stackoverflow.com/a/15895048/1990236 You basically have to read Auto Layout documentation and watch Auto Layout related lectures from WWDC 2012 & 2013. Unfortunately, there isn't any shortcut to gaining an understanding. – Arek Holko Oct 14 '13 at 14:55
0

Try to encapsulate the UILabel into a UIView and animate that view.

UIView *auxView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
[auxView addSubview:labelFav];
[UIView animateWithDuration:1.3 animations:^{
    CGRect frame = CGRectMake(50, 15, 140, 20);
    [auxView setFrame:frame];
} completion:^(BOOL finished) {
    //[labelFav setHidden:YES];
        [UIView animateWithDuration:1.3 animations:^{
            CGRect frame = CGRectMake(50, 15, 10, 20);
            [auxView setFrame:frame];
        }];
}];