5

我想UIViewController在 iPad 中显示一个带有自定义框架的模式,以它的父视图控制器为中心。

我尝试使用表单,但据我所知框架和阴影效果无法更改。

vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:cv animated:YES];

我也尝试过使用弹出框,但据我所知,要么无法居中,要么无法隐藏箭头。

还有另一种显示模式视图控制器的方法吗?是否可以通过使用表单或弹出框来解决此问题?

4

5 回答 5

6

我正在使用以下方法创建一个以屏幕为中心的任何给定大小的模态视图控制器。如果需要,您可以将其更改为在父视图控制器中居中。这是从情节提要中工作的,因此您也许可以将视图控制器作为参数发送。但除此之外,它还可以满足您的需求。

注意:我发现如果您尝试在此模式上显示另一个模式,它将返回到原始大小。

- (UIViewController *) presentModalViewControllerWithIdentifier:(NSString *)identifier 
                                                        andSize:(CGSize)size 
                                        andModalTransitionStyle:(UIModalTransitionStyle)modalTransitionStyle {
    UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:identifier];


    viewController.modalPresentationStyle = UIModalPresentationPageSheet;
    viewController.modalTransitionStyle = modalTransitionStyle;
    [self presentModalViewController:viewController animated:YES];
    viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin | 
    UIViewAutoresizingFlexibleLeftMargin | 
    UIViewAutoresizingFlexibleRightMargin;    
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    viewController.view.superview.frame = CGRectMake(0, 0, size.width, size.height);
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds), CGRectGetMidY(screenBounds));
    viewController.view.superview.center = UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? center : CGPointMake(center.y, center.x);

    return viewController;
}

如果这是您唯一想要的,它可以正常工作。但我发现 Apple 对模态视图控制器的实现有点适得其反,因为您无法访问它的任何底层部分,因此您无法完全为它们设置动画。如果您想拥有自己的过渡,这很有用。

它也不属于子视图控制器的类别,因为它位于窗口中的所有其他视图之上。

于 2012-08-15T09:53:15.310 回答
4

没有官方方法可以做到这一点,但是您可以通过编写自定义视图来获得所需的行为,该视图保留引用或委托以与其呈现的视图控制器进行交互并将其添加到视图层次结构中。要真正获得模态的感觉,您还可以在“模态”视图下方的呈现控制器上放置一个透明覆盖层。我已经在许多应用程序中做到了这一点,而且通常效果很好。您可能需要制作自定义叠加视图,以便您可以拦截触摸并更优雅地为其演示设置动画。

我的透明覆盖通常是这样的:

@protocol TransparentOverlayDelegate <NSObject>

@optional
- (void)transparentOverlayWillDismiss:(TransparentOverlay *)backgroundTouch;
- (void)transparentOverlayDidDismiss:(TransparentOverlay *)backgroundTouch;
@end


@interface TransparentOverlay : UIView {

    id<TransparentOverlayDelegate> _delegate;
    UIView *_contentView;
    CGFloat _pAlpha;
}

@property(nonatomic, assign) id<TransparentOverlayDelegate> delegate;
@property(nonatomic, retain) UIView *contentView;
@property(nonatomic, assign) CGFloat pAlpha;

- (void)presentTransparentOverlayInView:(UIView *)view;
- (void)dismissTransparentOverlay:(BOOL)animated;

我的自定义模式视图通常是这样的:

@protocol ModalViewDelegate <NSObject>
- (void)performSelectorOnDelegate:(SEL)selector;
@end

@interface ModalView : UIView {
    id<ModalViewDelegate> _delegate;
}

@property(nonatomic, assign) id<ModalViewDelegate> delegate;

在我展示的视图控制器中,我通常会执行以下操作:

- (void)presentModalController {
    TransparentOverlay *to = [[[TransparentOverlay alloc] initWithFrame:self.view.bounds] autorelease];
    to.delegate = self;

    ModalView *mv = [[ModalView alloc] initWithFrame:CGRectMake(500, 500, 300, 300)];
    mv.delegate = self;

    to.contentView = mv;
    [mv release];

    [to presentTransparentOverlayInView:self.view]; 
}

使用在这两个类上定义的委托给了我非常开放的访问权限来操作我的演示控制器以及我的演示和解散。唯一的缺点是当它在带有 NavigationBar 的视图上使用时,因为呈现控制器的视图的边界不会包含 NavigationBar 的边界,使其保持打开状态以进行交互,有一些方法可以解决这个问题,但不是其中的一种非常漂亮(添加到导航控制器的视图是一种选择)。

于 2012-01-28T14:53:28.500 回答
1

这可能无法完全回答您的问题。但是我从之前放置在 splitviewcontroller 详细视图顶部的导航控制器上的 rightbuttonitem 调用以下代码。

这个模态视图覆盖了整个屏幕。例如,您是否只想在 detailviewcontroller 中调用时才覆盖详细视图?

- (void)aboutAction {

About *about = [[About alloc] init];
UINavigationController *nav1 = [[UINavigationController alloc]initWithRootViewController:about];
[about release];
nav1.navigationBar.barStyle = UIBarStyleBlackOpaque;
nav1.modalPresentationStyle = UIModalPresentationFullScreen;
nav1.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:nav1 animated:YES ];
[nav1 release];

}
于 2011-02-10T21:39:25.930 回答
1

在我的情况下,覆盖viewWillLayoutSubviews就可以了。

- (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];

    self.view.superview.frame = CGRectMake(100.f, 100.f, <width>, <height>); 
}

无需再更改ModalViewController.

于 2014-07-31T19:14:25.313 回答
1

我更喜欢 fabio-oliveira 的回答,但它需要一些调整才能使其在 IOS 7 的多线程环境中工作:

- (UIViewController *)presentModalViewControllerWithId:(NSString *)identifier
                                           andSize:(CGSize)size
                           andModalTransitionStyle:(UIModalTransitionStyle)style
{
    UIViewController *viewController = 
            [self.storyboard instantiateViewControllerWithIdentifier:identifier];

    viewController.modalPresentationStyle = UIModalPresentationPageSheet;
    viewController.modalTransitionStyle = style;

    [self presentViewController:viewController animated:YES completion:nil];

    viewController.view.superview.autoresizingMask = 
        UIViewAutoresizingFlexibleTopMargin    |
        UIViewAutoresizingFlexibleBottomMargin | 
        UIViewAutoresizingFlexibleLeftMargin   | 
        UIViewAutoresizingFlexibleRightMargin;

    viewController.view.superview.frame = 
                   CGRectMake(0, 0, size.width, size.height);

   return viewController;
}

现在将居中代码放在目标 VC 中,以便新线程完成工作:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    CGPoint center = CGPointMake(CGRectGetMidX(screenBounds),
                                 CGRectGetMidY(screenBounds));

    self.view.superview.center =
    UIDeviceOrientationIsPortrait(self.interfaceOrientation) ? 
                                       center : CGPointMake(center.y, center.x);
}

哦是的,如果你支持那些可爱的 IOS 5 iPad 1,一定要让目标 vc 旋转:

- (BOOL)shouldAutorotateToInterfaceOrientation:
                         (UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}
于 2013-10-13T22:12:35.920 回答