I am attempting to switch views (XIB's) while fading through black. I have been doing this using UIView animations and I want to keep it that way. The problem is that whenever I switch views I am not fading through black, its more of a fade directly to the next XIB.
How would I properly do this?
Here is my code (self.view = view1.view in my case, but maybe I shouldn't do that):
[self.view setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]];
[UIView animateWithDuration:0.4
animations:^{
[view1.view setAlpha:0];
}
completion:^(BOOL finished){
[self.view.superview addSubview:view2.view];
[view2.view setAlpha:0];
[view2.view setFrame:CGRectMake(0, 0, 320, 480)];
[UIView animateWithDuration:0.4
animations:^{
[view2.view setAlpha:1];
}
completion:^(BOOL finished){
[view1.view removeFromSuperview];
}];
Thanks!
I think your problem is that the background color of self.view is part of that view. When you fade the view, it fades the background too.
Instead, you should put a view that you keep on the screen all the time, that's empty and has a black background color, and is behind view1 or view2.
Related
I am trying to make a slide out notification bar for when the app receives a notification and the app is currently open and in the foreground. I got this working with a custom UIView (actually it's a UIButton) and an animation. For some reason though it won't register a press when I tap on it. It won't call the selector method. Code is below:
-(void)appOpenPush {
//get string
NSLog(#"got a push while app was open");
AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *pushString = appDelegate.pushString;
//play sound
AudioServicesPlaySystemSound(MessageSound);
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
//note I am actually using a button here
UIButton *pushView =[[UIButton alloc] initWithFrame:CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75)];
pushView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
[pushView addTarget:self action:#selector(pushSlidePress) forControlEvents:UIControlEventTouchUpInside];
//set image
UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon120.png"]];
logo.frame=CGRectMake(5, 20, 35, 35);
logo.layer.cornerRadius=8;
logo.clipsToBounds=YES;
[pushView addSubview:logo];
UILabel *pushLabel = [[UILabel alloc] initWithFrame:CGRectMake(48, 34, 0, 0)];
pushLabel.text=pushString;
pushLabel.font=[UIFont systemFontOfSize:13];
[pushLabel sizeToFit];
pushLabel.textColor=[UIColor whiteColor];
[pushView addSubview:pushLabel];
//animate
UIWindow* currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:pushView];
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
pushView.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 delay:2.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
pushView.frame = CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[pushView removeFromSuperview];
}];
}];
}
Could anyone give me a pointer to why this isn't working? Is it because I am adding the UIButton to the main window? Any tips would be really helpful. thanks!
You have to add UIViewAnimationOptionAllowUserInteraction as an option to both of your animation blocks.
As per the documentation :
"Allow the user to interact with views while they are being animated."
Try this to avoid logo and pushLabel receive touches events:
logo.userInteractionEnabled = NO;
pushLabel.userInteractionEnabled = NO;
So it turns out you can't simply detect a press if the button is moving. I tested this by just adding the frame setup without it animating and it registered the press, when animation is turned on it doesn't. Seems that UIButton doesn't have tracking built in. I did come up with a quick fix. I just made a button the same size as the total animation area (i.e. the size of my slide out bar) and added that to the currentWindow on top of the animation frame. So it's just a clear invisible button on top of the animation but it's not moving itself. i.e:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0,[[UIScreen mainScreen]bounds].size.width , 75)];
[button addTarget:self action:#selector(pushSlidePress) forControlEvents:UIControlEventTouchUpInside];
[currentWindow addSubview:button];
[UIView animateWithDuration:0.4 delay:0.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction) animations:^{
pushView.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 delay:2.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction) animations:^{
pushView.frame = CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[pushView removeFromSuperview];
[button removeFromSuperview];
}];
}];
Obviously you are covering an area of the screen that might block other things being pressed, but it depends on your setup. The animation is quick and I only have one button that the notification bar will block and it's too quick to notice. Hopefully this will be helpful to someone else trying to achieve a similar thing. Thanks for your help guys.
I use the following lines of code:
[UIView animateWithDuration:0.50
animations:^{ itemView.transform = CGAffineTransformIdentity; }
completion:^(BOOL finished) { if (finished) [itemView removeFromSuperview]; }];
The animation does nothing. If I take the removeFromSuperview out of the completion block, it doesn't work either, I guess because the view is removed before it completes. So, either way, the appearance is the same - no animation.
I'll appreciate any suggestion or workaround on this.
Are you setting the transform correctly? The below is an example of scaling a UIView to zero area and then removing it from the superview.
UIView *itemView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 200, 200)];
[itemView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:itemView];
CGAffineTransform trans = CGAffineTransformScale(self.view.transform, 0, 0);
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
itemView.transform = trans;
} completion:^(BOOL finished) {
[itemView removeFromSuperview];
}];
I'm making a custom segue that fades to black, swaps out the view controller and then fades back to transparent. Unfortunately, I can't seem to get it to do that. Here's the code:
- (void)perform {
UIView *overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [self.sourceViewController navigationController].view.frame.size.width, [self.sourceViewController navigationController].view.frame.size.height)];
[overlay setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.0]];
[[self.sourceViewController navigationController].view addSubview:overlay];
[UIView animateWithDuration:2.0 delay:0.0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{
[overlay setAlpha:1.0];
}completion:^(BOOL finished) {
[[self.sourceViewController navigationController] pushViewController:[self destinationViewController] animated:NO];
[UIView animateWithDuration:2.0 delay:0.0 options:(UIViewAnimationOptionCurveEaseIn) animations:^{
[overlay setAlpha:0.0];
}completion:^(BOOL finished) {
[overlay removeFromSuperview];
NSLog(#"Done!");
}];
}];
}
So, what I've done is add a UIView to the navigation controller that has a black background and an alpha of 0. Then, I do an animation to change the alpha to 1, push the destination view controller onto the navigation controller, and then animate back to clear. When I do this, nothing happens. It just drops the destination view controller onto the navigation controller without any kind of animation.
Oddly, if I start with an alpha of 1 and animate to 0 and then back to 1, it works (but it isn't what I want).
I'm thinking that there's some optimization happening that excludes my clear UIView and so changing the transparency is meaningless.
What happens if you do this?
...
[overlay setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0]];
[overlay setAlpha:0.0];
[[self.sourceViewController navigationController].view addSubview:overlay];
...
I wan't to animate a view that's shaped as an arrow, and I want it to animate from left to right, left to right and so on..
This code below is not working, I'm guessing I need a path, but don't know how to do that in a UIView block animation.
[UIView animateWithDuration:.5 delay:0 options:UIViewAnimationOptionRepeat animations:^{
controller.view.frame = frame1;
controller.view.frame = frame2;
} completion:^(BOOL finished) {
}];
You can use UIViewAnimationOptionAutoreverse option, try the code below:
UIView * testView = [[UIView alloc] initWithFrame:CGRectMake(20.0f, 100.0f, 300.0f, 200.0f)];
[testView setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:testView];
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
[testView setFrame:CGRectMake(0.0f, 100.0f, 300.0f, 200.0f)];
}
completion:nil];
[testView release];
It'll repeat move from right to left, left to right, ... smoothly.
Assuming that frame1 is the starting position and frame2 is the end position before repeat.
The problem is that the animation is calculated at the end of the runloop therefore the frame1 is ignored and the view is simply moved to frame2. If you move the setting of frame1 outside of the block then it should work fine. If you want the animation to play back and forward you will need to make it autoreverse with UIViewAnimationOptionAutoreverse
I try to scale an UIView. And there is a white background outside of an UIview. How I can take it out to see just background view? Thanks!
self.view.transform = CGAffineTransformMakeScale(.5,.5);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.9];
self.view.transform = CGAffineTransformMakeScale(1,1);
[UIView commitAnimations];
Try setting the background color of the view you need to be transparent to [UIColor clearColor]:
myView.backgroundColor = [UIColor clearColor];