valfer
valfer

Reputation: 3545

UISplitViewController displayModeButtonItem()

Does someone know a way to change the text (and appearance?) of the button returned from the UISplitViewController delegate:

func displayModeButtonItem() -> UIBarButtonItem?

Upvotes: 17

Views: 8154

Answers (9)

Josh Pike
Josh Pike

Reputation: 51

I have this exact same issue.

This is how I'm going to solve it, I'll update on my results.

The UIBarButtonItem returned by displayModeButtonItem is managed by UISplitViewController in it's own good time. So any changes you make are blocked.

However there is a new delegate function:

- (UISplitViewControllerDisplayMode)targetDisplayModeForActionInSplitViewController:(UISplitViewController *)svc

I am going to create my own UIBarButtonItem that will change based on when this function fires.

I will then get it to trigger the display mode as appropriate.

Upvotes: 1

user1543432
user1543432

Reputation: 57

I wanted to update this with the proper solution to showing a title in the displayModeButtonItem. This method shows the back arrow, as well as the proper text. Most of the above solutions do not include the back arrow in the end, from what I could tell. I had tried setting this a few different ways, but it always got wiped when the master view would open and close again (iPad Portrait), only leaving me with the back arrow.

You must set the "Title" property on the Master View's navigationController.

Note that this is different from setting the Back and Title texts on the master view's navigation item. Setting on the Navigation Item WILL NOT work.

select the navigation controller for the master view, then set the "Title Property in the Attributes Inspector"

Upvotes: 3

JTango18
JTango18

Reputation: 634

This text is set by setting the "Back Button" text property of the Navigation Item in the Master View Controller through Interface BuilderVisual guide

Upvotes: 2

Leontien
Leontien

Reputation: 662

I tried EmilDo's solution, but the navigation button was not shown. I changed the solution a little bit and got it working with the following code:

DetailViewController:

override func viewDidLayoutSubviews() {
    if splitViewController!.displayMode == UISplitViewControllerDisplayMode.PrimaryHidden || splitViewController!.displayMode == UISplitViewControllerDisplayMode.PrimaryOverlay {
        let displayModeButton = splitViewController!.displayModeButtonItem()
        let searchButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Search, target: displayModeButton.target, action: displayModeButton.action)
        navigationItem.leftBarButtonItem = searchButton
    } else {
        navigationItem.leftBarButtonItem = nil
    }
}

SplitViewController:

func splitViewController(svc: UISplitViewController, willChangeToDisplayMode displayMode: UISplitViewControllerDisplayMode) {
    svc.view.setNeedsLayout()
}

Upvotes: 2

nemesys
nemesys

Reputation: 554

The problem with all the above solutions is that the back button image is not displayed, at least not in my project where I tried to create my own custom bar button item. When using the UISplitViewController displayModeButtonItem and setting the master view controller left bar button item to supplement the back button item (controller.navigationItem.leftItemsSupplementBackButton = YES), the little < symbol appears before the left bar button item title. With a custom one, it doesn't.

Upvotes: 0

EmilDo
EmilDo

Reputation: 1177

doing that in targetDisplay does the trick but removal/addition of the button is visible at the end of the rotation, it is better to do that in splitViewController:willChangeToDisplayMode:displayMode but keep in mind that this should also be handled on viewDidLoad too since that delegate method is not called at startup.

 - (void)splitViewController:(UISplitViewController *)svc willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode
    {
        if (displayMode == UISplitViewControllerDisplayModePrimaryHidden || displayMode == UISplitViewControllerDisplayModePrimaryOverlay) {
            self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Lista" style:UIBarButtonItemStylePlain target:self.splitViewController.displayModeButtonItem.target action:self.splitViewController.displayModeButtonItem.action];
        } else {
           self.navigationItem.leftBarButtonItem = nil;
        }
    }

Upvotes: 4

Rodrigo Gonzalez
Rodrigo Gonzalez

Reputation: 723

I made a combination of josh's and voluntas88's solutions on my solution.

First you need to use the UISplitViewControllerDelegate method func targetDisplayModeForActionInSplitViewController(_ svc: UISplitViewController) -> UISplitViewControllerDisplayMode and then add a customized UIBarButtonItem. Here is my solution:

func targetDisplayModeForActionInSplitViewController(svc: UISplitViewController) -> UISplitViewControllerDisplayMode {
        if svc.displayMode == UISplitViewControllerDisplayMode.PrimaryHidden || svc.displayMode == UISplitViewControllerDisplayMode.PrimaryOverlay {
            self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named:"menu.png"),
                landscapeImagePhone: UIImage(named:"menu.png"),
                style: UIBarButtonItemStyle.Plain,
                target: self.splitViewController!.displayModeButtonItem().target,
                action: self.splitViewController!.displayModeButtonItem().action)
        }else {
// disable button on landscape
            if UIApplication.sharedApplication().statusBarOrientation == UIInterfaceOrientation.LandscapeLeft || UIApplication.sharedApplication().statusBarOrientation == UIInterfaceOrientation.LandscapeRight {
                self.navigationItem.leftBarButtonItem?.enabled = false
            }
        }
        return UISplitViewControllerDisplayMode.Automatic
    }

Upvotes: 5

bolnad
bolnad

Reputation: 4583

So i was looking for a way to implement a custom button on my UISplitViewController, the button that shows the RootViewController (the side drawer or overlay, whatever its called). I came to this page and the question is to change the button that is being sent from the UISplitViewControllerDelegate. It appears that there is no call that you can implement in that delegate but you can just set the button to be a custom bar button item

On the DetailViewController, the nondrawer, overlay view, you just need to declare it and point the action and target of your custom button to be the same as what the UISplitViewController's button is

self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self.splitViewController!.displayModeButtonItem().target, action: self.splitViewController!.displayModeButtonItem().action) 

Upvotes: 0

voluntas88
voluntas88

Reputation: 241

I resolved it for myself in such way:

UIBarButtonItem(image: UIImage(named:"home"),
            landscapeImagePhone: UIImage(named:"home"),
            style: UIBarButtonItemStyle.Plain,
            target: splitViewController.displayModeButtonItem().target,
            action: splitViewController.displayModeButtonItem().action)

I use this in AppDelegate instead of splitViewController.displayModeButtonItem() and it works fine for me.

Upvotes: 21

Related Questions