如何调整UIModalPresentationFormSheet的大小?

46

我正在尝试将一个modal视图控制器显示为UIPresentationFormSheet。视图出现了,但是我似乎无法调整它的大小。我的XIB具有正确的高度和宽度,但是当我像这样调用它时,它似乎被覆盖:

composeTweetController = [[ComposeTweet alloc] initWithNibName:@"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:composeTweetController animated:TRUE];
任何想法吗?我正在使用iPhone SDK 3.2 beta 4。

有什么建议吗?我正在使用iPhone SDK 3.2 beta 4。


Beta版属于NDA条款,因此我怀疑你在这里不会得到很多答案。我建议使用苹果公司位于http://devforums.apple.com的SDK 3.2 Beta论坛。 - Martin Gordon
13个回答

90
您可以在显示模态视图后调整其框架:
测试过的iOS版本为5.1-7.1。
MyModalViewController *targetController = [[[MyModalViewController alloc] init] autorelease];
targetController.modalPresentationStyle = UIModalPresentationFormSheet;
targetController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;  //transition shouldn't matter
[self presentViewController:targetController animated:YES completion:nil];

if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1){
     targetController.view.superview.frame = CGRectInset(targetController.view.superview.frame, 100, 50);
}else{
     targetController.view.frame = CGRectInset(targetController.view.frame, 100, 50);
     targetController.view.superview.backgroundColor = [UIColor clearColor];
}

6
这在我的iPad上也起作用,但是...... 如果我旋转设备,视图就不居中了。 - Mauro Delrio
4
为了使其在横屏模式下正常工作,您需要翻转中心坐标。例如: CGPoint center = self.view.center; targetController.view.superview.center = {isPortrait} ? center : CGPointMake(center.y, center.x); - Nate Weiner
3
注意这种方法可能会导致视图控制器中的视图出现扭曲,因为它涉及缩放。 - Ralphleon
1
不错的解决方案。我更喜欢像这样改变边界 targetController.view.superview.frame = CGRectInset(targetController.view.superview.frame, 110, 70); - stigi
2
需要解决IOS7的问题。 - Codesen
显示剩余11条评论

12

iOS7起,您可以简单地执行以下操作:

composeTweetController.preferredContentSize = CGSizeMake(380.0, 550.0);

1
这是正确的做法。即使在文档中也指出:“要提供自定义内容大小,请使用模态视图控制器的preferredContentSize属性。” - JPetric

12

这里有一个方法可以在iOS7以及iOS5和iOS6上使用:(自动引用计数)

-(void)presentController:(UIViewController*)controller fromRootController:(UIViewController*)rootController withSize:(CGSize)size
{
    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:controller];
    nav.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    nav.modalPresentationStyle = UIModalPresentationFormSheet;
    [rootController presentModalViewController:nav animated:YES];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
    {
        nav.view.superview.backgroundColor = [UIColor clearColor];
        nav.view.bounds = CGRectMake(0, 0, size.width, size.height);
    }
    else
    {
        nav.view.superview.bounds = CGRectMake(0, 0, size.width, size.height);
    }
}

1
这在我的iOS 7上可行,谢谢。我在[rootController presentModalViewController:nav animated:YES];上收到了一个弃用警告,指出自iOS 6起不再支持presentModalViewController。我认为新方法是presentViewController。再次感谢,做得很好。 - Clifton Labrum
适用于两个iOS版本更改大小的可行解决方案。 - Nikolay Spassov
如果新的尺寸比旧的尺寸大,并且该区域中有可点击的项目,则它们将不再可点击...我该如何解决? - Nava Carmon

11

composeTweetController = [[ComposeTweet alloc] initWithNibName:@"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:composeTweetController animated:TRUE];
//if you want to change its size but the view will remain centerd on the screen in both portrait and landscape then:
composeTweetViewController.view.superview.bounds = CGRectMake(0, 0, 320, 480);
//or if you want to change it's position also, then:
composeTweetViewController.view.superview.frame = CGRectMake(0, 0, 320, 480);


我认为你可以只设置 frame boundscenter - nielsbot

4

这将适用于任何 UIModalTransitionStyle

@interface BaseDialog ()

@property(nonatomic,assign) CGRect origFrame;

@end

@implementation BaseDialog

-(void)viewDidLoad{
    [super viewDidLoad];
    self.origFrame=self.view.frame;
}
-(CGSize)formSheetSize{
    return self.origFrame.size;
}

太棒了!干得好!不过,我很想知道这个为什么能够工作的原因! :) - iOSProgrammingIsFun
1
苹果在布局计算中使用了_formSheetSize。我进行了覆盖以获取实际大小;我在加载时从xib框架中获取实际大小。 - john07
谢谢!你是怎么找到类方法 / 属性 formSheetSize 的?私有头文件吗? - iOSProgrammingIsFun
请继续留在 "presentViewController:animated:completion" 并在调试器中检查 UIViewController。我使用直觉方法 :) - john07
哇,这是一些聪明的“黑客”技巧!我甚至不知道你可以这样做!写一个教程博客文章吗? :) - iOSProgrammingIsFun
我很难写教程。我不会说英语,只能读写2-3个相关单词。这里有人写教程吗? - john07

4

以下是如何呈现您的模型视图控制器的第一段代码:

 composeTweetController = [[ComposeTweet alloc] initWithNibName:@"ComposeTweet" bundle:nil];
    composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:composeTweetController];
    navigationController.delegate = self;   
    [self presentModalViewController:navigationController animated:YES];

在您的ComposeTweet控制器类中:
-(void)viewWillAppear:(BOOL)animated
{
 [super viewWillAppear:animated];
 self.navigationController.view.superview.frame = CGRectMake(0, 0,500,400);
}

+1 - 这是我能找到的唯一一个尊重您设置的x,y坐标的解决方案。 - Lizza

4

已经测试并适用于iOS 6,使用XCode 4.5

在阅读了这里的许多提示后,我偶然找到了答案:

  1. In the viewWillAppear:(BOOL)animated method:

    [super viewWillAppear:animated];
    
     //resize modal view
     self.view.superview.bounds = CGRectMake(0, 0, 432, 680);
    
  2. In the viewDidAppear:(BOOL)animated method:

    CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2);
    self.view.superview.center = centerPoint;
    

我尝试将居中代码放在与调整大小代码相同的位置,但没有起作用。由于某种原因,它只能在视图出现在屏幕上后才起作用。

我猜想这与UIModalPresentationFormSheet的工作方式有关,因为当我在LLDB调试器中逐步执行时,我注意到还有一个变量_formSheetSize,它仍然是{540,620}。真是奇怪。


2
这个解决方案的问题是,在transitionStyle完成后,表格会改变其中心。 - Fede Cugliandolo
1
@FedeCugliandolo - 你说得对。上述方法只适用于使用交叉淡入淡出转场样式或根本不进行动画的情况。我最终选择了没有动画的演示,然后使用自己的动画。 - Jon
对我不起作用 :( 表单表仍然具有相同的大小 - Petr Peller
1
在iOS7上,UIModalTransitionStyleCoverVertical也存在缺陷!但是使用UIModalTransitionStyleCrossDissolve就可以正常工作。 - Carlos Ricardo

3

iOS 7

在iOS 7中,使用设置superview的frame或bounds的方法(对于UIModalTransitionStyleCoverVertical)不再适用。但是,您现在可以将superview的背景颜色设置为clear,然后根据需要更改模态视图控制器的frame。

所以在iOS 7中,您需要:

  1. 呈现视图控制器(presentation mode: UIModalPresentationFormSheet)
  2. 将视图控制器superview的背景颜色设置为clear
  3. 根据需要更改视图控制器的frame(例如,使其更小,然后将其居中在superview中)

不需要将视图居中于父视图中。只需在 -presentViewController:animated:completionHandler 后设置边界为 (0, 0, width, height),它就会自动居中。 - colincameron
在我的情况下,设置边界限制没有使用背景颜色也可以正常工作。(我的视图控制器位于导航控制器中。不确定此处是否有影响。) - arsenius

2

我只需一行代码,即可从 UIPresentationFormSheet 得到一个全屏模态视图:

modalViewController.view.superview.bounds = CGRectMake(0, 0, 1024, 748);

2

@bdrobert很遗憾,您的好方法在iOS6上不再起作用——即使使用自定义尺寸嵌入新视图控制器,容器仍保持原始大小。

您可能需要使用在iOS5中引入的容器API,但您需要自己添加一个暗色背景,并获取该区域的所有触摸事件。


@Austin:我最近使用了包含 API,但不是为了这个目的。对我来说,回到原始大小是可以接受的。 - Oliver Michalak
这是我在这里看到的最佳解决方案。修改视图的父视图大小,无论是通过更改边界还是框架,都是在寻求麻烦。它假定了您不控制的视图层次结构的位的实现特定知识。 - jdc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接