Reputation: 432
I have created a new split view based project in my XCode 4.2
Then in DetailViewController.m
file i have add this method
- (BOOL)splitViewController: (UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
//This method is only available in iOS5
return NO;
}
Now by doing this i can able to show both left & right part of my splitview Controller at a time.
Now i have added a UIBarButtonItem
in my DetailViewController
Navigation bar and i want by using which i can hide & show my Master View both in Portrairt and Landscape Mode.
- (IBAction)hideUnhide:(id)sender
{
//How can hide & unhide
}
How can i do this?
Upvotes: 21
Views: 34540
Reputation: 898
SWIFT 3.0
I've used
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = self.exercises[indexPath.row]
let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem
controller.navigationItem.leftItemsSupplementBackButton = true
UIView.animate(withDuration: 0.2, delay: 0.0, options: [.curveEaseOut], animations: {
self.splitViewController?.preferredDisplayMode = .primaryHidden
}, completion: nil)
}
}
}
Upvotes: 0
Reputation: 3726
You can show/hide the master ViewController by triggering the action of the displayModeButtonItem
property of UISplitViewController
:
Swift
if let displayModeButtonItem = splitViewController?.displayModeButtonItem() {
displayModeButtonItem.target?.performSelector(displayModeButtonItem.action)
}
Objective-C
UIBarButtonItem *displayModeButtonItem = [self.splitViewController displayModeButtonItem];
[displayModeButtonItem.target performSelector: displayModeButtonItem.action];
It feels more proper to me than meddling with the delegate, the orientation and the layout at the same time.
Upvotes: 0
Reputation: 11993
In iOS8 this is easy.
To hide it
[UIView animateWithDuration:0.2 animations:^{
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryHidden;
} completion:nil];
To show it
[UIView animateWithDuration:0.2 animations:^{
self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;
} completion:nil];
Upvotes: 2
Reputation: 161
-(IBAction)clickToShowMaster:(id)sender
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
self.navigationItem.leftBarButtonItem = systemItem1;
[self.tabBarController.tabBar setHidden:NO];
[self hideMaster:NO];
}
-(void)hideMaster:(BOOL)hideState
{
ishideMaster=hideState;
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate = nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
}
-(void)hideMaster:(BOOL)hideState
{
ishideMaster=hideState;
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate = nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
}
#pragma mark - Split view
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
if(UIInterfaceOrientationIsPortrait(orientation))
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"down.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showPopup)];
self.navigationItem.leftBarButtonItem = systemItem1;
[self setUIforPortrait];
return YES;
}
if (UIInterfaceOrientationIsLandscape(orientation))
{
if(ishideMaster==TRUE)
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"next.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToShowMaster:)];
self.navigationItem.leftBarButtonItem = systemItem1;
[self setUIForFullLandscape];
}
else
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
self.navigationItem.leftBarButtonItem = systemItem1;
[self setUIForHalfLandscape];
}
return ishideMaster;
}
}
//add the navigation button on left top, to pop-up master view.
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
[barButtonItem setImage:[UIImage imageNamed:@"down.png"]];
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"down.png"] style:UIBarButtonItemStylePlain target:self action:@selector(showPopup)];
self.navigationItem.leftBarButtonItem = systemItem1;
self.masterPopoverController = popoverController;
self.masterPopoverController.delegate=self;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
//;
if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
if(ishideMaster==FALSE)
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"prev.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToHidemaster:)];
self.navigationItem.leftBarButtonItem = systemItem1;
}
else
{
UIBarButtonItem *systemItem1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"next.png"] style:UIBarButtonItemStylePlain target:self action:@selector(clickToShowMaster:)];
self.navigationItem.leftBarButtonItem = systemItem1;
}
}
else if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
}
//self.masterPopoverController = nil;
}
Upvotes: 3
Reputation: 1177
Regarding wzbozon's comment about not needing to reassign the delegate, I found that the two lines
self.splitViewController.delegate = nil;
self.splitViewController.delegate = self;
...were not needed on the simulator but were needed on my iOS5 iPad 1. Without them, the hide/show behavior did not occur (clicking the button did not collapse the master view).
Upvotes: 1
Reputation: 939
I combined the above responses and the following works well in IOS 6:
// In split delegate
-(void)hideMaster:(BOOL)hideState
{
_masterIsHidden = hideState;
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate = nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
}
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return self.masterIsHidden;
}
Upvotes: 4
Reputation: 51
- (BOOL)splitViewController:(UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
[spv.view setNeedsLayout]; //add the line
return self.hideMaster;
}
Upvotes: -1
Reputation: 1165
instead spv.delegate=nil; spv.delegate=self;
you need to do next:
[spv willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
Upvotes: 8
Reputation: 11148
In iOS 5.1 you have to do it this way:
Inside DetailViewController.m
- (IBAction)hideUnhide:(id)sender {
UISplitViewController* spv = ...;
self.hideMaster= !self.hideMaster;
[spv.view setNeedsLayout];
spv.delegate = nil;
spv.delegate = self;
}
- (BOOL)splitViewController:(UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
return self.hideMaster;
}
Upvotes: 6
Reputation: 559
'setNeedsLayout' makes UISplitViewController to ask for "shouldHideViewController"
- (IBAction)hideUnhide:(id)sender {
UISplitViewController* spv = ...;
self.hideMaster= !self.hideMaster;
[ spv.view setNeedsLayout ]
}
Upvotes: 7
Reputation: 5953
Well, the easy part of your question is to use a bool, say a property hideMaster, and then
- (IBAction)hideUnhide:(id)sender
{
self.hideMaster= !self.hideMaster;
}
and then...
- (BOOL)splitViewController: (UISplitViewController*)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
//This method is only available in iOS5
return self.hideMaster;
}
That works fine, but the shouldHideViewController is only called during a redraw of the splitVC, such as during a rotation, so the master only hides/unhides then.
Upvotes: 0