透明视图控制器

3

我正在使用UIViewController进行推送

[otherController presentViewController: newController animated: NO completion: nil];

新控制器的nib文件包含一个基本视图、一个较小的视图、一个文本框和一些按钮。我希望基本视图是半透明灰色的,这样我就可以看到它下面的视图控制器,同时让用户知道其他视图被禁用了。

我尝试将Alpha值设置为低(这使我的其他控件变得透明),将视图背景设置为透明黑色并取消Opaque标志。但这些方法都不起作用,我只能得到一个不透明的浅灰色背景。

以下是我的视图控制器:

@interface MyEditQueryViewController : UIViewController

@property (nonatomic, strong) id<MyEditQueryDelegate> delegate;
@property (nonatomic, strong) IBOutlet UITextField* textField;
@property (nonatomic, strong) IBOutlet UIView* editView;
@property (nonatomic, strong) IBOutlet UIButton* cancelButton;
@property (nonatomic, strong) IBOutlet UIButton* saveButton;
@property (nonatomic, strong) NSString* defaultText;
@property (nonatomic) CGFloat verticalOffset;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
- (id)initWithDefaultText:(NSString*)defaultText orign:(CGPoint)origin;

- (IBAction)cancelTapped:(id)sender;
- (IBAction)saveTapped:(id)sender;
@end

有没有办法使这个视图半透明?
2个回答

1
在iPhone上,除了使用UIAlertView和UIActionSheet之外,实现这一目标的唯一方法是将UIView作为UIViewController的子视图呈现,以作为背景视图。您呈现的UIView可以占用整个屏幕,并使用透明/半透明视图来实现调暗效果。
在iPad上,除了UIAlertViewUIActionSheet,您还可以模态呈现不是全屏的视图。 这些视图有自己的视图控制器。 为此,您需要将UIModalPresentationStyle设置为以下之一:
  • UIModalPresentationPageSheet

  • UIModalPresentationFormSheet

但是,在我的看法中,这两个选项在大小和位置方面都有一些限制,因此,如果您想进行全面定制,您必须像我为iPhone解释的那样,通过在作为背景视图的UIViewController上呈现单独的UIView来完成。
除了iPad上的UIModalPresentationPageSheetUIModalPresentationFormSheet选项外,为视图控制器设置透明/半透明背景将假定在您可以设置颜色的最后一层背景之后有一个白色背景。

需要注意的是,UIAlertViewUIActionSheet被苹果公司设计为应该按原样使用,不应该被子类化,而你可以随意子类化UIView以获得所需的外观。


你是说除了UIViewController默认拥有的那个UIView之外,还有另一个UIView吗? - kwiqsilver
是的。将一个子视图添加到 UIViewControllerview 中。 - nhgrif
在nib文件中,我在“View”下添加了一个透明度为0.5、黑色背景的视图,但我仍然看不到其他视图控制器的内容。它们都是灰色的。 - kwiqsilver
@kwiqsilver - 我自己不使用这种方法,但你确定它不起作用吗?我以前见过这种方法被接受为答案。 - Jasper Blues
1
@JasperBlues 在工作中,我正在使用与您的答案解释类似的方法...主要是因为我需要在其他几个视图控制器中使用相同的视图,但我的答案提供了kwiqsilver所追求的最基本的实现。 - nhgrif
显示剩余3条评论

0

当使用自定义RootViewController来管理其自己的容器视图时,这种事情就变得很容易了。根视图控制器可以定义自己的导航系统或委托给标准的UIKit组件。

这也有一个优点,即能够使用特定于领域的语言 - 在Root VC的接口中建模您的特定应用程序的方法名称 - 例如[rootViewController presentMenuItem:menuItem]。

我有一个使用根视图控制器的应用程序示例here

这里还有另一个代码片段(来自另一个应用程序),它显示具有半透明背景的覆盖层:

- (void)presentOverlayViewController:(UIViewController*)viewController
{
    LogDebug(@"Presenting overlay view controller: %@", viewController);
    if (_overlayViewController)
    {
        [self dismissOverlayViewController];
    }

    [self.view setUserInteractionEnabled:NO];
    [self.view bringSubviewToFront:_tintView];
    [_tintView setAlpha:0.0];
    [self.view bringSubviewToFront:_overlayViewContainer];
    _overlayViewController = viewController;

    CGSize screenSize = [[UIScreen mainScreen] currentSize];

    [viewController willMoveToParentViewController:self];
    [_overlayViewContainer addSubview:viewController.view];
    [_overlayViewController.view setPosition:(CGPoint) {(screenSize.width / 2) - (_overlayViewController.view.frame.size.width / 2),
            (screenSize.height / 2) - (_overlayViewController.view.frame.size.height / 2)}];

    __weak UIView* overlayViewContainer = _overlayViewContainer;
    __weak UIView* view = self.view;
    __weak UIView* tintView = _tintView;
    [UIView transitionWithView:self.view duration:0.60 options:UIViewAnimationOptionCurveEaseInOut animations:^
    {
        [tintView setAlpha:0.7];
        CGRect newFrame = overlayViewContainer.frame;
        newFrame.origin.y -= screenSize.height;
        [overlayViewContainer setUserInteractionEnabled:YES];
        overlayViewContainer.frame = newFrame;
    } completion:^(BOOL complete)
    {
        [viewController didMoveToParentViewController:self];
        [view setUserInteractionEnabled:YES];
    }];
}

这种方法适用于iOS或iPad,实际上可以编写成同时适用于两者。

编辑:

如果您还没有将自定义根视图控制器设置为UIWindow的根VC,则仍然可以通过在将呈现半透明覆盖层的VC上添加相同的方法来实现此操作。

编辑2:

请注意添加:

 [viewController willMoveToParentViewController:self];
 [viewController didMoveToParentViewController:self];

正如Jesse Rusak指出的那样,这些是必需的。


这很有道理,但你需要使用UIViewController的容器API,而不仅仅是从视图控制器中获取视图。 - Jesse Rusak
1
是的,还有旋转、视图卸载、事件处理等等,都会在一些意想不到的情况下出现问题或造成麻烦。在iOS 5之前基本上是不支持这样做的,因此最好至少调用那些API以正确地实现它。 - Jesse Rusak
支持子视图,但不支持属于不同视图控制器的子视图。 - Jesse Rusak
@JesseRusak 哇 - 我不知道这在 IOS5 之前是特别不支持的。我只是认为这需要更多的工作. . . 实际上,甚至在 iOS5 之前也使用了同样的方法!无论如何 - 感谢您的提示。 - Jasper Blues
1
我能找到的最正式的文档来自于苹果的UIViewController文档:“在将子视图的根视图添加到视图层次结构之前,您的容器视图控制器必须将一个子视图控制器与其关联。”我相信在某个WWDC视频中一定有相关内容... :) - Jesse Rusak

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