I have an app using a UITabBarController, and I have another view that needs to slide up from behind the tab bar controls, but in front of the tab bar's content. If that's not clear, imagine an advertisement sliding up in a tabbed app that appears in front of everything except for the tab bar buttons.
So far I have code that looks something like this, but I'm willing to change it if there's a better way to do this...
tabBarController.viewControllers = [NSArray arrayWithObjects:locationNavController, emergencyNavController, finderNavController, newsNavController, nil];
aboutView = [[AboutView alloc] initWithFrame:CGRectMake(0, window.frame.size.height - tabBarController.tabBar.frame.size.height - 37 ,
320, window.frame.size.height - tabBarController.tabBar.frame.size.height)];
[window addSubview:tabBarController.view]; // adds the tab bar's view property to the window
[window addSubview:aboutView]; // this is the view that slides in
[window makeKeyAndVisible];
Currently aboutView is a subclass of UIView and sits at its starting position at the bottom, but it hides the tabBarController. How can I change this to let the tabs be on top, but still have the aboutView in front of the other content?
You need to add the aboutView as a subview of the view in the currently active view controller in the UITableBarController. You can access that view via the selectedViewController property.
You can add code to your aboutView implementation to animate the view when it appears.
I do something like this in a popup view that I want to appear under the tab bar controls. You can add some code to the didMoveToSuperview message on the aboutView implementation:
- (void)didMoveToSuperview
{
CGRect currentFrame = self.frame;
// animate the frame ... this just moves the view up a 10 pixels. You will want to
// slide the view all the way to the top
CGRect targetFrame = CGRectOffset(currentFrame, 0, -10);
// start the animation block and set the offset
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5]; // animation duration in seconds
[UIView setAnimationDelegate:self];
self.frame = targetFrame;
[UIView commitAnimations];
}
So when your aboutView is added to the selected view controller's view, it automatically animates up.
Related
Is it possible to make a custom push view controller animation like the image? The basic idea is to push the view normally, but without moving the current view (that calls the pushViewController...).
Sure, that can be done. I made a project where I did it like this:
-(void)slideInController:(RDSlideController *) next {
next.presentingVC = self;
next.view.frame = CGRectMake(self.view.frame.origin.x + 320, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
[self.view.window addSubview:next.view];
[UIView animateWithDuration:slideTime animations:^{
next.view.frame = self.view.frame;
} completion:^(BOOL finished) {
self.view.window.rootViewController = next;
}];
}
The view controllers that I slid in were subclasses of RDSlideController (so I could have the presentingVC property and some other things), but that's not really necessary. Basically, you just instantiate the new controller, set its view's frame to be off screen to the right, add that view to the window, then animate the frame to the current view's frame. Finally, you switch out the view controllers so that the new one is now the root view controller of the window.
We can achieve this by adding subview and animating view which we want to add.
When we are adding give animation to move next view from left edge to right edge. And vise versa with removing view.
I am switching between views using view animations, its works but I am having an issue with interface orientation.
I have two views on window.
authenticationViewCont
mainViewCont
Both have a button, when button clicked on authenticationViewCont I remove it and show mainViewCont and vice versa.
Once I addSubview the authenticationViewCont.view and putting device in portrait mode then removed it by removeFromSuperview then I change device orientation to landscape in my hands then again addSubview the authenticationViewCont. It first displayed animating in portrait and changing orientation after animation.
-(void)mainToAuthentication {
CGRect originalFrame = authenticationViewCont.view.frame;
CGRect modifiedFrame = originalFrame;
modifiedFrame.origin.y = originalFrame.size.height;
// made view out from screen
authenticationViewCont.view.frame = modifiedFrame;
// add sub view on top of other views
[self.window addSubview:authenticationViewCont.view];
// transiting view from bottom to center of screen
[UIView animateWithDuration:0.5
animations:^{ authenticationViewCont.view.frame = originalFrame; }
completion:^(BOOL finished){ mainViewCont.view removeFromSuperview; }];
}
-(void)authenticationToMain {
CGRect originalFrame = mainViewCont.view.frame;
CGRect modifiedFrame = originalFrame;
modifiedFrame.origin.y = -originalFrame.size.height;
// made view out from screen
mainViewCont.view.frame = modifiedFrame;
// add sub view on top of other views
[self.window addSubview:mainViewCont.view];
// transiting view from top to center of screen
[UIView animateWithDuration:0.5
animations:^{ mainViewCont.view.frame = originalFrame; }
completion:^(BOOL finished){ authenticationViewCont.view removeFromSuperview; }];
}
How can I make it to display in current interface orientation instead of old interface orientation in which it was removeFromSuperview?
I think the problem here is that you are initialliy adding one viewController.view ontop of another then removing the old one.
The problem with window only expects one rootViewController. So the window will only pass rotation events onto the first controller. Meaning your second viewController will not get rotation events until the completionsBlock gets called.
The way I would get around this is to put this switching code inside of a rootViewController that is on the window. Then whenever you do your switching you can pass in the current rotation of the rootviewController and have your authenticationViewController set itself up based on the orientation you pass it
At some part of my code I am using this line
[[self navigationController] pushViewController:myController animated:YES];
This works perfectly and pushes a view, coming from bottom, over the current one, covering the last one completely.
I am wondering if there's a way to make it cover just part of screen. Let's say, just the half bottom of the screen...
Is it possible? I have tried to change the controller's view frame but the size kept coming full screen.
thanks.
Instead of using a new view controller modally, you could add a new subview to your existing view, using the same view controller.
You can do the "slide in" animation with something like:
[self.view addSubview: newView];
CGRect endFrame = newView.frame; // destination for "slide in" animation
CGRect startFrame = endFrame; // offscreen source
// new view starts off bottom of screen
startFrame.origin.y += self.view.frame.size.height;
self.newImageView.frame = startFrame;
// start the slide up animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
newView.frame = endFrame; // slide in
[UIView commitAnimations];
You can do it in a limited fashion with a modal view controller. Check out the presentation options available under UIModalPresentationStyle in the apple docs.
You will need to be on iOS 3.2 or above to do a modal view controller.
Hey I have a view that has a button that when pressed should modally present a UIDatePicker. I have the picker showing up properly, but because it is on its own UIView, it is full height, and looks funny. All I want is to get a really quick date input from the user, more like a UIActionSheet than a UIView.
How can I make the UIPicker slide up modally only halfway and have some actions on a toolbar, like done etc?
Thanks
You could put it on another UIView which has a transparent background, or more simply, don't use presentModalViewController, but write your own routine to show it in the current view.
// Untested code:
// put this in your current UIViewController (the one where you were going to call presentModalViewController:)
- (void)showPicker:(UIPickerView *) picker{
CGRect startFrame = picker.frame;
CGRect endFrame = picker.frame;
// Set the start position to below the bottom of the visible frame:
startFrame.origin.y = self.view.frame.size.height;
// Set the end position to slid up by the height of the view, so it will just fit:
endFrame.origin.y = startFrame.origin.y - endFrame.size.height;
picker.frame = startFrame;
[self.view addSubView:picker];
[UIView beginAnimations]
picker.frame = endFrame;
[UIView commitAnimations];
}
You would of course need to add all the necessary code to keep a pointer to the picker and keep track of when to show and get rid of it.
In my test application (im learning) i have 2 view controllers.
on the first view i have button "go to second view".
what i want to do :
when user click the "go to second view", the first view move left and go out of the screen
and the second view will appear from the right and replace the first view.
now, this animation is happen when pushing and poping with navigate controller.
my question :
how can i do the same animation, without nav controller ?
You can add a view off screen to the right, and then you can animate it to a new frame on-screen. Another common use for this method is to animate modal menu views from the bottom. You can also animate other properties of the view, such as the alpha value to make a view disappear/reappear.
// the size of the screen minus the Status Bar
#define SCREEN_FRAME [[UIScreen mainScreen] applicationFrame]
// add the full-screen view offscreen to the right
CGRect frame = CGRectMake(SCREEN_FRAME.size.width,
SCREEN_FRAME.origin.y,
SCREEN_FRAME.size.width,
SCREEN_FRAME.size.height);
UIView *view = [[[UIView alloc]initWithFrame:frame]autorelease];
[self.view addSubview view];
// this is the frame the view will end on after the animation
CGRect newFrame = CGRectMake(SCREEN_FRAME.origin.x,
SCREEN_FRAME.origin.y,
SCREEN_FRAME.size.width,
SCREEN_FRAME.size.height);
// animate the transition
[UIView beginAnimations:nil context: nil];
[UIView setAnimationDuration: .5];
view.frame = newFrame;
[UIView commitAnimations];