Change the width of Master in UISplitViewController

前端 未结 16 1622
自闭症患者
自闭症患者 2020-11-28 05:55

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 a

相关标签:
16条回答
  • 2020-11-28 06:30
    // in UISplitViewController subclass
    // let more space for detail in portrait mode
    - (void)viewWillLayoutSubviews
    {
        CGFloat width;
        if (UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication.statusBarOrientation)){
            width = CGRectGetWidth(self.view.bounds) * 0.25f;
        }
        else {
            width = CGRectGetWidth(self.view.bounds) * 0.33f;
        }
        width = (NSInteger)fminf(260, fmaxf(120, width));
        self.minimumPrimaryColumnWidth = width;
        self.maximumPrimaryColumnWidth = width;
    
        [super viewWillLayoutSubviews];
    }
    
    0 讨论(0)
  • 2020-11-28 06:31

    In my case, I had to set both maximum and minimum to make this work

    mySplitViewController.preferredDisplayMode = .allVisible;
    mySplitViewController.maximumPrimaryColumnWidth = UIScreen.main.bounds.width/2;
    mySplitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width/2; 
    
    0 讨论(0)
  • 2020-11-28 06:39

    None of the answers worked for me on iOS7, so I did some of my own research and created a working solution. This will involve subclassing UISplitViewController for the full functionality.

    I will present the answer as if we just created a new project for iPad with all device orientations and have set the custom UISplitViewController as the main view controller.

    Create your custom UISplitViewController. In this example mine is called MySplitViewController. All code will be based in MySplitViewController.m.

    We're going to need to access a method from the UISplitViewControllerDelegate so add that and set the delegate. We'll also setup a delegate forwarder incase you need to call the delegate methods from another class.

    @interface MySplitViewController () <UISplitViewControllerDelegate>
    @property (nonatomic, weak) id<UISplitViewControllerDelegate> realDelegate;
    @end
    
    @implementation MySplitViewController
    
    - (instancetype)init {
        self = [super init];
        if (self) {
            self.delegate = self;
        }
        return self;
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            self.delegate = self;
        }
        return self;
    }
    
    - (void)setDelegate:(id<UISplitViewControllerDelegate>)delegate {
        [super setDelegate:nil];
        self.realDelegate = (delegate != self) ? delegate : nil;
        [super setDelegate:delegate ? self : nil];
    }
    
    - (BOOL)respondsToSelector:(SEL)aSelector {
        id delegate = self.realDelegate;
        return [super respondsToSelector:aSelector] || [delegate respondsToSelector:aSelector];
    }
    
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        id delegate = self.realDelegate;
        return [delegate respondsToSelector:aSelector] ? delegate : [super forwardingTargetForSelector:aSelector];
    }
    

    Setup the master and detail view controllers.

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UIViewController* masterViewController = [[UIViewController alloc] init];
        masterViewController.view.backgroundColor = [UIColor yellowColor];
    
        UIViewController* detailViewController = [[UIViewController alloc] init];
        detailViewController.view.backgroundColor = [UIColor cyanColor];
    
        self.viewControllers = @[masterViewController, detailViewController];
    }
    

    Lets add our desired width to a method for easy reference.

    - (CGFloat)desiredWidth {
        return 200.0f;
    }
    

    We'll manipulate the master view controller before presenting it.

    - (void)splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController {
        id realDelegate = self.realDelegate;
    
        if ([realDelegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) {
            [realDelegate splitViewController:svc popoverController:pc willPresentViewController:aViewController];
        }
    
        CGRect rect = aViewController.view.frame;
        rect.size.width = [self desiredWidth];
        aViewController.view.frame = rect;
    
        aViewController.view.superview.clipsToBounds = NO;
    }
    

    However, now we're left with a display like this. enter image description here

    So were going to override a private method. Yes a private method, it will still be acceptable in the App Store since its not an underscore private method.

    - (CGFloat)leftColumnWidth {
        return [self desiredWidth];
    }
    

    This deals with portrait mode. So a similar thing for -splitViewController:willShowViewController:invalidatingBarButtonItem: and you should be set for landscape.

    However none of this will be needed in iOS8. You'll be able to simply call a min and max width property!

    0 讨论(0)
  • 2020-11-28 06:40

    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];
        }
    }
    
    0 讨论(0)
  • 2020-11-28 06:42

    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.

    0 讨论(0)
  • 2020-11-28 06:42

    Here is how I did this in iOS8 with Swift.

    class MainSplitViewController: UISplitViewController {
    
        override func viewDidLoad() {
    
            self.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
            self.maximumPrimaryColumnWidth = 100 // specify your width here
        }
    }
    

    If you need to change the width dynamically from within your master/detail view in the split view, then do something like this:

    var splitViewController = self.splitViewController as MainSplitViewController
    splitViewController.maximumPrimaryColumnWidth = 400
    
    0 讨论(0)
提交回复
热议问题