Ios 在UISplitViewController中更改主控形状的宽度
iPad编程指南说splitView的左窗格固定为320点。但是我的主视图控制器的320像素太多了。我想减少它,给细节视图控制器更多的空间。无论如何,有可能吗 链接到说明固定宽度的链接。否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
有两个私有属性
@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];
}