I use the following code to present a viewcontroller. My problem is: After the animation completes, the transparent main background becomes opaque black.
How can I fix this and make it stay as clearColor?
UIViewController *menuViewController=[[UIViewController alloc]init];
menuViewController.view.backgroundColor=[UIColor clearColor];
menuViewController.view.tintColor=[UIColor clearColor];
menuViewController.view.opaque=NO;
UIView *menuView=[[UIView alloc]initWithFrame:CGRectMake(0,[UIScreen mainScreen].bounds.size.height-200,320,200)];
menuView.backgroundColor=[UIColor redColor];
[menuViewController.view addSubview:menuView];
[self presentViewController:menuViewController animated:YES completion:nil];
update: I am trying to see the contents of "self" (the presenter viewcontroller's view).
Apple has introduced a new API, UISheetPresentationController, which makes it rather trivial to achieve a half-sized (.medium()
) sheet presentation. If you are after something more custom, then the original answer is what you need.
let vc = UIViewController()
if let sheet = vc.presentationController as? UISheetPresentationController {
sheet.detents = [.medium()]
}
self.present(vc, animated: true, completion: nil)
You can present a view controller, and still have the original view controller visible underneath, like a form, in iOS 7. To do so, you will need to do two things:
Set the modal presentation style to custom:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationCustom;
Set the transitioning delegate:
viewControllerToPresent.transitioningDelegate = self;
In this case, we have set the delegate to self, but it can be another object. The delegate needs to implement the two required methods of the protocol, possible like so:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
SemiModalAnimatedTransition *semiModalAnimatedTransition = [[SemiModalAnimatedTransition alloc] init];
semiModalAnimatedTransition.presenting = YES;
return semiModalAnimatedTransition;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
SemiModalAnimatedTransition *semiModalAnimatedTransition = [[SemiModalAnimatedTransition alloc] init];
return semiModalAnimatedTransition;
}
At this point you may be thinking, where did that SemiModalAnimatedTransition
class come from. Well, it is a custom implementation adopted from teehan+lax's blog.
Here is the class's header:
@interface SemiModalAnimatedTransition : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) BOOL presenting;
@end
And the implementation:
#import "SemiModalAnimatedTransition.h"
@implementation SemiModalAnimatedTransition
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return self.presenting ? 0.6 : 0.3;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect endFrame = fromViewController.view.bounds;
if (self.presenting) {
fromViewController.view.userInteractionEnabled = NO;
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:toViewController.view];
CGRect startFrame = endFrame;
startFrame.origin.y = endFrame.size.height;
toViewController.view.frame = startFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
toViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
toViewController.view.userInteractionEnabled = YES;
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
endFrame.origin.y = endFrame.size.height;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
fromViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
@end
Not the most straightforward solution, but avoids hacks and works well. The custom transition is required because by default iOS will remove the first view controller at the end of the transition.
For iOS 8, once again the landscape has changed. All you need to do is use the new presentation style .OverCurrentContext
, ie:
viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext;
Update
In most cases, you're going to want to follow the guidelines from Ric's answer, below. As he mentions, menuViewController.modalPresentationStyle = .overCurrentContext
is the simplest modern way to keep the presenting view controller visible.
I'm preserving this answer because it provided the most direct solution to the OPs problem, where they already had a view managed by the current view controller and were just looking for a way to present it, and because it explains the actual cause problem.
As mentioned in the comments, this isn't a transparency problem (otherwise you would expect the background to become white). When the presentViewController:animated:completion:
animation completes, the presenting view controller is actually removed from the visual stack. The black you're seeing is the window's background color.
Since you appear to just be using menuViewController
as a host for menuView
to simplify the animation, you could consider skipping menuViewController
, adding menuView
to your existing view controllers view hierarchy, and animate it yourself.
This is a fairly simple problem to solve. Rather than creating a custom view transition, you just need to set the modalPresentationStyle for the view controller being presented. Also, you should set the background color (and alpha value) for the view controller being presented, in the storyboard / via code.
CustomViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.6)
}
}
In the IBAction component of presenting view controller -
let vc = storyboard?.instantiateViewControllerWithIdentifier("customViewController") as! CustomViewController
vc.modalPresentationStyle = UIModalPresentationStyle.Custom
presentViewController(vc, animated: true, completion: nil)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With