I have main dashboard (UITableViewController) and once i sign in i need to show this page with a welcome message which am showing using a UIViewController.
How can i show this popup from my ViewDidAppear() method ?
Am using following code and its not working
-(void)viewDidAppear:(BOOL)animated{
popupObj= [self.storyboard instantiateViewControllerWithIdentifier:#"popup"];
[popupObj setModalPresentationStyle:UIModalPresentationCurrentContext];
}
please help me..
i saw couple of stackoverflow links
Update
When i change my code to this one
-(void)viewDidAppear:(BOOL)animated{
popupObj= [self.storyboard instantiateViewControllerWithIdentifier:#"popup"];
// [popupObj setModalPresentationStyle:UIModalPresentationCurrentContext];
popupObj.modalPresentationStyle = UIModalPresentationOverCurrentContext;
popupObj.modalTransitionStyle = UIModalPresentationPopover;
[self presentViewController:popupObj animated:YES completion:nil];
}
Now i can see my UIViewController coming as popup but now UIViewController
coming as full screen view.
But i need only this frame (320 , 320)
popupObj= [self.storyboard instantiateViewControllerWithIdentifier:#"popup"];
popupObj.view.frame = CGRectMake(20, 200, 280, 168);
[self.view addSubview:popupObj.view];
[self addChildViewController:popupObj];
You can add UIViewController as subview and set it's frame so it will look like popup.
Hope this will help you.
I have two way,maybe not good, but work at most of time.
First,when the second view controller appear, show a screen shot of the first view controller. like this:
- (void)setBackGround {
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, [UIScreen mainScreen].scale);
[self.presentingViewController.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.layer.contents = (__bridge id)(image.CGImage);
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (!_isShown) {
_isShown = YES;
[self setBackGround];
}
}
Do't forget set "_isShown = NO" when init.
Second: you can only init a view, and show it on a view controller with animation. code at :http://blog.moemiku.com/?p=101
I have update a example on the blog. Direct download url
Your code creates the view controller and sets its presentation style, but doesn't actually present it. For that to happen you need this line after the two you have right now:
[self presentViewController:popupObj animated:true completion:nil];
Please set navigation controller on your rootviewcontroller :
-(void)viewDidAppear:(BOOL)animated
{
popupObj= [self.storyboard instantiateViewControllerWithIdentifier:#"popup"];
[self.navigationController presentViewController:popupObj animated:YES completion:nil];
}
Or
-(void)viewDidAppear:(BOOL)animated
{
popupObj= [self.storyboard instantiateViewControllerWithIdentifier:#"popup"];
[self.view addSubview:popupObj.view];
}
I'm trying to make a custom alertView (for iOS7+) on my own but I struggle with the alertView presentation.
I have a UIViewController with a black background (alpha set to 0.25f), and a alertView as subview.
When I want to show the alertView, I present modally the viewController:
-(void) show
{
UIWindow* window = [[UIApplication sharedApplication] keyWindow];
self.modalTransitionStyle = UIModalPresentationCustom;
self.transitioningDelegate = self;
[window.rootViewController presentViewController:self animated:YES completion:nil];
}
And here is my animator object:
-(NSTimeInterval) transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
NSLog(#"%s",__PRETTY_FUNCTION__);
return 2;
}
-(void) animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
NSLog(#"%s",__PRETTY_FUNCTION__);
UIView* toView = [transitionContext viewForKey:UITransitionContextToViewKey];
toView.alpha = 0;
UIView* container = [transitionContext containerView];
[container addSubview:toView];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toView.alpha = 0.5;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
The thing is: the modal VC is fading with the presenting VC in background as its supposed to do, but when the animation ends the presenting VC is removed from the background.
If I call [transitionContext completeTransition:YES]; instead, the presenting VC is in background but the modal VC is removed at animation end, so I guess the context cancels the presentation if we send 'NO'.
Is there a way to keep the presenting VC in background without having to make a snapshot of it and set it as background of the modal VC's view?
I've tried this solution and it works on both iOS 7 and 8:
if ([[UIDevice currentDevice].systemVersion integerValue] >= 8)
{
//For iOS 8
presentingViewController.providesPresentationContextTransitionStyle = YES;
presentingViewController.definesPresentationContext = YES;
presentedViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
}
else
{
//For iOS 7
presentingViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
}
Note: Be aware of the difference between 'presentingViewController' and 'presentedViewController'.
iOS8+
For iOS8+ you can use below code snippet
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:secondViewController animated:YES completion:nil];
My case might differ from yours, but the information might be useful for the conversation.
In Storyboard, I changed my segue's Presentation to state "Over Full Screen" and it did the trick.
I think what you are seeing is the default behavior of iOS.
View controllers are not supposed to be non-opaque when presented as modal view controllers. iOS removes the underlaying view controller when the animation is complete, in order to speed up composition when the presented view controller is supposed to take up the entire screen. There is no reason to draw a view controller - which might be complex in it's view hierarchy - when it is not even visible on screen.
I think your only solution is to do a custom presentation.
Remark: I did not test this. But it goes something like this.
/* Create a window to hold the view controller. */
UIWindow *presenterWindow = [[UIWindow alloc] init];
/* Make the window transparent. */
presenterWindow.backgroundColor = [UIColor clearColor];
presenterWindow.opaque = NO;
/* Set the window rootViewController to the view controller you
want to display as a modal. */
presenterWindow.rootViewController = myModalViewController;
/* Setup animation */
CGRect windowEndFrame = [UIScreen mainScreen].bounds;
CGRect windowStartFrame = windowEndFrame;
/* Adjust the start frame to appear from the bottom of the screen. */
windowStartFrame.origin.y = windowEndFrame.size.height;
/* Set the window start frame. */
presenterWindow.frame = windowStartFrame;
/* Put the window on screen. */
[presenterWindow makeKeyAndVisible];
/* Perform the animation. */
[UIView animateWithDuration:0.5
delay:.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
presenterWindow.frame = windowEndFrame;
}
completion:^(BOOL finished){
/* Your transition end code */
}];
This does however leave you with no option to use any of the presenting view controller logic build into UIViewController. You'll need to figure yourself, when the presented view controller is done, and then reverse the animation and remove the UIWindow from screen.
The ViewController is not supposed to be transparent when you present it or push it. You can try adding it as subview. And for transition effect change its frame immediately after adding as subview. Make its frame somewhere outside the visible view and then animate it to change frame to visible view.
Hope this helps.
For your information,
I finally made my custom alertView a subclass of UIView for the "popUp part".
To show it, I just add the alertView as subview of the keyWindow with the constraints to center it, and put a transparent black background view behind it.
As it's not a controller, I have to manage UI rotation by myself (only for iOS 7, it rotates well with the UI in iOS 8).
I have vc1.view covering the whole screen, and I want to be able to dim vc1.view, and have vc2.view zoom into the whole screen.
I don't have any navigation controller in the app, so what's the best practice to achieve my goal? The solution I'm thinking of is:
Add both vc1.view and vc2.view into a common container view
Use [UIView transitionFromView:vc1.view toView:vc2.view ......]
I dislike the idea of having to add views of different vc into a common container view. Any suggestions? Thanks in advance.
You can use transitionFromView:toView:... without adding the new view to a common container, because that transition method takes care of adding the view. The following worked for me. The code is in the view controller whose view is the "from view". I'm using a cross fade here, but you could change that to any of the other available methods:
-(void)switchViews:(id)sender {
UIWindow *win = self.view.window;
YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:#"Yellow"];
yellow.view.frame = self.view.frame;
[UIView transitionFromView:self.view toView:yellow.view duration:2 options:UIViewAnimationOptionTransitionCrossDissolve completion:^(BOOL finished) {
win.rootViewController = yellow;
}];
}
However, to do a custom transition, you do have to add the new view as a subview of whatever view the "from view" is in (I think). In this example, that is the window's view. This code grows the new view from the center of the old one, while that one fades out. At the end of the transition, the view controller is switched to the one that owns the new view (yellow in this case)
After Edit: I changed this method to use a CGAffineTransform (thanks to jrturton for that suggestion made in an answer to my question):
-(void)switchViews3:(id)sender {
UIWindow *win = self.view.window;
YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:#"Yellow"];
yellow.view.frame = self.view.frame;
yellow.view.transform = CGAffineTransformMakeScale(.1, .1);
[win addSubview:yellow.view];
[UIView animateWithDuration:.6 animations:^{
yellow.view.transform = CGAffineTransformIdentity;
self.view.alpha = 0;
}
completion:^(BOOL finished) {
[self.view removeFromSuperview];
win.rootViewController = yellow;
}];
}
To present from vc1 to vc2 without a navigation controller, use
[vc1 presentViewController:vc2 animated:YES completion:nil];
To change the presenting style, Apple provides a few. You just need to set it before calling the above code:
vc2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
Here is the list:
typedef enum {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl,
} UIModalTransitionStyle;
I have a view controller which is not fullscreen (has a status bar) and want to present a modal view controller which is fullscreen.
If I hide the status bar at the beginning of the animation (parent's viewWillDisappear or modal's viewWillAppear) then for a moment the parent will be visible without a status bar, looking like a bug.
If I do it at the end of the animation (parent's viewDidDisappear or modal's viewDidAppear) then the status bar will be visible for a moment over the modal view, i.e. it won't appear as the modal view "covered it".
Is there a way to do this nicely?
edit:
One possibility would be to create a UIWindow with windowLevel=alert for at least the duration of the animation. The sample iAd ad seems to cover the status bar nicely without another window, so it must be possible somehow.
Another fun little project. This was the best I could come up with. It's not too bad if you don't mind using your own container controller to manage presenting/dismissing view controllers. I try to do things in a general way but this could be rolled into an app w/ the ContainerViewController if desired.
Note that I only implemented the equivalent of UIModalTransitionStyleCoverVertical. You can customize the animation however you like as well.
Relevant animation code:
- (void)presentViewController:(UIViewController *)viewControllerToPresent
{
// do nothing if no controller
if (!viewControllerToPresent) return;
[__viewControllers addObject:viewControllerToPresent];
CGRect toFrame = viewControllerToPresent.view.frame;
toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds));
viewControllerToPresent.view.frame = toFrame;
[UIView transitionWithView:self.view
duration:0.2
options:UIViewAnimationOptionTransitionNone
animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:viewControllerToPresent.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide];
[self.view addSubview:viewControllerToPresent.view];
viewControllerToPresent.view.frame = [UIScreen mainScreen].applicationFrame;
}
completion:nil];
}
- (void)dismissViewController
{
// nothing to dismiss if showing first controller
if (__viewControllers.count <= 1) return;
UIViewController *currentViewController = [__viewControllers lastObject];
UIViewController *previousViewController = [__viewControllers objectAtIndex:__viewControllers.count - 2];
[UIView transitionWithView:self.view
duration:0.2
options:UIViewAnimationOptionTransitionNone
animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:previousViewController.wantsFullScreenLayout withAnimation:UIStatusBarAnimationSlide];
CGRect toFrame = currentViewController.view.frame;
toFrame.origin = CGPointMake(0, CGRectGetMaxY(self.view.bounds));
currentViewController.view.frame = toFrame;
}
completion:^(BOOL finished) {
[currentViewController.view removeFromSuperview];
[__viewControllers removeLastObject];
}];
}
I do that in my app with this code:
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation: UIStatusBarAnimationSlide ];
DocumentListViewController * dl = [[DocumentListViewController alloc] initWithNibName:#"DocumentListView" bundle:nil] ;
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:dl];
[dl release];
// Go to the list of documents...
[[self.view superview] addSubview:nav.view];
nav.view.alpha = 0.0 ;
[self hideActivityAlert];
[UIView animateWithDuration:1.0 animations:^{
nav.view.alpha = 1.0; } completion:^(BOOL A){
[self.view removeFromSuperview];
[self release];} ];
The status bar is presented shoftly while the animation occurs.
You have to be sure that the first view, when status bar is going hidden will fill the space. Use the property autoresizingMask with proper value.
Here's a solution that seems to work. You can derive the viewcontroller you want to present modally from my TSFullScreenModalViewController, or you can just implement the code right in the view controller itself.
#interface TSFullScreenModalViewController : UIViewController
{
UIWindow* _window;
}
- (void) presentFullScreenModal;
#end
#implementation TSFullScreenModalViewController
- (void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear: YES];
[_window resignKeyWindow];
[_window release];
_window = nil;
}
- (void) presentFullScreenModal
{
UIViewController* rvc = [[UIViewController new] autorelease];
rvc.view.backgroundColor = [UIColor clearColor];
_window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds] ;
_window.windowLevel = UIWindowLevelStatusBar+1;
_window.backgroundColor = [UIColor clearColor];
_window.rootViewController = rvc;
[_window makeKeyAndVisible];
[UIApplication sharedApplication].statusBarHidden = YES;
[rvc presentModalViewController: self animated: YES];
[UIApplication sharedApplication].statusBarHidden = NO;
}
#end
Derive your modal view controller, like this:
#interface MyModalViewController : TSFullScreenModalViewController
{
}
- (IBAction) onDismiss:(id)sender;
#end
Use it from another view controller, like this:
- (IBAction) onShowModal:(id)sender
{
MyModalViewController* mmvc = [[MyModalViewController new] autorelease];
[mmvc presentFullScreenModal];
}
Finally, dismiss your view controller as you normally would:
- (IBAction) onDismiss:(id)sender
{
[self dismissModalViewControllerAnimated: YES];
}
Might be a bit of a hack but have you considered:
Take a screenshot programatically of the first view with the status bar (see this SO question)
Create a new view which displays the image you just took in fullscreen (using UIImage's initWithFrame)
Hide the status bar
Present the modal view controller
Then to dismiss the modal view, just reverse the steps.
EDIT:
Won't work for this because you can't take screenshots of the status bar.
It could be as simple as delaying the presentation of your modalViewController using performSelector:withDelay:
Tell the status bar to animate out and then launch the modal controller with the right delay so it coincides with the status bar animation.
I am displaying a modal view with
[self presentModalViewController:controller animated:YES];
When the view moves up the screen it is transparent as per the setting in the xib file it is created from, but once it fills the screen it goes opaque.
Is there anyway of keeping the view transparent?
I suspect that the view it is being placed over is not being rendered rather then that the modal view is becoming opaque.
After iOS 3.2 there is a method to do this without any “tricks” – see the documentation for the modalPresentationStyle property. You have a rootViewController which will present the viewController.
So here's the code to success:
viewController.view.backgroundColor = [UIColor clearColor];
rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[rootViewController presentModalViewController:viewController animated:YES];
With this method the viewController's background will be transparent and the underlying rootViewController will be visible. Please note that this only seems to work on the iPad, see comments below.
Your view is still transparent, but once your modal controller is at the top of the stack, the view behind it is hidden (as is the case with any top-most view controller). The solution is to manually animate a view yourself; then the behind-viewController won't be hidden (since you won't have 'left' it).
What I needed to get this to work:
self.window.rootViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
For those who want to see some code, here's what I added to my transparent view's controller:
// 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];
}
The Apple-approved way to do this in iOS 8 is to set the modalPresentationStyle to 'UIModalPresentationOverCurrentContext'.
From the UIViewController documentation:
UIModalPresentationOverCurrentContext
A presentation style where the content is displayed over only the
parent view controller’s content. The views beneath the presented
content are not removed from the view hierarchy when the presentation
finishes. So if the presented view controller does not fill the screen
with opaque content, the underlying content shows through.
When presenting a view controller in a popover, this presentation
style is supported only if the transition style is
UIModalTransitionStyleCoverVertical. Attempting to use a different
transition style triggers an exception. However, you may use other
transition styles (except the partial curl transition) if the parent
view controller is not in a popover.
Available in iOS 8.0 and later.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/
The 'View Controller Advancements in iOS 8' video from WWDC 2014 goes into this in some detail.
Be sure to give your presented view controller a clear background color (otherwise, it will still appear opaque).
There is another option: before showing the modal controller, capture a screenshot of the whole window. Insert the captured image into an UIImageView and add the image view to the controller's view you're about to show.
Then send to back.
Insert another view above the image view (background black, alpha 0.7).
Show your modal controller and it looks like it was transparent.
Just tried it on iPhone 4 running iOS 4.3.1. Like charm.
this is quite old, but i solved the same problem as follows:
Since i need to present a navigation controller in iPhone, adding a subview wasn't a viable solution.
So what i did:
1) Before presenting the view controller, take a screenshot of your current screen:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
2) Create the view controller you want to present, and add the background as a subview, sending it to back.
UIViewController * presentingVC = [UIViewController new];
UIImageView * backgroundImageOfPreviousScreen = [[UIImageView alloc] initWithImage:backgroundImage];
[presentingVC.view addSubview:backgroundImageOfPreviousScreen];
[presentingVC.view sendSubviewToBack:backgroundImageOfPreviousScreen];
3) Present your view controller, but before that in the new view controller, add a transparent view in the viewDidLoad (i used ILTranslucentView)
-(void)viewDidLoad
{
[super viewDidLoad];
ILTranslucentView * translucentView = [[ILTranslucentView alloc] initWithFrame:self.view.frame];
[self.view addSubview:translucentView];
[self.view sendSubviewToBack:translucentView];
}
And that's all!
I wrote down my findings about this in a different question, but the gist of it is that you have to call modalPresentationStyle = UIModalPresentationCurrentContext on whatever owns the full screen at the moment. Most of the time, it's whatever is the [UIApplication sharedApplication].delegate.window's rootViewController. It could also be a new UIViewController that was presented with modalPresentationStyle = UIModalPresentationFullScreen.
Please read my other much more detailed post if you're wondering how I specifically solved this problem. Good luck!
This appears to be broken in IOS 8, I am using a navigation controller and the context that is being displayed is the Navigation menus context which in our case is a sliding Menu controller.
We are using pod 'TWTSideMenuViewController', '0.3' have not checked to see if this is an issue with the library yet or the method described above.
This worked to me in iOS 8-9:
1- Set your view controller's background with an alpha
2- add this code:
TranslucentViewController *tvc = [[TranslucentViewController alloc] init];
self.providesPresentationContextTransitionStyle = YES;
self.definesPresentationContext = YES;
[tvc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
[self.navigationController presentViewController:tvc animated:YES completion:nil];
I know this is pretty old question. I was stuck on this issue and I was able to get a lead from this thread. So putting here how I got it worked :) .
I am using storyboard and I have segue to the ViewController which is to be presented. The view controller have a transparent background colour. Now in the Attributes inspector of the segue I set the presentation to "Over current context".And it worked for me. I am developing for iPhone.
I've created open soruce library MZFormSheetController to present modal form sheet on additional UIWindow. You can use it to present transparency modal view controller, even adjust the size of the presented view controller.
In my condition i am having view on same viewController. So make a new view controller for holding UIView. Make that view transparent by setting it's alpha property.
Then on a button click i wrote this code. It looks good.
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];
And it shows what i want. hope it help some one.
Here's a category I've created that will solve the problem.
//
// 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
After a lot of research looks like this will solve our issue and serve our purpose.
create a segue from source VC to destination VC with an identifier.
for example "goToDestinationViewController"
okay to makes lives easy let's consider the current view controller i.e, the one you want behind your transparent view as source and the destination as destination
Now in source VC in viewDidLoad: or view
performSegueWithIdentifier("goToDestinationViewController", sender: nil)
good we are half way through.
Now go to your storyboard. Click on the segue. which should look like this:
segue
change the options to what are shown.
Now comes the real solution.
in your destination view controller's viewDidLoad add this code.
self.modalPresentationStyle = .Custom
.........................................................................THAT EASY..................................................................
Alternate way is to use a "container view". Just make alpha below 1 and embed with seque.
XCode 5, target iOS7.
can't show image, not enough reputation)))
Container view available from iOS6.
This code works fine on iPhone under iOS6 and iOS7:
presentedVC.view.backgroundColor = YOUR_COLOR; // can be with 'alpha'
presentingVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentingVC presentViewController:presentedVC animated:YES completion:NULL];
But along this way you loose 'slide-from-the-bottom' animation.
I found this elegant and simple solution for iOS 7 and above!
For iOS 8 Apple added UIModalPresentationOverCurrentContext, but it does not work for iOS 7 and prior, so I could not use it for my case.
Please, create the category and put the following code.
.h file
typedef void(^DismissBlock)(void);
#interface UIViewController (Ext)
- (DismissBlock)presentController:(UIViewController *)controller
withBackgroundColor:(UIColor *)color
andAlpha:(CGFloat)alpha
presentCompletion:(void(^)(void))presentCompletion;
#end
.m file
#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
Note: it works also for navigationContoller, tabBarController.
Example of usage:
// 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();
};
Enjoy it! and please, leave some feedbacks.
This is the best and cleanest way I found so far:
#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];
}
The best solution I have come across is to use the addChildViewController method.
Here is an excellent example : Add a child view controller's view to a subview of the parent view controller
I try to use multiple methods to solve but still failed, the follow code implemented finally.
The resolution by Swift:
// A.swift init method
modalPresentationStyle = .currentContext // or overCurrentContent
modalTransitionStyle = .crossDissolve // dissolve means overlay
then in B view controller:
// B.swift
let a = A()
self.present(a, animated: true, completion: nil)