Ios 在UISplitViewController中更改主控形状的宽度

Ios 在UISplitViewController中更改主控形状的宽度,ios,uisplitviewcontroller,ipad,Ios,Uisplitviewcontroller,Ipad,iPad编程指南说splitView的左窗格固定为320点。但是我的主视图控制器的320像素太多了。我想减少它,给细节视图控制器更多的空间。无论如何,有可能吗 链接到说明固定宽度的链接。否 有两个私有属性 @property(access,nonatomic) CGFloat masterColumnWidth; @property(access,nonatomic) CGFloat leftColumnWidth; // both are the same! 但是私有意味着它们不能用于Ap

iPad编程指南说splitView的左窗格固定为320点。但是我的主视图控制器的320像素太多了。我想减少它,给细节视图控制器更多的空间。无论如何,有可能吗

链接到说明固定宽度的链接。


有两个私有属性

@property(access,nonatomic) CGFloat masterColumnWidth;
@property(access,nonatomic) CGFloat leftColumnWidth; // both are the same!
但是私有意味着它们不能用于AppStore应用程序。

这段代码对我来说很有用:)


@接口UISplitViewController(myExt)
-(void)setNewMasterSize:(浮动)大小;
@结束

@实现UISplitViewController(myExt) -(无效)setNewMasterSize:(浮动)大小 { _主列宽度=大小; } @结束


并在每个视图操作中使用它(如旋转)

此代码适合我

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

如果将UISplitViewController作为子类,则可以实现
-viewdilayoutsubviews
,并在其中调整宽度。这是干净的,没有黑客或私人API,甚至可以与旋转一起工作

- (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];
    }
}

在iOS7上,没有一个答案对我有效,所以我做了一些自己的研究,并创建了一个有效的解决方案。这将涉及子类化
UISplitViewController
,以获得完整的功能

我将给出答案,就好像我们刚刚为iPad创建了一个具有所有设备方向的新项目,并将自定义
UISplitViewController
设置为主视图控制器一样

创建自定义的
UISplitViewController
。在本例中,我的名为
MySplitViewController
。所有代码都将基于
MySplitViewController.m

我们需要从
UISplitViewControllerDelegate
访问一个方法,因此添加该方法并设置委托。我们还将设置一个委托转发器,以防您需要从另一个类调用委托方法

@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];
}
让我们将所需的宽度添加到方法中,以便于参考

- (CGFloat)desiredWidth {
    return 200.0f;
}
在显示主视图控制器之前,我们将对其进行操作

- (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;
}
然而,现在我们只剩下这样一个显示屏。

所以我们要重写一个私有方法。是的,它是私有方法,但在应用商店中仍然可以接受,因为它不是下划线私有方法

- (CGFloat)leftColumnWidth {
    return [self desiredWidth];
}
这涉及肖像模式。因此,
-splitViewController:willShowViewController:invalidatingBarButtonItem:
也有类似的情况,您应该设置为横向


但是,iOS8中不需要这些。您可以简单地调用“最小宽度”和“最大宽度”属性

iOS 8引入了一个新属性:

// 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

使用此属性可将主viewcontroller调整到所需的宽度。

在IOS 8.0中,您可以通过执行以下操作轻松完成此操作:

1。在MasterSplitViewController.h中添加

@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0);
 self.maximumPrimaryColumnWidth = 100;
 self.splitViewController.maximumPrimaryColumnWidth = self.maximumPrimaryColumnWidth;
2。在MasterSplitViewController.m viewDidLoad方法中添加

@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0);
 self.maximumPrimaryColumnWidth = 100;
 self.splitViewController.maximumPrimaryColumnWidth = self.maximumPrimaryColumnWidth;

这是IOS 8的一个非常好、简单和容易的特性。

在分配给rootviewcontroller之前,请使用以下代码。它对我来说适用于ios7

[self.splitViewController setValue:[NSNumber numberWithFloat:256.0]forKey:@“\u masterColumnWidth”];

self.window.rootViewController=self.splitViewController

以下是我如何在iOS8中使用Swift实现这一点的

class MainSplitViewController: UISplitViewController {

    override func viewDidLoad() {

        self.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
        self.maximumPrimaryColumnWidth = 100 // specify your width here
    }
}
如果需要在拆分视图的主视图/详细视图中动态更改宽度,请执行以下操作:

var splitViewController = self.splitViewController as MainSplitViewController
splitViewController.maximumPrimaryColumnWidth = 400
你可以用。这个可以在iOS 7和iOS 8上使用

splitView = [[GSSplitViewController alloc] init];
splitView.masterPaneWidth = 180;

您还可以通过将
pod'GSSplitViewController'
添加到您的
pod文件

中来包含它,因为没有人提到这可以通过IB完成,所以我想添加这个答案。显然,您可以使用以下详细信息为UISplitViewContorller设置“用户定义的运行时属性”: 关键路径:masterColumnWidth 类型:编号 值:250
@property(非原子,赋值)CGFloat maximumPrimaryColumnWidth NS\u可用\u IOS(8\u 0)

ViewController.m

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

    if (SYSTEM_VERSION_LESS_THAN(@"10.0")) {

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

    }else{

    self.maximumPrimaryColumnWidth = 200;
    self.splitViewController.maximumPrimaryColumnWidth = self.maximumPrimaryColumnWidth;

     }

故事板的方式是@Tim提到的:

此外,如果希望主视图始终占据屏幕的一定百分比,则可以使用Key Path=“preferredPrimaryColumnWidthFraction”并将该值设置为0.2(屏幕大小为20%)

请注意,“maximumPrimaryColumnWidth”设置为320,因此如果尝试屏幕百分比值0.5(50%),则不会超过320。如果需要覆盖此选项,可以为maximumPrimaryColumnWidth添加键路径。

Swift 3.0

let widthfraction = 2.0 //Your desired value for me 2.0    
splitViewController?.preferredPrimaryColumnWidthFraction = 0.40
let minimumWidth = min((splitViewController?.view.bounds.size.width)!,(splitViewController?.view.bounds.height)!)
splitViewController?.minimumPrimaryColumnWidth = minimumWidth / widthFraction
splitViewController?.maximumPrimaryColumnWidth = minimumWidth / widthFraction
let leftNavController = splitViewController?.viewControllers.first as! UINavigationController
leftNavController.view.frame = CGRect(x: leftNavController.view.frame.origin.x, y: leftNavController.view.frame.origin.y, width: (minimumWidth / widthFraction), height: leftNavController.view.frame.height)

在我的情况下,我必须设置最大值和最小值才能使这项工作正常进行

mySplitViewController.preferredDisplayMode = .allVisible;
mySplitViewController.maximumPrimaryColumnWidth = UIScreen.main.bounds.width/2;
mySplitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width/2; 

谢谢,但我不打算使用私有API,而是实现自己的分割视图控制器@Raj我怎么能将UISplitViewController子类化,只覆盖masterColumnWidth?@Kyle-如果你想将应用提交到appstore,就不能采用上述方法。否则,如果您仍然坚持使用它,则不必对其进行子类化。请看下面的答案:@Raj-我需要提交到应用商店。有没有一种方式可以让苹果接受你建议的答案?我假设答案是一个子类,或者这也很糟糕?不,不,为了子孙后代的缘故,我正在更改被接受的答案。如果要提交到appstore,则不能使用此方法,甚至不能使用子类和更改宽度。它肯定会被拒绝。使用Matt Gemmell的分割视图控制器。看到我新的被接受的答案。我知道私密可以使用这样的类别进行修改,但这是我第二次尝试,并得到相同的错误:“\u OBJC\u IVAR\u$\u UISplitViewController.\u masterColumnWidth”,引用自:\u OBJC\u IVAR\u$\u UISplitViewController.\u masterColumnWidth$non\u lazy\u ptr in UISplitViewController+myExt.o(可能您的意思是:_OBJC_IVAR_$_UISplitViewController._masterColumnWidth$non_lazy_ptr)未找到符号。Collect2:ld返回了1个出口st
// 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];
}