【问题标题】:How to resize a UIModalPresentationFormSheet?如何调整 UIModalPresentationFormSheet 的大小?
【发布时间】:2026-01-04 23:55:02
【问题描述】:

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

composeTweetController = [[ComposeTweet alloc] initWithNibName:@"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:composeTweetController animated:TRUE];

有什么想法吗?我正在使用 iPhone SDK 3.2 beta 4

【问题讨论】:

  • 测试版在保密协议下,所以我怀疑你会在这里得到很多答案。我建议使用 Apple 的 SDK 3.2 Beta 论坛devforums.apple.com

标签: iphone objective-c cocoa-touch uikit


【解决方案1】:

视图大小是固定的。如果你想要不同的东西,你必须自己实现。

【讨论】:

  • 这不是错误的,也与您的答案不符。在我的书中,修改视图控制器的视图的父视图的帧算作“不同的东西”。
【解决方案2】:

您可以在展示模态视图后调整它的框架:

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

【讨论】:

  • 它在 iPad 上也适用于我,但是...如果我旋转设备,视图不会居中
  • @MauroDelrio 要使其在横向上正常工作,您需要翻转中心坐标。例如:CGPoint 中心 = self.view.center; targetController.view.superview.center = {isPortrait} ?中心 : CGPointMake(center.y, center.x);
  • 小心这种方法,由于缩放,它会导致视图控制器的视图出现一些失真。
  • 不错的解决方案。我更喜欢像这样targetController.view.superview.frame = CGRectInset(targetController.view.superview.frame, 110, 70);
  • 需要IOS7解决方案
【解决方案3】:

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 bounds & center
【解决方案4】:

我从UIPresentationFormSheet 获得了全屏模式视图,仅此行:

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

【讨论】:

    【解决方案5】:

    @bdrobert 遗憾的是,您的好解决方案在 iOS6 上不再适用 - 即使新的视图控制器嵌入了自定义大小,容器仍保持原始大小。

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

    【讨论】:

    • @Austin:我最近使用了遏制 API,但不是出于此目的。对我来说,回到原来的大小是可以接受的。
    • 这是我在这里看到的最好的解决方案。修改视图的父视图的大小,无论是通过改变边界还是框架,都是自找麻烦。它假定您无法控制的视图层次结构的特定实现知识。
    【解决方案6】:

    使用 XCode 4.5 测试并适用于 iOS 6

    在阅读了这里的大部分提示后,我偶然发现了我的答案:

    1. viewWillAppear:(BOOL)animated 方法中:

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

      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}。去图吧。

    【讨论】:

    • 这个解决方案的问题是在transitionStyle完成后工作表改变了中心
    • @FedeCugliandolo - 你是对的。上述方法仅在您使用交叉淡入淡出过渡样式或根本不设置动画时才有效。我最终没有动画演示,然后使用我自己的动画。
    • 对我不起作用 :( 表单的大小仍然相同
    • 在 iOS7 上 UIModalTransitionStyleCoverVertical 也有问题!但是使用 UIModalTransitionStyleCrossDissolve 效果很好
    【解决方案7】:

    在改变方向时,此代码完美运行....

    settingViewController.modalPresentationStyle = UIModalPresentationFormSheet;

        [self presentViewController:settingViewController animated:YES completion:nil];
    
        settingViewController.view.superview.frame = CGRectMake(0, 0, 700, 700);
    
        UIInterfaceOrientation currentOrientation = [self getDeviceOrientation];
    
        if(currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
        {
                CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2);
                settingViewController.view.superview.center = centerPoint;
        }
        else
        {
            CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.height/2, [[UIScreen mainScreen] bounds].size.width/2);
            settingViewController.view.superview.center = centerPoint;
        }
    

    【讨论】:

      【解决方案8】:

      iOS 7

      所以设置超级视图的框架或边界的方法在 iOS 7 上不再起作用(对于 UIModalTransitionStyleCoverVertical)。但是,您现在可以将 superview 的背景颜色设置为清除,然后根据您认为合适的方式更改模态视图控制器的框架。

      所以在 iOS 7 中你会想要:

      1. 呈现视图控制器(呈现模式:UIModalPresentationFormSheet)
      2. 将视图控制器超级视图背景颜色设置为清除
      3. 根据需要更改视图控制器的框架(可能使其更小,然后在超级视图中居中)

      【讨论】:

      • 不需要在超级视图中居中视图。只需将边界(在-presentViewController:animated:completionHandler 之后)设置为(0, 0, width, height) 即可使其自动居中。
      • 在不使用背景颜色的情况下设置边界对我来说效果很好。 (我的视图控制器在导航控制器中。不确定这是否重要。)
      【解决方案9】:

      这适用于任何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;
      }
      

      【讨论】:

      • 太棒了!做得好!我很想知道为什么这样做的原因! :)
      • 苹果在布局计算中使用_formSheetSize。我是真实尺寸的替代品;我在加载时从 xib 框架中获取的实际大小;
      • 谢谢!您是如何找到类方法/属性 formSheetSize 的?私有标头?
      • 停留在 presentViewController:animated:comletion 并在调试器中检查 UIViewController。我使用直觉方法:)
      • 哇,这是一些聪明的“黑客”荣誉!我什至不知道你能做到这一点!写一篇教程博文??? :)
      【解决方案10】:

      下面是第一个代码是如何呈现你的模型视图控制器

       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 坐标的解决方案。
      【解决方案11】:

      这是一种适用于 iOS7 以及 iOS5 和 iOS6 的方法:(arc)

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

      【讨论】:

      • 这适用于我在 iOS 7 上,谢谢。我收到了关于[rootController presentModalViewController:nav animated:YES]; 的弃用警告,指出从iOS 6 开始不再支持presentModalViewController。我认为新方法是presentViewController。再次感谢,干得好。
      • 在两个 iOS 版本下更改大小的有效解决方案。
      • 如果新尺寸大于旧尺寸并且我在该区域有可点击的项目,它们将不再可点击...我该如何解决?
      【解决方案12】:

      从 iOS7 开始,您可以简单地做

      composeTweetController.preferredContentSize = CGSizeMake(380.0, 550.0);
      

      【讨论】:

        【解决方案13】:

        现代ios13方式:

        使用弹出框(表单和页面忽略首选内容大小)

        然后设置或覆盖 preferredContentSize aka Ed Pilowat & Co

        【讨论】:

          最近更新 更多