Change the width of Master in UISplitViewController

42,459

Solution 1

If you subclass UISplitViewController, you can implement -viewDidLayoutSubviews and adjust the width there. This is clean, no hacks or private APIs, and works even with rotation.

- (void)viewDidLayoutSubviews
{
    const CGFloat kMasterViewWidth = 240.0;

    UIViewController *masterViewController = [self.viewControllers objectAtIndex:0];
    UIViewController *detailViewController = [self.viewControllers objectAtIndex:1];

    if (detailViewController.view.frame.origin.x > 0.0) {
        // Adjust the width of the master view
        CGRect masterViewFrame = masterViewController.view.frame;
        CGFloat deltaX = masterViewFrame.size.width - kMasterViewWidth;
        masterViewFrame.size.width -= deltaX;
        masterViewController.view.frame = masterViewFrame;

        // Adjust the width of the detail view
        CGRect detailViewFrame = detailViewController.view.frame;
        detailViewFrame.origin.x -= deltaX;
        detailViewFrame.size.width += deltaX;
        detailViewController.view.frame = detailViewFrame;

        [masterViewController.view setNeedsLayout];
        [detailViewController.view setNeedsLayout];
    }
}

Solution 2

In IOS 8.0 you can easily do this by doing the following:

1. In your MasterSplitViewController.h add

@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0);

2. In your MasterSplitViewController.m viewDidLoad method add

 self.maximumPrimaryColumnWidth = 100;
 self.splitViewController.maximumPrimaryColumnWidth = self.maximumPrimaryColumnWidth;

This is a really good, simple and easy feature of IOS 8.

Solution 3

this code is work for me

[splitViewController setValue:[NSNumber numberWithFloat:200.0] forKey:@"_masterColumnWidth"];

Solution 4

No.


There are two private properties

@property(access,nonatomic) CGFloat masterColumnWidth;
@property(access,nonatomic) CGFloat leftColumnWidth; // both are the same!

but being private mean they can't be used for AppStore apps.

Solution 5

iOS 8 introduced a new property:

// An animatable property that can be used to adjust the maximum absolute width of the primary view controller in the split view controller.
@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0); // default: UISplitViewControllerAutomaticDimension

Use this property to adjust your master viewcontroller to your desired width.

Share:
42,459

Related videos on Youtube

Raj Pawan Gumdal
Author by

Raj Pawan Gumdal

Updated on April 11, 2020

Comments

  • Raj Pawan Gumdal
    Raj Pawan Gumdal about 4 years

    The iPad programming guide says that the splitView's left pane is fixed to 320 points. But 320 pixels for my master view controller is too much. I would like to reduce it and give more space to detail view controller. Is it possible by anyway?

    Link to the document which speaks about fixed width.

    • oliveryas01
      oliveryas01 over 13 years
      Why not try Matt Gemmell's excellent MGSplitViewController? It's open source, and is available on GitHub. Gregor, Sweden
  • Raj Pawan Gumdal
    Raj Pawan Gumdal about 14 years
    Thanks, but I am not going to use the private APIs, rather I would implement own split view controller . . .
  • nacho4d
    nacho4d almost 14 years
    I know that privates can be modified using categories like this one, but this is the second time I try it and getting the same error:"_OBJC_IVAR_$_UISplitViewController._masterColumnWidth‌​", referenced from: _OBJC_IVAR_$_UISplitViewController._masterColumnWidth$non_la‌​zy_ptr in UISplitViewController+myExt.o (maybe you meant: _OBJC_IVAR_$_UISplitViewController._masterColumnWidth$non_la‌​zy_ptr) Symbol(s) not found. Collect2: ld returned 1 exit status
  • Raj Pawan Gumdal
    Raj Pawan Gumdal over 13 years
    I am afraid that we will be changing the private properties in this case. Better not do it. Who knows, Apple might decide to change its class hierarchy?
  • Dan Rosenstark
    Dan Rosenstark almost 13 years
    @Raj @pryiyanka, also you're assured rejection in the appstore.
  • Raj Pawan Gumdal
    Raj Pawan Gumdal almost 13 years
    Yes, and thats the reason why I have implemented own SplitViewController, Matt Gamell's splitViewController didnt exist back then but now you can use MGSplitViewController, its good.
  • Kyle Clegg
    Kyle Clegg over 11 years
    @Raj how could I subclass UISplitViewController and only override the masterColumnWidth?
  • Raj Pawan Gumdal
    Raj Pawan Gumdal over 11 years
    @Kyle - Cannot go with the above approach, if you want to submit the app to appstore. Otherwise, if you still insist using it, you dont have to subclass it. See this answer below: stackoverflow.com/a/4022406/260665
  • Kyle Clegg
    Kyle Clegg over 11 years
    @Raj - I need to submit to the App Store. Is there a way to use the answer you suggested in a fashion that Apple will accept? I am assuming the answer is a subclass, or is that bad too?
  • Raj Pawan Gumdal
    Raj Pawan Gumdal over 11 years
    No no, I am changing the accepted answer for posterity sake. You cannot use this approach or even subclass and change the width if you want to submit to appstore. It will be rejected for sure. Use Matt Gemmell's split view controller. See my new accepted answer.
  • Cutetare
    Cutetare over 10 years
    Would this cause the app to be rejected at the AppStore?
  • jrc
    jrc over 10 years
    I don't see why it would, as no private APIs are used.
  • Charlie Seligman
    Charlie Seligman over 10 years
    This worked great for me in landscape but when I went back to portrait the view was shifted left. Any ideas how to resolve that?
  • jrc
    jrc over 10 years
    Good catch. Edited my answer.
  • nigong
    nigong over 10 years
    I can correctly resize the master view, however when the detailViewController.view.frame gets a new value, the app just goes purely black. Any idea?
  • kmiklas
    kmiklas about 10 years
    In iOS7, this worked for me: [self.splitViewController setValue:@78 forKey:@"_masterColumnWidth"];
  • d512
    d512 about 10 years
    This should be the accepted answer. It's ridiculous that Apple makes you jump through hoops like this when they could easily expose a setting, but I'm glad you shared this.
  • lordB8r
    lordB8r almost 10 years
    @nigong I'm getting the same problem. It somehow causes an infinite loop that I cannot get out of. If I don't set detailViewController.view.frame = detailViewFrame, then the masterViewController.view.frame updates correctly, but the detail doesn't. If I uncomment it, I get an infinite loop :(
  • DaSilva
    DaSilva over 9 years
    did you got any solution for the infinite loop? @AndréCytryn
  • Andre Cytryn
    Andre Cytryn over 9 years
    yes. on my subclass I added: self.preferredPrimaryColumnWidthFraction = 0.3 but the thing is that I does not go more than 0.4 I dont know why
  • Bill
    Bill over 9 years
    The black screen only happens on iOS 8. On iOS 8, you don't need this code - use maximumPrimaryColumnWidth instead. On iOS 7, the black screen doesn't occur and @jrc's solution works.
  • Kenny Wyland
    Kenny Wyland over 9 years
    INFINITE LOOP AVOIDANCE: Some change in iOS8 is what causes the infinite loop. To avoid it, we used the above code, but wrapped it in an if() block that checked for the version of iOS. If it's less than 8.0, then use the above code, else, just set: self.maximumPrimaryColumnWidth = masterViewWidth; Please go upvote @SJTriggs and Twan's answers for this solution.
  • romiem
    romiem over 9 years
    Would anyone be able to provide me the Swift equivalent of this code please? I can't seem to get this working in a Swift project.
  • romiem
    romiem over 9 years
    Never mind, I managed to find the solution (although it is a bit different) stackoverflow.com/questions/2949067/…
  • Jason G
    Jason G over 9 years
    add splitViewController.maximumPrimaryColumnWidth = ### to your appdelegate.swift
  • Erik van der Neut
    Erik van der Neut about 9 years
    Infinite loop is obviously very easy to avoid (test whether you already have the width you're after and only change it if you don't), but as Bill pointed out above: use maximumPrimaryColumnWidth on iOS8 and if you still support iOS7, then follow jrc's solution (although I would still improve that with a check of whether you need to adjust the width or not).
  • aroon65
    aroon65 about 9 years
    This approach mostly works (+1) but introduces a secondary problem. There is a transparent view used to detect touches outside the master area and instigate closure of the master. If this view's frame isn't updated to be the same as the detail view's frame, it becomes possible for the user to interact with the details whilst the master is open. To fix this, I did this: this.View.Subviews[2].Frame = detailFrame; straight after setting the detail frame.
  • malhal
    malhal over 8 years
    Since there are many different screen sizes you are better using preferredPrimaryColumnWidthFraction
  • JJack_
    JJack_ almost 8 years
    Used with iOS 10 GM, xCode 8 and Swift 2.3. It works like a charm! :)
  • AppsolutEinfach
    AppsolutEinfach almost 8 years
    Worked still under iOS 9, now under iOS 10 it crashes!
  • Himanshu jamnani
    Himanshu jamnani over 7 years
    It will crash for iOS10