我正在显示一个模态视图
[self presentModalViewController:controller animated:YES];
当视图在屏幕上移动时,根据创建它的 xib 文件中的设置,它是透明的,但是一旦它填满屏幕,它就会变得不透明。
无论如何保持视图透明?
我怀疑它被放置的视图没有被渲染,而不是模态视图变得不透明。
我正在显示一个模态视图
[self presentModalViewController:controller animated:YES];
当视图在屏幕上移动时,根据创建它的 xib 文件中的设置,它是透明的,但是一旦它填满屏幕,它就会变得不透明。
无论如何保持视图透明?
我怀疑它被放置的视图没有被渲染,而不是模态视图变得不透明。
在 iOS 3.2 之后,有一种方法可以做到这一点而无需任何“技巧”——请参阅 modalPresentationStyle 属性的文档。您有一个 rootViewController,它将显示 viewController。所以这是成功的代码:
viewController.view.backgroundColor = [UIColor clearColor];
rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[rootViewController presentModalViewController:viewController animated:YES];
使用此方法,viewController 的背景将是透明的,并且底层的 rootViewController 将是可见的。请注意,这似乎只适用于 iPad,请参阅下面的评论。
您的视图仍然是透明的,但是一旦您的模态控制器位于堆栈的顶部,它后面的视图就会被隐藏(就像任何最顶层的视图控制器一样)。解决方案是自己手动为视图设置动画;那么后面的viewController就不会被隐藏(因为你不会'离开'它)。
我需要让它工作:
self.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
对于那些想要查看一些代码的人,这是我添加到透明视图控制器中的内容:
// Add this view to superview, and slide it in from the bottom
- (void)presentWithSuperview:(UIView *)superview {
// Set initial location at bottom of superview
CGRect frame = self.view.frame;
frame.origin = CGPointMake(0.0, superview.bounds.size.height);
self.view.frame = frame;
[superview addSubview:self.view];
// Animate to new location
[UIView beginAnimations:@"presentWithSuperview" context:nil];
frame.origin = CGPointZero;
self.view.frame = frame;
[UIView commitAnimations];
}
// Method called when removeFromSuperviewWithAnimation's animation completes
- (void)animationDidStop:(NSString *)animationID
finished:(NSNumber *)finished
context:(void *)context {
if ([animationID isEqualToString:@"removeFromSuperviewWithAnimation"]) {
[self.view removeFromSuperview];
}
}
// Slide this view to bottom of superview, then remove from superview
- (void)removeFromSuperviewWithAnimation {
[UIView beginAnimations:@"removeFromSuperviewWithAnimation" context:nil];
// Set delegate and selector to remove from superview when animation completes
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
// Move this view to bottom of superview
CGRect frame = self.view.frame;
frame.origin = CGPointMake(0.0, self.view.superview.bounds.size.height);
self.view.frame = frame;
[UIView commitAnimations];
}
在 iOS 8 中,Apple 批准的方法是将 modalPresentationStyle 设置为 'UIModalPresentationOverCurrentContext'。
从 UIViewController 文档:
UIModalPresentationOverCurrentContext
仅在父视图控制器的内容上显示内容的演示样式。演示结束时,所呈现内容下方的视图不会从视图层次结构中删除。因此,如果呈现的视图控制器没有用不透明的内容填充屏幕,则底层内容会显示出来。
在弹出窗口中呈现视图控制器时,仅当过渡样式为 UIModalTransitionStyleCoverVertical 时才支持此呈现样式。尝试使用不同的转换样式会触发异常。但是,如果父视图控制器不在弹出窗口中,您可以使用其他转换样式(部分卷曲转换除外)。
在 iOS 8.0 及更高版本中可用。
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/
WWDC 2014 中的“iOS 8 中的视图控制器改进”视频对此进行了详细介绍。
确保为您呈现的视图控制器提供清晰的背景颜色(否则,它仍然会显得不透明)。
还有另一种选择:在显示模态控制器之前,捕获整个窗口的屏幕截图。将捕获的图像插入 UIImageView 并将图像视图添加到您将要显示的控制器视图中。然后送回去。在图像视图上方插入另一个视图(背景黑色,alpha 0.7)。显示您的模态控制器,它看起来像是透明的。刚刚在运行 iOS 4.3.1 的 iPhone 4 上尝试过。喜欢魅力。
这已经很老了,但我解决了以下相同的问题:由于我需要在 iPhone 中显示导航控制器,因此添加子视图不是一个可行的解决方案。
所以我做了什么:
1) 在展示视图控制器之前,对当前屏幕进行截图:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
2)创建您要呈现的视图控制器,并将背景添加为子视图,将其发送到后面。
UIViewController * presentingVC = [UIViewController new];
UIImageView * backgroundImageOfPreviousScreen = [[UIImageView alloc] initWithImage:backgroundImage];
[presentingVC.view addSubview:backgroundImageOfPreviousScreen];
[presentingVC.view sendSubviewToBack:backgroundImageOfPreviousScreen];
3) 展示您的视图控制器,但在此之前在新视图控制器中,在 viewDidLoad 中添加一个透明视图(我使用了 ILTranslucentView)
-(void)viewDidLoad
{
[super viewDidLoad];
ILTranslucentView * translucentView = [[ILTranslucentView alloc] initWithFrame:self.view.frame];
[self.view addSubview:translucentView];
[self.view sendSubviewToBack:translucentView];
}
就这样!
我在另一个问题中写下了我的发现,但要点是你必须调用modalPresentationStyle = UIModalPresentationCurrentContext
目前拥有全屏的任何东西。大多数时候,它是 [UIApplication sharedApplication].delegate.window 的 rootViewController。它也可能是一个新的 UIViewController,它带有modalPresentationStyle = UIModalPresentationFullScreen
.
如果您想知道我是如何专门解决这个问题的,请阅读我的其他更详细的帖子。祝你好运!
这似乎在 IOS 8 中被破坏了,我正在使用导航控制器,并且正在显示的上下文是导航菜单上下文,在我们的例子中是滑动菜单控制器。
我们正在使用 pod 'TWTsideMenuViewController', '0.3' 尚未检查这是否是库或上述方法的问题。
这在 iOS 8-9 中对我有用:
1- 使用 alpha 设置视图控制器的背景
2-添加此代码:
TranslucentViewController *tvc = [[TranslucentViewController alloc] init];
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[tvc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self.navigationController presentViewController:tvc animated:YES completion:nil];
在我的情况下,我在同一个 viewController 上有视图。所以制作一个新的视图控制器来保存 UIView。通过设置它的 alpha 属性使该视图透明。然后在一个按钮上单击我写了这段代码。这看起来不错的样子。
UIGraphicsBeginImageContext(objAppDelegate.window.frame.size);
[objAppDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIViewController *controllerForBlackTransparentView=[[[UIViewController alloc] init] autorelease];
[controllerForBlackTransparentView setView:viewForProfanity];
UIImageView *imageForBackgroundView=[[UIImageView alloc] initWithFrame:CGRectMake(0, -20, 320, 480)];
[imageForBackgroundView setImage:viewImage];
[viewForProfanity insertSubview:imageForBackgroundView atIndex:0];
[self.navigationController presentModalViewController:controllerForBlackTransparentView animated:YES];
它显示了我想要的。希望对某人有所帮助。
我创建了开放源库MZFormSheetController以在其他 UIWindow 上呈现模态表单。您可以使用它来呈现透明度模态视图控制器,甚至可以调整呈现的视图控制器的大小。
这是我创建的一个可以解决问题的类别。
//
// UIViewController+Alerts.h
//
#import <UIKit/UIKit.h>
@interface UIViewController (Alerts)
- (void)presentAlertViewController:(UIViewController *)alertViewController animated:(BOOL)animated;
- (void)dismissAlertViewControllerAnimated:(BOOL)animated;
@end
//
// UIViewController+Alerts.m
//
#import "UIViewController+Alerts.h"
@implementation UIViewController (Alerts)
- (void)presentAlertViewController:(UIViewController *)alertViewController animated:(BOOL)animated
{
// Setup frame of alert view we're about to display to just off the bottom of the view
[alertViewController.view setFrame:CGRectMake(0, self.view.frame.size.height, alertViewController.view.frame.size.width, alertViewController.view.frame.size.height)];
// Tag this view so we can find it again later to dismiss
alertViewController.view.tag = 253;
// Add new view to our view stack
[self.view addSubview:alertViewController.view];
// animate into position
[UIView animateWithDuration:(animated ? 0.5 : 0.0) animations:^{
[alertViewController.view setFrame:CGRectMake(0, (self.view.frame.size.height - alertViewController.view.frame.size.height) / 2, alertViewController.view.frame.size.width, alertViewController.view.frame.size.height)];
}];
}
- (void)dismissAlertViewControllerAnimated:(BOOL)animated
{
UIView *alertView = nil;
// find our tagged view
for (UIView *tempView in self.view.subviews)
{
if (tempView.tag == 253)
{
alertView = tempView;
break;
}
}
if (alertView)
{
// clear tag
alertView.tag = 0;
// animate out of position
[UIView animateWithDuration:(animated ? 0.5 : 0.0) animations:^{
[alertView setFrame:CGRectMake(0, self.view.frame.size.height, alertView.frame.size.width, alertView.frame.size.height)];
}];
}
}
@end
经过大量研究后,看起来这将解决我们的问题并达到我们的目的。
使用标识符创建从源 VC 到目标 VC 的 segue。
例如“goToDestinationViewController”可以让生活变得轻松让我们考虑当前的视图控制器,即你想要在透明视图后面的那个作为源,目的地作为目的地
现在在 viewDidLoad: 或视图中的源 VC
performSegueWithIdentifier("goToDestinationViewController", sender: nil)
很好,我们已经完成了一半。现在去你的故事板。点击转场。应该是这样的: segue
将选项更改为显示的内容。
现在是真正的解决方案。
在您的目标视图控制器的 viewDidLoad 中添加此代码。
self.modalPresentationStyle = .Custom
..................................................... ........................这很容易............ .........................................................
另一种方法是使用“容器视图”。只需将 alpha 设为 1 以下并嵌入 sequ。XCode 5,针对 iOS7。
无法显示图像,没有足够的声誉)))
iOS6 提供的容器视图。
此代码在 iOS6 和 iOS7 下的 iPhone 上运行良好:
presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];
但是沿着这种方式,您会失去“从底部滑动”的动画。
我为 iOS 7 及更高版本找到了这个优雅而简单的解决方案!
对于 iOS 8,Apple 添加了 UIModalPresentationOverCurrentContext,但它不适用于 iOS 7 及之前的版本,因此我无法将其用于我的案例。
请创建类别并输入以下代码。
.h 文件
typedef void(^DismissBlock)(void);
@interface UIViewController (Ext)
- (DismissBlock)presentController:(UIViewController *)controller
withBackgroundColor:(UIColor *)color
andAlpha:(CGFloat)alpha
presentCompletion:(void(^)(void))presentCompletion;
@end
.m 文件
#import "UIViewController+Ext.h"
@implementation UIViewController (Ext)
- (DismissBlock)presentController:(UIViewController *)controller
withBackgroundColor:(UIColor *)color
andAlpha:(CGFloat)alpha
presentCompletion:(void(^)(void))presentCompletion
{
controller.modalPresentationStyle = UIModalPresentationCustom;
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
__block UIView *overlay = [[UIView alloc] initWithFrame:keyWindow.bounds];
if (color == nil) {
color = [UIColor blackColor];
}
overlay.backgroundColor = color;
overlay.alpha = alpha;
if (self.navigationController != nil) {
[self.navigationController.view addSubview:overlay];
}
else if (self.tabBarController != nil) {
[self.tabBarController.view addSubview:overlay];
}
else {
[self.view addSubview:overlay];
}
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:controller
animated:true
completion:presentCompletion];
DismissBlock dismissBlock = ^(void) {
[self dismissViewControllerAnimated:YES completion:nil];
[UIView animateWithDuration:0.25
animations:^{
overlay.alpha = 0;
} completion:^(BOOL finished) {
[overlay removeFromSuperview];
}];
};
return dismissBlock;
}
@end
注意:它也适用于 navigationContoller、tabBarController。
使用示例:
// Please, insure that your controller has clear background
ViewController *controller = [ViewController instance];
__block DismissBlock dismissBlock = [self presentController:controller
withBackgroundColor:[UIColor blackColor]
andAlpha:0.5
presentCompletion:nil];
// Supposed to be your controller's closing callback
controller.dismissed = ^(void) {
dismissBlock();
};
好好享受!请留下一些反馈。
这是迄今为止我发现的最好和最干净的方法:
@protocol EditLoginDelegate <NSObject>
- (void)dissmissEditLogin;
@end
- (IBAction)showtTransparentView:(id)sender {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"foo bar"
delegate:self
cancelButtonTitle:@"cancel"
destructiveButtonTitle:@"destructive"
otherButtonTitles:@"ok", nil];
[actionSheet showInView:self.view];
}
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet{
UIStoryboard *loginStoryboard = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
self.editLoginViewController = [loginStoryboard instantiateViewControllerWithIdentifier:@"EditLoginViewController"];
self.editLoginViewController.delegate = self;
[self.editLoginViewController viewWillAppear:NO];
[actionSheet addSubview:self.editLoginViewController.view];
[self.editLoginViewController viewDidAppear:NO];
}
我遇到的最佳解决方案是使用 addChildViewController 方法。这是一个很好的例子:将子视图控制器的视图添加到父视图控制器的子视图中
我尝试使用多种方法解决但仍然失败,最终实现以下代码。
斯威夫特的决议:
// A.swift init method
modalPresentationStyle = .currentContext // or overCurrentContent
modalTransitionStyle = .crossDissolve // dissolve means overlay
然后在 B 视图控制器中:</p>
// B.swift
let a = A()
self.present(a, animated: true, completion: nil)