Strange UILabel and UIButton behavior - ios

I have a function called change shape:
- (void)changeShape {
NSLog(#"**** CHANGE SHAPE ****");
/* Set previous shape to current shape */
self.previousShape = self.currentShape;
/* Transition old shape out of view */
[UIView animateWithDuration:.4 animations:^(void){
[self.shapeButton setCenter:CGPointMake(self.view.frame.size.width+200, self.view.frame.size.height/2)];
} completion:^(BOOL finished){
if (finished) {
/* Set new current shape */
self.currentShape = [NSString stringWithFormat:#"%#",self.shapes[(arc4random() % [self.shapes count])]];
[self.shapeButton setImage:[UIImage imageNamed:self.currentShape] forState:UIControlStateNormal];
/* Transition new shape into view */
[self.shapeButton setCenter:CGPointMake(-200, self.view.frame.size.height/2)];
[UIView animateWithDuration:.3 animations:^(void){
[self.shapeButton setCenter:CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2)];
} completion:^(BOOL completed){
if (completed) {
[self changeScore];
}
}];
}
}];
}
- (void)changeScore {
self.score++;
[self.scoreLabel setText:[NSString stringWithFormat:#"%i",self.score]];
}
This function moves a UIButton off the screen, and then animates it back onto the screen. At the end of the final animation, I want to increment the score and change a UILabel on screen. For some reason, the image on the UIButton will only change after the UILabel has been changed. Does anybody know why this might be?

Call [self.shapeButton layoutIfNeeded] after you applied position change and new image.

Related

How to prevent 2 Animation on Object at the same time in Objective-C?

I have a UILabel and each time it touched, it'll scaled with CGAffineTransformMakeScale and animation, then back to real size with animation. Now if it touched before last animation ends, it'll scale the scaled object not the real size of main object and so it'll scaled more than it should to be scale. How to prevent this problem ? I want to second touch before last scale ending scale the main size of object.
Here is My Code :
(void)MyLabelTouched
{
[UIView animateWithDuration:.15 animations:^{
MyLabel.transform = CGAffineTransformMakeScale(1.5,1.5);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.15 animations:^{
MyLabel.transform = CGAffineTransformIdentity;
}];
}];
}
Try this
(void)MyLabelTouched
{
if(animRunning){return;}
animRunning = YES;
[ MyLabel.layer removeAllAnimations];
MyLabel.transform = CGAffineTransformIdentity;
[UIView animateWithDuration:.15 animations:^{
MyLabel.transform = CGAffineTransformMakeScale(1.5,1.5);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.15 animations:^{
MyLabel.transform = CGAffineTransformIdentity;
animRunning = NO;
}];
}];
}

UIView Animation happens faster than specified seconds

I have a view with an image shows some text in it.
I need to perform animation which reveals the character by character in the end the complete text has to be displayed.
I have a logo view in my interface, over that I have animate view. for animate view the Leading, trailing, top and bottom constraints are set based on the superView (logo view).
I have tried following code but the duration which I have specified is not working properly.
- (void) animateLogo {
[UIView animateWithDuration:10.0 animations:^{
NSLog(#"animation started");
if (self.animateViewLeadingConstraint.constant < 94) { //94 is the total width of the logo view
self.animateViewLeadingConstraint.constant = self.animateViewLeadingConstraint.constant + 1;
} else {
self.animateViewLeadingConstraint.constant = 0;
}
} completion:^(BOOL finished) {
NSLog(#"animation ended");
[self.animateView layoutIfNeeded];
[self animateLogo];
}];
}
I have attached the log for time duration
2016-08-01 17:55:27.317 sample[20361:481531] animation started
2016-08-01 17:55:27.318 sample[20361:481531] animation ended
2016-08-01 17:55:27.318 sample[20361:481531] animation started
2016-08-01 17:55:27.318 sample[20361:481531] animation ended
2016-08-01 17:55:27.318 sample[20361:481531] animation started
2016-08-01 17:55:27.319 sample[20361:481531] animation ended
2016-08-01 17:55:27.319 sample[20361:481531] animation started
2016-08-01 17:55:27.319 sample[20361:481531] animation ended
I am not sure what mistake I have made in above code or am I misunderstood the UIView Animation concept
Any help or hint would greatly appreciated.
See this answer: How do I animate constraint changes?
You should be calling layoutIfNeeded on the animated view's superview before your animation block, and in the animations: block itself. The first call makes sure any layout changes are applied. Assuming logoView is the superview of animateView:
- (void) animateLogo {
self.animateViewLeadingConstraint.constant = 0.0;
[self.logoView layoutIfNeeded];
[UIView animateWithDuration:10.0 animations:^{
NSLog(#"animation started");
self.animateViewLeadingConstraint.constant = 94.0;
[self.logoView layoutIfNeeded];
} completion:^(BOOL finished) {
NSLog(#"animation ended");
}];
}
Finally, I have got the solution based on #stevekohls comments
- (void) animateLogo {
self.animateViewLeadingConstraint.constant = 0;
[UIView animateWithDuration:5.0f animations:^{
self.animateViewLeadingConstraint.constant = 94.0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5f animations:^{
self.animateView.alpha = 0;
} completion:^(BOOL finished) {
self.animateViewLeadingConstraint.constant = 0;
[self.view layoutIfNeeded];
self.animateView.alpha = 1.0f;
[self animateLogo];
}];
}];
}

Show scaled UIViewController in another UIViewController

I want to display a scaled down "preview" of another ViewController in another ViewController. Is this possible? No interaction are needed so it can basically be a screenshot, but scaled down. I can be solved by manually take a screenshot and save it as an image, but the ViewController contains a lot of localizations and are constantly updated, so if this can be done programatically.
https://www.dropbox.com/s/kd5vinrym1k7afk/Screenshot%202014-05-13%2015.20.17.png
Is this possible?
Edit: the sub view is stored in a storyboard
Edit: This is how I've solved it:
//Load the viewcontroller and view
previewViewController = [self.storyboard instantiateViewControllerWithIdentifier:[PLACEHOLDER_VIEWCONTROLLER_NAMES objectAtIndex:self.identifier]];
[self addChildViewController:previewViewController];
[self.placeholderView.superview addSubview:previewViewController.view];
previewViewController.view.transform = CGAffineTransformMakeScale(scale*2, scale*2);
CGPoint center = self.placeholderView.center;
center.y += 25;
previewViewController.view.center = center;
Use the viewController.view and then scale it down like:
viewController.view.transform = CGAffineTransformMakeScale(0.5, 0.5);
Add your another view controller view as subview to first viewcontroller
[UIView animateWithDuration:2.0f animations:^{
InnerView.userInteractionEnabled = NO;
//Always starts from original scale
InnerView.transform = CGAffineTransformMakeScale(0.5, 0.5);
//Incremental scale
//InnerView.transform = CGAffineTransformScale(InnerView.transform, 0.5, 0.5);
} completion:^(BOOL finished) {
NSLog(#"in Half size");
}];
[UIView animateWithDuration:2.0f animations:^{
InnerView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
InnerView.userInteractionEnabled = YES;
NSLog(#"Normal size");
}];

iOS7 view transition effect zoomed in

Hi maybe this is a duplicated question and I just don't know the keyword to describe my question, if this is the case please point out.
I'm currently implementing a transition between two view, as the second view shows, it should looked like it's zoomed into the screen from outside, kind of fall on the screen. My idea is to zoom the second view 9 * original size and place the origin to -original_width, -original_height, and set alpha to 0. At the end I set alpha to 1 and show the original size.
so the following code is not working, the subviews are not resized. Could anyone tell me what I miss here or better show me some API which do the task?
[toVC.view setFrame:CGRectMake(0-fromVC.view.frame.size.width, 0-screenRect.size.height, fromVC.view.frame.size.width*3, fromVC.view.frame.size.height*3)];
for (UIView* view in toVC.view.subviews) {
CGRect frame = view.frame;
[view setFrame:CGRectMake(frame.origin.x*3, frame.origin.y*3, frame.size.width*3, frame.size.height*3)];
}
[toVC.view layoutIfNeeded];
[toVC.view setAlpha:0.1];
[UIView animateWithDuration:duration*5
animations:^{
[toVC.view setAlpha:1.0];
[toVC.view setFrame:CGRectMake(0, 0, fromVC.view.frame.size.width, fromVC.view.frame.size.height)];
for (UIView* view in toVC.view.subviews) {
CGRect frame = view.frame;
[view setFrame:CGRectMake(frame.origin.x/3, frame.origin.y/3, frame.size.width/3, frame.size.height/3)];
}
}
completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
You could just set the view transform prior and after the transition:
CGAffineTransform scaleTransform = CGAffineTransformIdentity;
scaleTransform = CGAffineTransformScale(rotationTransform, 9., 9.);
view.transform = scaleTransform;
view.alpha = 0;
[UIView animateWithDuration:duration*5
animations:^{
view.transform = CGAffineTransformIdentity;
view.alpha = 1.;
}
}
completion:^(BOOL finished) {
}];

Animating multiple UIViews simultaneously

I have three UIButton objects visually stacked one on top of another. When a user taps on a button the buttons below should move down a certain distance. I am using the following animation block:
// Assuming button 1 was clicked...
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^(void) {
self.button2.frame = CGRectOffset(self.button2.frame, 0.0f, 20.0f);
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
If I increase the animation duration, e.g. from 0.25 to 0.75, the buttons do not remain together but they begin to move in different time intervals. I have tried with Core Animation methods, by grouping animations and other stuff, but haven't found any solution yet.
Do you have any ideas? Right now I'm keeping the duration in 0.25 until I come up with something.
One solution is to set both button2 and button3 as a subview in another UIView and animate the view instead of each of the buttons separately. Whether this is a good approach depends on what you are trying to accomplish with the stacked button.
EDIT:
Since my experience is that animations within a block are in sync, I implemented the code as show below. I tried numerous values for the animation duration (0.15, 0.25, 0.75, 1.25) and button2 and button3 are moving in sync (and since button2 is on top of button3, I can't actually see button3 at all, until I tap on button2, which causes button3 to move from underneath button 3).
- (IBAction)button1Tapped:(id)sender {
NSLog(#"button1Tapped...");
[UIView animateWithDuration:0.75f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^(void) {
self.button2.frame = CGRectOffset(self.button2.frame, 0.0f, 20.0f);
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
}
- (IBAction)button2Tapped:(id)sender {
NSLog(#"button2Tapped...");
[UIView animateWithDuration:0.75f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^(void) {
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
}
- (IBAction)button3Tapped:(id)sender {
NSLog(#"button3Tapped...");
}

Resources