Present Modal View with Animation Effect - iphone

In my iPhone App I need to display a modal view with transparent background and it should appear with animation like it is appearing from center of view and its size is increasing.
similar like "drawing something" iPhone App when we click on settings button.
How do I do this?

You can do one of 4 following transition styles:
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
viewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:viewController animated:YES];
If you want something that is not included in these defaults you are going to have to build your own custom animation for presenting the modal view. Like the following but obviously for the style you want.
UIModalTransitionStyle horizontal movement

Let's say you have a viewController thats called aScoreSheet that you want to present. Try to define this method in the view controller that's going to do the presenting.
-(void) presentTransparentModalViewController: (ScoreSheet *) aViewController
{
scoreSheet = aViewController;
UIView *view = aViewController.view;
view.opaque = NO;
[view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIView *each = obj;
each.opaque = NO;
}];
[self.view addSubview:view];
view.center = CGPointMake(160, 800); //for iPhone
[UIView animateWithDuration:0.9 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
view.center = CGPointMake(160, 240);
} completion:^(BOOL finished) {
self.view.userInteractionEnabled=YES;
}];
}
and then to dismiss the controller:
-(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{
if (animated) {
[UIView animateWithDuration:0.4
animations:^{
scoreSheet.view.center = CGPointMake(scoreSheet.view.center.x, scoreSheet.view.center.y + 480);
} completion:^(BOOL finished) {
[scoreSheet.view removeFromSuperview];
scoreSheet = nil;
}];
}
}

Not a full answer, but maybe you can take a look at this open source library:
https://github.com/Split82/HMGLTransitions
It has some custom modal transitions, maybe not exactly the one you are looking for, but you can easily add your transition by subclassing HMGLTransition.
Hope this helps

Related

Scrollview didn't scrolling after dismissViewControllerAnimated

I'm calling a view controller from my mainScreen with the following code:
VisualizarFotoViewController *visualizarFoto = [self.storyboard instantiateViewControllerWithIdentifier:#"VisualizarFoto"];
[self presentViewController:visualizarFoto animated:NO completion:^{
[UIImageView animateWithDuration:0.5 animations:^{
visualizarFoto.visualizarFoto.contentMode = UIViewContentModeScaleAspectFit;
visualizarFoto.visualizarFoto.image = _fotoPrincipal.image;
visualizarFoto.viewPrincipal.alpha = 1;
visualizarFoto.telaOrigem = 2;
}];
}];
To come back to the mainScreen I dismiss the view controller with the following code:
[UIImageView animateWithDuration:0.2 animations:^{
_viewPrincipal.alpha = 0;
} completion:^(BOOL finished) {
[self dismissViewControllerAnimated:NO completion:nil];
}];
My issue is that when I come back to the mainScreen, my scrollview doesn't answer to any scrolling gesture. I've tried to use [_scrollView becomeFirstResponder] in viewDidAppear section but with no success.
Do you have any hint to solve this please?
Thanks
If is there someone looking for an answer, this is what I did to solve this issue:
- (void)viewDidLayoutSubviews {
// Define the scrollview size accordingly with the number of pages
[_scrollView setFrame:CGRectMake(0, 43, 320, 450)];
[_scrollView setContentSize:CGSizeMake(320 * 3, 450)];
}

How to zoom image to fullscreen mode?

I have paging UIScrollView with images. I want to implement animated zooming of image to fullscreen on some gesture. And another animation to zoom image back to scroll view. Like in Photos app on iPad or like videos in Safari.
Of course it would not be UIImageView. It would be some wrapper class with image inside. The main question is how to present fullscreen view. Is it must be modal view or not.
Any help is appreciated.
Check on touching the image
if it is small convert into full size.
if it is large convert into small size.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (isLarge) [self makeSmall];
else [self makeFull];
}
- (void)makeFull {
[[self superview] bringSubviewToFront:self];
isLarge = YES;
CGRect largeFrame = [self superview].bounds;
original = self.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[self setFrame:largeFrame];
[internal setFrame:self.bounds];
[UIView commitAnimations];
}
- (void)makeSmall {
isLarge = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[self setFrame:original];
[internal setFrame:self.bounds];
[UIView commitAnimations];
}
I found a solution to this that involves both gesture recognizers and animated transitions. You remove the scrollview and add the fullscreen image. Then reverse that to return to the just the scrollview.
Use the frame of the window to determine size for the new UIImage.
The types of gesture recognizers can be adjusted to suit your needs!
-(void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice:)];
tapTwice.numberOfTapsRequired = 2;
[self.imageView addGestureRecognizer:tapTwice];
}
- (void)tapOnce:(id)tapOnce {
[UIView transitionWithView:self.view
duration:0.7
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.fullScreenImage removeFromSuperview];
}
completion:nil];
}
- (void)tapTwice:(id)tapTwice {
if(self.fullScreenImage == nil){
self.fullScreenImage = [[UIImageView alloc] initWithFrame:self.view.window.frame];
UITapGestureRecognizer *tapOnce = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnce:)];
tapOnce.numberOfTapsRequired = 1;
[tapOnce requireGestureRecognizerToFail:tapTwice];
[self.fullScreenImage addGestureRecognizer:tapOnce];
[self.fullScreenImage setUserInteractionEnabled:YES];
//self.fullScreenImage = [load your image here]
}
[UIView transitionWithView:self.view.window
duration:0.7
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.view.window addSubview:self.fullScreenImage];
}
completion:nil];
}
Download this sample for Image gallery sample code and get through it. It would definitely helps you to understand how to implement your idea.
Like below you can use for zooming the image view.
UIView * viewForScroll;
UIImageView *imgviewForScroll;
UIScrollView *scrollToRead = [[UIScrollViewalloc]initWithFrame:CGRectMake(175, 5, 300, 311)];
scrollToRead.backgroundColor = [UIColordarkGrayColor];
scrollToRead.showsHorizontalScrollIndicator = YES;
scrollToRead.delegate = self;
[scrollToRead setContentSize:CGRectMake(0, 0, 300, 400).size];
scrollToRead.maximumZoomScale = 2;
scrollToRead.minimumZoomScale = 1;
[self.view addSubview:scrollToRead];
[scrollToRead release];
viewForScroll = [[UIViewalloc]initWithFrame:CGRectMake(0,0,300,400)];
[scrollToRead addSubview:viewForScroll];
[viewForScroll release];
imgviewForScroll = [[UIImageViewalloc]initWithFrame:CGRectMake(0,0,300,400)];
imgviewForScroll.image = [UIImageimageWithContentsOfFile:[arrayComicContentobjectAtIndex:0]];
[viewForScroll addSubview:imgviewForScroll];
[imgviewForScroll release];
//=========UIScrollView Delegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return viewForScroll;
}
Like to know if you need any further clarifications

Unclear on how to properly remove a UIViewController from another UIViewController

thank you for your time, (As a side note, this question pertains mostly to iOS 4.2.3, I am aware some of these issues could be resolved with moving the code base to iOS 5, however we would like to release this app for phones running iOS 4 as well.)
I have a "MasterViewController" that is in charge of calling and dismising other UIVIewControllers.
First we trigger a new one:
In MasterViewController.m
-(IBAction)triggerPrime:(id)sender {
[self clearHomeScreen];
NSUInteger randomNumber = arc4random() % 2;
if (randomNumber == 0) {
self.flashTextViewIsDisplayed = NO;
ThinkOfViewController *thinkVC = [[ThinkOfViewController alloc] initWithNibName:#"ThinkOfViewController" bundle:nil];
self.thinkOfViewController = thinkVC;
[thinkVC release];
self.picturePrimeViewIsDisplayed = YES;
[self.view addSubview:self.thinkOfViewController.view];
}
else if (randomNumber == 1) {
self.picturePrimeViewIsDisplayed = NO;
FlashTextPrimeViewController *flashVC = [[FlashTextPrimeViewController alloc] initWithNibName:#"FlashTextPrimeViewController" bundle:nil];
self.flashTextPrimeViewController = flashVC;
[flashVC release];
self.flashTextViewIsDisplayed = YES;
[self.view addSubview:self.flashTextPrimeViewController.view];
}
Let's say that our randomNumber is 0, and it adds the ThinkOfViewController to the subview, (This is a very basic screen, it essentially displays some text with some assets animating:
In ThinkOfViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.thinkOf.alpha = 0.0;
self.dot1.alpha = 0.0;
self.dot2.alpha = 0.0;
self.dot3.alpha = 0.0;
self.background.alpha = 0.0;
[self animateViews];
}
-(void)animateViews {
[UIView animateWithDuration:0.25 animations:^ {
self.background.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.75 delay:0.00 options:UIViewAnimationCurveEaseIn animations:^ {
self.thinkOf.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot1.alpha = 1.0;
}completion:^(BOOL finsihed) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot2.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.20 delay:0.60 options:UIViewAnimationCurveEaseIn animations:^ {
self.dot3.alpha = 1.0;
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.50 delay:0.60 options:UIViewAnimationCurveEaseInOut animations:^{
self.view.alpha = 0.0;
}completion:^(BOOL finished) {
NSLog(#"all animations done");
[[NSNotificationCenter defaultCenter] postNotificationName:#"removeThinkOfView" object:nil];
}];
}];
}];
}];
}];
}];
}
As you can see, once the animation sequence is finished, I post a notification to NSNotificationCenter (which resides in the MasterViewController) to remove this viewController.
In MasterViewController.m
-(void)removeThinkOfView {
[self.thinkOfViewController.view removeFromSuperview];
[self showPicturePrime];
}
-(void)showPicturePrime {
if (self.picturePrimeViewController == nil) {
PicturePrimeViewController *pVC = [[PicturePrimeViewController alloc] initWithNibName:#"PicturePrimeViewController" bundle:nil];
self.picturePrimeViewController = pVC;
[pVC release];
[self.view addSubview:self.picturePrimeViewController.view];
}
else {
PicturePrimeViewController *pVC = [[PicturePrimeViewController alloc] initWithNibName:#"PicturePrimeViewController" bundle:nil];
self.picturePrimeViewController = pVC;
[pVC release];
[self.view addSubview:self.picturePrimeViewController.view];
}
}
Now a picturePrimeViewController is loaded and added to the subview, everything loads and displays fine. Now, to get a new prime, you simple swipe for a new one.
In picturePrimeViewController.m
-(void)handleSwipeFromRight:(UISwipeGestureRecognizer *)gestureRecognizer {
if (!transitioning) {
[self performTransition];
}
}
-(void)performTransition {
CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
transitioning = YES;
transition.delegate = self;
[self.view.layer addAnimation:transition forKey:nil];
[UIView animateWithDuration:0.5 animations:^ {
self.view.alpha = 0.0;
}completion:^(BOOL finished) {
NSLog(#"Transition Animation Complete");
}];
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
transitioning = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:#"nextPrime" object:nil];
}
Now in the animationDidStop: Method, i again post another notification to the NSNotificationCenter back to the MasterViewController to signal another prime.
In MasterViewController.m
-(void)nextPrime {
if (self.picturePrimeViewIsDisplayed) {
[self.picturePrimeViewController.view removeFromSuperview];
self.picturePrimeViewController = nil;
[self showAPrime];
}
if (self.flashTextViewIsDisplayed) {
[self.flashTextPrimeViewController.view removeFromSuperview];
self.flashTextPrimeViewController = nil;
[self showAPrime];
}
}
However! Upon swiping the right, the view animates properly but then I get a bad access crash when the ThinkOfViewController is attempting to dealloc it's UIViews. So for some reason, it is taking that the ThinkOfViewController a long time to dealloc, when I assumed when I called [self.thinkOfViewController removeFromSuperview], it should of been removed immeditately.
(Side note, the textFlashViewController has no problems, the only problems are comming with this ThinkOfViewController).
Is this paradigm I set up a bad implmentation of dealing with UiViewController's comming in and out? I have read that delegation can help in this instance, I'm just not sure how that works.
If any of you have any ideas, I would be so grateful, as I have mined through forums and documentations and cannot see a solution to my rather custom implmentation of dealing with these views.
So, the short answer is yes, this "paradigm" is a bad implementation of dealing with UIViewControllers. I would suggest going and reading Apple's View Controller Programming Guide, which outlines the correct implementation, but here's a quick synopsis:
Your MasterViewController, from what I gather, manages these other two UIViewControllers, ThinkOfViewController and PicturePrimeViewController. When you are adding or removing the views of a view controller from the screen, you don't add or remove the views to the MasterViewController. The whole point of a view controller is to manage the "showing" or "hiding" of its view. I put showing and hiding in quotes because you're not actually showing or hiding them. You are pushing and popping them off of the view hierarchy, and this is done with a UINavigationController. Each UIViewController knows the UINavigationController that it is being controlled by (thus, UINavigationControllers are known as "controllers of controllers"), and you can thus push a view controller onto the stack by saying
[self.navigationController pushViewController:vcToBePushed animated:YES];
When the view controller that is on top of the stack is to be removed, you simply have to say
[self.navigationController popViewControllerAnimated:YES];
Pushing or popping a UIViewController onto or off of the stack means the view controller takes its view with it, and displays it or removes it from on screen. So that covers, in the tightest nutshell imaginable, UIViewController view management.
The other issue, regarding the EXC_BAD_ACESS crash, means that you are trying to access memory that has already been allocated for another object. I suspect the culprit is here:
if (randomNumber == 0) {
self.flashTextViewIsDisplayed = NO;
ThinkOfViewController *thinkVC = [[ThinkOfViewController alloc] initWithNibName:#"ThinkOfViewController" bundle:nil];
self.thinkOfViewController = thinkVC;
[thinkVC release];
self.picturePrimeViewIsDisplayed = YES;
[self.view addSubview:self.thinkOfViewController.view];
}
The problem is that you release thinkVC before it has had a chance to be retained by the MasterViewController's view (which happens in self.view addSubview:). Thus, self.view is adding a pointer to an object whose memory just got added back to the heap. Scrapping your add/removeSubview methodology for the push/pop methodology I just outlined will keep that sort of memory issue from happening.
I hope this helps, but let us (us being SO) know if you still have issues.

Why no animation in PageControl project?

I'm using the PageControl project, which is on Apple's dev site. I've added a flip view to the project and an info icon to the top right of each view/page. For some reason, only the first page is able to animate the flipping. Page 2 on still shows the flipped page but does not animate. To make sure it isn't anything special about page 1, I switch page 1 and 2 and that worked fine. Page 2 in position 1 animated while Page 1 in position 2 did not. Any ideas why this would happen or how I can trouble shoot it?
I did take a look at this thread, which seems to be the same issue: Flip View Iphone. However, My flipview is a UIViewController and so is the class with the info icon on it. In the other thread, they are using UIViews.
I did implement the showInfo code from the above thread. When on Page 2, I see no flip. Then I scroll over to Page 1 and see it has flipped. Not sure why it isn't staying with Page 2. When on Page 1, it doesn't animate the flip. The flipview just suddenly appears.
Do you have a containerView? Something that can be there so you can add and remove subviews from it? Animation can break if you have two viewControllers, one coming and one going, without a containerView. I use a rootViewController and animate all my pages to and from each other with the rootViewcontroller in the back. Here is my code for flipping, you'll probably have to do a little editing to make it work for you:
(keep in mind that self is the rootViewcontroller, a viewcontroller with a blank view (color it so it matches your views))
- (void)switchTwoViews:(UIViewController *)view1 otherView:(UIViewController *)view2
{
/*
This method is called to switch views.
It flips the displayed view from the main view to the flipside view and vice-versa.
*/
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
[view1.view setUserInteractionEnabled: NO];
[view2.view setUserInteractionEnabled: NO];
if (view1.view.superview == nil) {
coming = view1;
going = view2;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else {
coming = view2;
going = view1;
transition = UIViewAnimationTransitionFlipFromRight;
}
// in some cases the following is needed to size the view
// coming.view.frame = [UIScreen mainScreen].applicationFrame;
// going.view.alpha = 1.0; //uncomment these lines if we want fading of views
// coming.view.alpha = 0.0;
NSArray *viewArray = [[NSArray alloc] initWithObjects:coming, going, nil];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[UIView beginAnimations:#"View Flip" context:viewArray]; {
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidEnd:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// coming.view.alpha = 1.0; //uncomment these lines if we want fading of views
// going.view.alpha = 0.0;
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[self.view addSubview: coming.view];
}
[UIView commitAnimations];
}
- (void) animationDidEnd:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
NSArray *viewArray = context;
[((UIViewController *)[viewArray objectAtIndex:1]).view removeFromSuperview];
[[viewArray objectAtIndex:1] viewDidDisappear:YES];
[[viewArray objectAtIndex:0] viewDidAppear:YES];
[[[viewArray objectAtIndex:0] view] setUserInteractionEnabled: YES];
[viewArray release];
}

Iphone: Is it possible to hide the TabBar? (Pre-iOS 8)

I have an application that uses a UITabBarController to switch between modes. When in a certain mode, I'd like to hide the tab bar until the steps of that mode have been completed. Note that I'm not using a navigation controller so I can't use the setHidesBottomBarWhenPushed method on the navigation controller to hide the tab bar.
Prior to iOS 8, When I attempt to hide the tarbar using:
self.tabBarController.tabBar.hidden = YES
the tab bar goes away, but it leaves a 50 pixel blank area at the bottom of the screen where the tab bar used to be. I can't seem to figure out how to fill that area. Anything in the UI that is in that area is clipped and cannot be seen.
Any ideas if this is even possible? I'd really like to stay away from the navigation controller.
Here's my code for that:
This is, of course, mucking with the goings on in the controller's view hierarchy. It could change/break. This uses defined APIs, so Apple won't care, but they won't care about breaking your code, either.
- (void)hideTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds);
tabBar.frame = tabFrame;
content.frame = window.bounds;
}];
// 1
}
- (void)showTabBar {
UITabBar *tabBar = self.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.5
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
tabBar.frame = tabFrame;
CGRect contentFrame = content.frame;
contentFrame.size.height -= tabFrame.size.height;
}];
// 2
}
Edit:
An anonymous user has suggested the following addition for 7.0 (i have not tested this, and could not say whether it is a workaround or an ideal implementation):
// 1. To Hide the black line in IOS7 only, this extra bit is required
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[self.tabBarController.tabBar setTranslucent:YES];
}
// 2. For IOS 7 only
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[self.tabBarController.tabBar setTranslucent:NO];
}
Edit: Entirely untested in 8.x and likely lacking in some layouts.
Like Steve, I haven't found a clean way to do this (even though Apple Photopicker does something similar). Here is what I have done:
if (systemAction)
{
// Reveal tab bar back
CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height);
self.toolBar.hidden = YES;
systemAction = NO;
}
else
{
//hide tab bar
CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect tabBarFrame = self.tabBarController.tabBar.frame;
CGRect navigationBarFrame = self.navigationController.navigationBar.frame;
self.tabBarController.view.frame = CGRectMake(0,0,bounds.size.width,bounds.size.height+tabBarFrame.size.height);
self.toolBar.hidden = NO;
CGRect frame = self.toolBar.frame;
frame.origin.y = bounds.size.height - frame.size.height - navigationBarFrame.size.height;
self.toolBar.frame = frame;
systemAction = YES;
}
What it is doing is pushing the view down so I can display a toolbar (and not hiding it). Obviously this is for only the 'root view' of a tabbar + navigation controller. For any subsequent views you can set the 'hidesBottomBarWhenPushed' on the viewcontroller you are pushing.
I tried a number of the solutions above, but no joy in iOS 8. I find that setting in viewWillAppear the following works for me. Should work in iOS 7 as the extendedLayoutIncludesOpaqueBars was introduced then.
self.extendedLayoutIncludesOpaqueBars = true
self.tabBarController?.tabBar.isHidden = true
self.tabBarController?.tabBar.isOpaque = true
and if you need to turn tabBars on again when you leave to use the following in viewWillDisappear.
self.tabBarController?.tabBar.isHidden = false
self.tabBarController?.tabBar.isOpaque = false
I use this to allow a return from a transition to keep the TabBar hidden. Not used it in a button action but if like me you find nothing above now works, this could be the basis of a programmable solution.
It's a bit late in the day, but of all the answers to the question that I've trawled through this afternoon, this is the one that worked best for me.
How to hide uitabbarcontroller
// Method call
[self hideTabBar:self.tabBarController];
// Method implementations
- (void)hideTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
}
}
[UIView commitAnimations];
}
- (void)showTabBar:(UITabBarController *) tabbarcontroller
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
NSLog(#"%#", view);
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 431, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 431)];
}
}
[UIView commitAnimations];
}
I use only this single line to achieve this. I use prepareForSegue method before showing the view controller having the tab bar.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showLogin"]){
[segue.destinationViewController setHidesBottomBarWhenPushed:YES];
}
}
I had worked on almost the same case, actually used the code from http://www.developers-life.com/hide-uitabbarcontrolleruitabbar-with-animation.html and made it better according to my needs, this might help others too.
I am using a UISplitViewController as the root view controller and its detail portion is a UITabBarController, I had to hide the tabbar in portrait mode:
// In UITabBarController's custom implementation add following method,
// this method is all that will do the trick, just call this method
// whenever tabbar needs to be hidden/shown
- (void) hidetabbar:(NSNumber*)isHidden {
UITabBarController *tabBarController=self;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
CGRect tabbarFrame=CGRectZero;
for(UIView *theView in tabBarController.view.subviews) {
//NSLog(#"%#", view);
if([theView isKindOfClass:[UITabBar class]]) {
tabbarFrame=theView.frame;
if ([isHidden boolValue]) {
tabbarFrame=CGRectMake(tabbarFrame.origin.x,
tabBarController.view.frame.size.height,
tabbarFrame.size.width,
tabbarFrame.size.height);
} else {
tabbarFrame=CGRectMake(tabbarFrame.origin.x,
tabBarController.view.frame.size.height - tabbarFrame.size.height,
tabbarFrame.size.width,
tabbarFrame.size.height);
}
theView.frame=tabbarFrame;
break;
}
}
for(UIView *theView in tabBarController.view.subviews) {
if(![theView isKindOfClass:[UITabBar class]]) {
CGRect theViewFrame=theView.frame;
if ([isHidden boolValue]) {
theViewFrame=CGRectMake(theViewFrame.origin.x,
theViewFrame.origin.y,
theViewFrame.size.width,
theViewFrame.size.height + tabbarFrame.size.height);
} else {
theViewFrame=CGRectMake(theViewFrame.origin.x,
theViewFrame.origin.y,
theViewFrame.size.width,
theViewFrame.size.height - tabbarFrame.size.height);
}
theView.frame=theViewFrame;
}
}
[UIView commitAnimations];
}
I used following code to call the hidetabbar: method
//In my UISplitViewController's custom implementation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
#synchronized(self){
//change the self.splitDetailController to your UITabBarController's object
[self.splitDetailController
performSelector:#selector(hidetabbar:)
withObject:[NSNumber numberWithBool:UIInterfaceOrientationIsLandscape(interfaceOrientation)]
afterDelay:0.5];
}
return YES;
}
I tested this code to work in simulator only, let me know if it works on device too ;-)
Do you have the autoResizingMask set on the sub view?
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Something like that should do the trick and allow the view sitting atop the stack to re-size.
The obvious solution, keeping your original architecture, would have been to present that view modally:
- (void)tabBarController:(UITabBarController *)tb
didSelectViewController:(UIViewController *)vc {
if (tb.selectedIndex == MODALONE) {
UIViewController* mod =
[[UIViewController alloc] initWithNibName: #"ModalView"
bundle: nil];
[tb presentModalViewController:mod animated:NO];
[mod release];
}
}
The view now covers the entire screen (except for the status bar is there is one) including the tab bar, so it looks as if the tab bar has gone away in response to the user pressing that tab bar item.
autoresizing mask has an enumeration. Try to set all the options and check if autoresize subviews option is checked in parent view
You can create Tabbar Category and show/Hide easily. and you can access full view.
create category #import "UITabBarController+HideTabBar.h"
#implementation UITabBarController (HideTabBar)
- (void)hideTabBarAnimated:(BOOL)animated
{
CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect tabBarControllerFrame = self.view.frame;
if (statusbarFrame.size.height>20)
{
tabBarControllerFrame.size.height = screenSize.size.height + self.tabBar.frame.size.height - 20.0;
}
else
{
tabBarControllerFrame.size.height = screenSize.size.height + self.tabBar.frame.size.height ;
}
if (animated) {
[UIView animateWithDuration:0.2 animations:^{
[self.view setFrame:tabBarControllerFrame];
} completion:^(BOOL finished) {
}];
}
else
[self.view setFrame:tabBarControllerFrame];
}
- (void)showTabBarAnimated:(BOOL)animated {
CGRect statusbarFrame = [UIApplication sharedApplication].statusBarFrame;
CGRect tabBarControllerFrame = self.view.frame;
if (statusbarFrame.size.height>20)
{
tabBarControllerFrame.size.height = screenSize.size.height - 20.0;
}
else
{
tabBarControllerFrame.size.height = screenSize.size.height ;
}
if (animated) {
[UIView animateWithDuration:0.2 animations:^{
[self.view setFrame:tabBarControllerFrame];
} completion:^(BOOL finished) {
}];
}
else
[self.view setFrame:tabBarControllerFrame];
}
#end
Note : use statusbarFrame is used when hotspot or call is ON so tabbar would not cut down.
Now Import category in which you class you want to use methods and just call below methods to hide or show tabbar.
[self.tabBarController hideTabBarAnimated:YES];
[self.tabBarController showTabBarAnimated:YES];
Hope this Helps.
Hope this works.
#interface UITabBarController (Additions)
-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated;
#end
#implementation UITabBarController (Additions)
-(void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
if (animated)
{
[UIView beginAnimations:nil context:nil];
}
if (hidden)
{
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
}
else
{
self.tabBar.frame = CGRectMake(self.tabBar.frame.origin.x, self.tabBar.superview.frame.size.height - self.tabBar.frame.size.height + 10, self.tabBar.bounds.size.width, self.tabBar.bounds.size.height);
}
if (animated)
{
[UIView commitAnimations];
}
}
Here is my solution (my tab view controller is inside navigation controller for good measure)... So I have subclassed UITabBarController and did this... exposing -setTabBarHidden: method
- (void)setTabBarHidden:(BOOL)hidden {
_tabBarHidden = hidden;
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
- (void)adjustViews {
if ( _tabBarHidden ) {
CGRect f = self.tabBar.frame;
// move tab bar offscreen
f.origin.y = CGRectGetMaxY(self.view.frame);
self.tabBar.frame = f;
// adjust current view frame
self.selectedViewController.view.frame = self.view.frame;
} else {
CGRect f = self.tabBar.frame;
// move tab bar on screen
f.origin.y = CGRectGetMaxY(self.view.frame) - (CGRectGetMaxY(self.tabBar.bounds) + CGRectGetMaxY(self.navigationController.navigationBar.frame));
self.tabBar.frame = f;
// adjust current view frame
f = self.view.bounds;
f.size.height -= CGRectGetMaxY(self.tabBar.bounds);
self.selectedViewController.view.frame = f;
}
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[UIView performWithoutAnimation:^{
[self adjustViews];
}];
}
put the statement in the init method of the UIViewController
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.hidesBottomBarWhenPushed = true
setupDependencyConfigurator()
}
See this thread:
Show/Hide TabBarController in iphone
In summary, you can see an example of this behavior in this sample code:
http://developer.apple.com/iphone/library/samplecode/TheElements/index.html
Why are you not using a navigation controller. It's a lot easier to hide the nav bar than the tab bar...
Just made the following code in Monotouch inside a subclass of UITabBarController:
public void ShowTabBar()
{
UIView.BeginAnimations("Anim");
UIView.SetAnimationDuration(0.25f);
this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 431f);
this.TabBar.Frame = new RectangleF(0f, 431f, 320f, 49f);
this.TabBar.Hidden = false;
UIView.CommitAnimations();
}
public void HideTabBar()
{
UIView.BeginAnimations("Anim");
UIView.SetAnimationDuration(0.25f);
this.View.Subviews[0].Frame = new RectangleF(0f, 0f, 320f, 480f);
this.TabBar.Frame = new RectangleF(0f, 481f, 320f, 510f);
this.TabBar.Hidden = true;
UIView.CommitAnimations();
}