I have 2 views. One is the 'viewheader' and the other is the 'viewContent' (added as subview).
'viewContent' contains a TableView (based on UINavigationController) and the TableView can drill down to a DetailView (UIViewController). (see Image below)
My Question is: How can I remove (pop) the DetailView, with a UIButton FROM the 'headerView'.
The goal is to create a fixed Navigation, and only change (animate) the lower Content.
Thanks
// add "fixed" Header
- (void)loadView {
viewHeader = [[HeaderViewController alloc] initWithNibName:#"HeaderViewController" bundle:nil];
self.view = viewHeader.view;
}
// add content view
- (void)viewDidLoad {
[super viewDidLoad];
viewContent = [[MainContentViewController alloc] initWithNibName:#"MainContentViewController" bundle:nil];
CGRect viewFrame = CGRectMake(0.0f, 164.0f, 320, 316);
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewContent];
[navController setNavigationBarHidden:YES];
[navController.view setFrame:viewFrame];
viewHeader.contentNavView = navController; // <<<< CAN'T POP THE VIEW by passing UINavigationController to "header view"
[self.view addSubview:navController.view];
}
You must somehow send a removeFromSuperview message to the detail view when the button on the header view is tapped (i.e. an IBAction is triggered). You can achieve this by either making the detail view a property of the header view controller to be able to call the removeFromSuperview of the detail view in your header view's IBAction.
Or if you prefer loose coupling (which you should), post a notification from the IBActionin the header view and register for that notification in the detail view with a method that removes the detail view from the header view.
I Found my mistake. The definition of 'contentNavView' inside 'viewheader' was wrong
Changed it from UIViewController to UINavigationController.
#interface HeaderViewController : UIViewController {
UINavigationController *contentNavView;
}
...
Calling
[contentNavView pushViewController:aViewController animated:NO];
works.
Related
I implemented a custom tab bar controller as a set of buttons each one related to it's own View Controller. I guided on this link http://idevrecipes.com/2011/01/04/how-does-the-twitter-iphone-app-implement-a-custom-tab-bar/ to achieve the behavior. So the relevant part of code is as follows:
- (void) selectedItemAtIndex:(NSUInteger)itemIndex
{
// Get the right view controller
NSDictionary* data = [self.tabBarItems objectAtIndex:itemIndex];
UIViewController* viewController = [data objectForKey:#"viewController"];
// Remove the current view controller's view
UIView* currentView = [self.view viewWithTag:SELECTED_VIEW_CONTROLLER_TAG];
[currentView removeFromSuperview];
// Set the view controller's frame to account for the tab bar (+ 48)
viewController.view.frame = CGRectMake(0,48,self.view.bounds.size.width, self.view.bounds.size.height - 48);
// Se the tag so we can find it later
viewController.view.tag = SELECTED_VIEW_CONTROLLER_TAG;
// Add the new view controller's view
[self.view insertSubview:viewController.view belowSubview:self.tabBar];
//Keep track of current view controller
self.currentController = viewController;
}
So far is working, I can see each view controller in a similar maner to the default TabBarViewController. But then there's a requirement where I need to push a new navigation controller modally (it should take all the application frame) from inside one of the tabBar controllers.
At first glance I tried the following code from within one of the tab controllers:
DetailViewController *detailViewController = [[DetailViewController alloc]init];
UINavigationController *navigationController = [[UINavigationController alloc]detailViewController];
[self presentModalViewController:navigationController animated:YES];
However is not working as expected, first the view is shown below the TabBar and second the new view is not taking in consideration the parent view frame which should be the screen bounds less the tabbar. (0, 48, 360, 412). My detail view controller it's loading content from a nib file.
Well, this is quite obvious since the TabBar Controller is inserting each view below my custom TabBar.
[self presentModalViewController:navigationController animated:YES];
So I tried inserting it directly as a window subview:
[[UIApplication sharedApplication].keyWindow addSubview:navigationController.view];
But, I think this is not okay... there should be a better approach that I can't figure out. So if anybody could give me suggestions on how to correct or improve this navigation system it would be great.
Thanks a lot.
If you are building you app for iOS 5.0 and up you can make use of childViewController. In your custom Tab Bar you can have a containerView and a tabView.
The view of viewController is added to containerView. All the necessary events are generated to the subsequently added viewController if the following methods are implemented correctly
- (void)addChildViewController:(UIViewController *)childController;
- (void)removeFromParentViewController;
More about viewController containment can be found here.
I would like to have a UISegmentedControl embedded in a PopoverController, similar to what is described in this SO question : UISegmentedControl embedded in a UINavigationBar/Item
The difference is that I have a different view controller for each view that I want to show in the popover, depending on the selected index on the Segmented Control. I'm not sure how I would go about doing this. Whenever I try to push a new view on top of the root view controller, the UISegmentedControl disappears. I would just like to switch between the two viewcontrollers, while keeping the UISegmentedControl visible. Is this even possible?
Thanks in advance!
If its a different viewController for each one of the segments on the segmentBar, you'll have to use a container viewController that adds the views of each of the viewController as a subview on itself or sets its view to that of the viewController's view. For example:
UIViewController* containerController = [[[UIViewController alloc] init] autorelease];
//Inside the viewDidLoad of the the ContainerController class, do the following:
//Initialize all three viewControllers
UIViewController* test1 = [[[UIViewController alloc] init] autorelease];
UIViewController* test1 = [[[UIViewController alloc] init] autorelease];
UIViewController* test1 = [[[UIViewController alloc] init] autorelease];
//set up the segment and add it to the container's navBar's title view.
[segmentedControl addTarget:self action:#selector(segmentValueChanged:) forControlEvents:UIControlEventValueChanged];
- (void)segmentValueChanged:(id)sender
{
//if first tab selected
[self.view removeAllSubviews];
[self.view addSubview:test1.view];
//if second tab selected
[self.view removeAllSubviews];
[self.view addSubview:test2.view];
//if third tab selected
[self.view removeAllSubviews];
[self.view addSubview:test3.view];
}
Instead of adding it as a subView, you might be able to just set self.view = test1.view. Obviously, you would use the container view to initialize the navController and put that navController inside the popover. Hope this helps!
If you are using presentModalViewController method to show your new view controller on the screen, it will always cover the entire screen and what ever is underneath it. That's just how it works.
As per docs:
On iPhone and iPod touch devices, the view of modalViewController is
always presented full screen. On iPad, the presentation depends on the
value in the modalPresentationStyle property.
The way to do it and still being able to control how the view controller is positioned is to create your own presentation method.
I'm using a Navigation Controller. My RootViewController pushes a number of views but it also presents a modal view. That modal view presents a tableView. So what I'm trying to do is figure out of I can push the Navigation Controller across the modal view, then use it from that modal view to push the view with the tableView? or barring that, is there a way to implement a second Navigation Controller from the modal view?
The real issue is that I want to present the view with the tableView using a right to left transition, which of course is not available with modal views.
I have this code that SORT OF provides the right to left transition used by the Navigation Controller:
NewViewController *newViewController = [[NewViewController alloc] init];
[self presentModalViewController:newViewController animated:NO];
CGSize theSize = CGSizeMake(320, 460);
newViewController.view.frame = CGRectMake(0 + theSize.width, 0 + 20, theSize.width, theSize.height);
[UIView beginAnimations:#"animationID" context:NULL];
[UIView setAnimationDuration:0.5];
newViewController.view.frame = CGRectMake(0, 0 + 20, 320, 460);
[UIView commitAnimations];
[newViewController release];
The problem is that the OldViewController (the one calling the NewViewController) disappears immediately so the NewViewController transitions across a blank screen, instead of covering the OldViewController.
Presenting a UIViewController modally creates a whole new navigation stack. You could do something like this:
//Create the view you want to present modally
UIViewController *modalView = [[UIViewController alloc] init];
//Create a new navigation stack and use it as the new RootViewController for it
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:modalView];
//Present the new navigation stack modally
[self presentModalViewController:nav animated:YES];
//Release
[modalView release];
[nav release];
This can be done because UINavigationController is a subclass of UIViewController. When the new view is loaded, you can use it however you wish (push another view on top of it, us UIView animations like Waqas suggeste, etc').
I hope I got your question correctly. Do tell if I didn't.
I have a root view controller which has few buttons. On click of these button, I shown up a tab bar controller with each controller showing the table view controller. I have achieved this. So basically, for each table view controller I have a dedicated class. To go ahead, I replaced the tab bar controller, and added the segmented controller to the navigation title view.
The question is how can I set the view based on the selected index. I am able to set the navigation title to be segmented control but on select I am unable to set the view.
Below is what i have achieved so far.
Note: What matters is a running code, I would do that code optimization later on. I dont want to hidde views. I want to call different view controller class.
RootViewController class (on click of the button, i call the first view controller. So that I can set the segment controller:
-(IBAction) pushSegmentController: (id) sender
{
NSLog(#"My Location Button being clicked/touched") ;
FirstViewController *firstViewController = [[FirstViewController alloc] init] ;
[self.navigationController pushViewController:firstViewController animated:YES];
// Releae the view controllers
[firstViewController release];
}
IN FirstViewController class:
-(void)viewDidLoad {
[super viewDidLoad];
NSArray *viewControllers = [self segmentViewControllers];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Table1", #"Table2"]];
self.navigationItem.titleView = segmentedControl;
[self.segmentedControl addTarget:self
action:#selector(indexDidChangeForSegmentedControl:)
forControlEvents:UIControlEventValueChanged];
self.segmentedControl.selectedSegmentIndex = 0;
}
-(void)indexDidChangeForSegmentedControl:(UISegmentedControl *)aSegmentedControl {
NSUInteger index = aSegmentedControl.selectedSegmentIndex;
if(index ==0) {
UIViewController *table1Controller = [[AustraliaViewController alloc] initWithStyle:UITableViewStylePlain];
**???? HOW SHOULD I SET THE VIEW OVER HERE... AS ITS A PART OF THE NAVIGATION CONTROLLER**
}
else { }
}
Note: I have tried using this option:
[navigationController setViewControllers:theViewControllers animated:NO];
But this option doesnt give me the right result. How should I go ahead with the same as I want to call a view controller class and set its view based on the selected index.
You probably don't want to have one view controller with different views depending on the button index, especially since you already have view controllers for your different screens.
If you want the table view controller to be pushed onto your navigation controller, so it will have a back button that gets you back to FirstViewController, use
-(void)indexDidChangeForSegmentedControl:(UISegmentedControl *)aSegmentedControl {
NSUInteger index = aSegmentedControl.selectedSegmentIndex;
UIViewController *newViewController = nil;
if(index ==0) {
newViewController = [[AustraliaViewController alloc] initWithStyle:UITableViewStylePlain];
} else {
newViewController = [[YourOtherViewController alloc] initWithStyle:UITableViewStylePlain];
}
[self.navigationController pushViewController:newViewController animated:YES];
}
If you'd rather have it slide in from the bottom and you want to handle setting up all necessary user interface (e.g. a dismiss button), replace that last line with
[self presentModalViewController:newViewController animated:YES];
What about?
self.view = table1Controller;
or
[self.view addSubview:table1Controller];
I just saw one more mistake you have done. You are allocating a UIViewController, but initializing it like a tableViewController(with initWithStyle).
If it's a subclass of UITableViewController, alloc it with that, not UIViewController.
I have app with UItabBarTemplate with navigation controller.
On selecting tab bar ViewControllerA is shown which on button touch pushes UIPieChartTabController which inherits "UIViewController".
Now I want another tab bar in UIPieChartTabController.
so in viewDidLoad of UIPieChartTabController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
contentView.backgroundColor = [UIColor whiteColor];
self.view = contentView;
[contentView release];
UITabBarController *tabbar= [[UITabBarController alloc] init];
tabbar.view.frame = CGRectMake(0, 0, 320, 460);
piechartViewController *pr=[[piechartViewController alloc]init];
pr.tagInAction=1;
pr.title=#"Type";
pr.tabBarItem.image=[UIImage imageNamed:#"trend.png"];
pr.sDate=sDate;
pr.nDate=nDate;
piechartViewController *pr1=[[piechartViewController alloc]init];
pr1.title=#"category";
pr1.tagInAction=4;
pr1.sDate=sDate;
pr1.nDate=nDate;
piechartViewController *pr2=[[piechartViewController alloc]init];
pr2.title=#"paidWith";
pr2.tagInAction=3;
pr2.sDate=sDate;
pr2.nDate=nDate;
//tabbar.tabBar.delegate=self;
//this gave me error
ExportRep *pr3=[[ExportRep alloc]init];
pr3.tabBarItem.image=[UIImage imageNamed:#"database.png"];
pr3.title=#"Export Expenses";
[tabbar setViewControllers:[NSArray arrayWithObjects:pr,pr1,pr2,pr3,nil]];
[self.view addSubview:tabbar.view];
[pr release];
[pr1 release];
[pr2 release];
}
This piece of code worked but now when I select tab of viewController ExportRep type I tried
[self presentModalViewController:objMFMailComposeViewController animated:YES];
but navigationController of objMFMailComposeViewController hides behind navigationController of view that is presenting objMFMailComposeViewController.
Also viewWillAppear viewDidAppear of all the view controller which are bound to tab bar never gets called.
But none of this problem occurs for tabbar and viewcontroller which gets created by UITabbarTemplate.
Why Is it so? Whats wrong when I create Tab bar?
placing another tabBar within a tabbarVC, is not recommended. Why not use a UIToolBar to do the swapping of Views in your PieChartVC instead?
-apart from that, the reason your code doesn't call viewWillAppear,viewDidAppear is because of this:
[tabbar setViewControllers:[NSArray arrayWithObjects:pr,pr1,pr2,pr3,nil]];
[self.view addSubview:tabbar.view];
here only loadView of those prs will be called.
the viewControllers you assign to the tabBars should instead be wrapped around UINavigationControllers.
So something like this instead would do the trick
UINavigationController *nc1 = [[UINavigationController alloc]initWithRootViewController:pr];
[nc1.view setFrame:CGRectMake:("the frame in which you wnt prs to be displayed")];
[pr.view setFrame:nc1.view.frame];
. // similarly assign NavControllers for all prs
.
.
.
[tabbar setViewControllers:[NSArray arrayWithObjects:nc,nc1,nc2,nc3,nil]];
[self.view addSubview:tabbar.view];
The reason why new view which is being presented modally got its navigation bar hidden lies in [self.view addSubview:tabbar.view];
so it got room to present its view only in parent controllers view thus got cut its navigation bar.
so to hack it I kept tab selected and instead of presenting it in selected view controller,have presented it in main view controller only.