I am making custom popover by subclassing UIPopoverBackgroundView (using this tutorial) and presenting it by using UIPopoverController. Unfortunately as soon as I specify custom popoverBackgroundViewClass the native dimmed background disappears. Is there any way to leave the dimmed background when using custom UIPopoverBackgroundView? Any other solution that I can use to simulate native behaviour?
Not sure why this got down voted, it's a good question because when you implement a custom UIPopoverBackgroundView, the dimmed background doesn't get set. In researching this problem, I determined the best approach is to set it myself!
Just before creating the popover view, I create a "mask view" that will be added to the view before the popover. This code includes a nice fade in effect as well:
self.customPopoverMaskView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
self.customPopoverMaskView.backgroundColor = [UIColor blackColor];
self.customPopoverMaskView.alpha = 0.3f;
[UIView transitionWithView:self.view
duration:0.3
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.view addSubview:self.customPopoverMaskView];
}
completion:nil];
And to remove the view, plug this into the method(s) that handle the popover view disappearing:
[UIView transitionWithView:self.view
duration:0.3
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
[self.customPopoverMaskView removeFromSuperview];
}
completion:nil];
Works well for me. Happy coding!
Aaron
All you need is add next code into initWithFrame: method of your implementation of UIPopoverBackgroundView.
UIView *dimView = [[UIView alloc] initWithFrame:CGRectMake(0 - self.frame.origin.x,
0 - self.frame.origin.y,
[UIScreen mainScreen].bounds.size.width,
[UIScreen mainScreen].bounds.size.height)];
dimView.backgroundColor = [UIColor blackColor];
dimView.alpha = 0.15;
dimView.userInteractionEnabled = NO;
[self addSubview:dimView];
It works as same as default Apple implementation.
Related
trying to dim background view when I work with custom modal view controller I set background color to grey color with 0.5 opacity:
- (void)rulesTapped:(id)sender
{
RulesVC *rulesVC = [[RulesVC alloc] init];
self.view.backgroundColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.5];
rulesVC.modalPresentationStyle = UIModalPresentationCustom;
rulesVC.transitioningDelegate = self;
[self presentViewController:rulesVC animated:YES completion:nil];
}
but when I then try to set it back to whiteColor (or yellow) while dismissing the modal VC, this dimming keeps in place:
- (void) gotItTapped:(id)sender
{
[self.presentingViewController.view setBackgroundColor:[UIColor yellowColor]];
[self dismissViewControllerAnimated:YES completion:nil];
}
Why? And is there way to dim background (and then remove dimming) view without adding another overlaying view but just operating with existing view?
I don't think you can achieve it without adding another element to your UIViewController. I normally insert an UIView which is setHidden:YES and alpha 0.0f and blackColor as backgroundColor. When showing something, I always set it Hidden:NO and animate it to opacity 0.6f.
[UIView animateWithDuration:0.5f animations:^{
[self.view setAlpha:0.6];
}];
This way it appears not immediately and looks much smoother.
I actually needed this to be able to put some other UIView in dim view, and that every click outside this dimview, would dismiss both built-in UIView and dimView. What I've discovered, is that for this the best is to imitate a button which is removed from superview upon click:
self.dimView = [UIButton buttonWithType:UIButtonTypeCustom];
self.dimView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2f];
self.dimView.frame = CGRectMake(0,
0,
self.view.frame.size.width,
self.view.frame.size.height);
[self.dimView addTarget:self
action:#selector(removeDimView)
forControlEvents:UIControlEventTouchUpInside];
I have no idea, why it is not working.
All I want to do is a simple UIView animation in the viewDidLoad.
Here's my code:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setCenter:CGPointMake(0.0, 200.0)];
}];
Nothing happens. When I test the general approach of calling a animation method on that particular object like this:
[UIView animateWithDuration:3.0f animations:^{
[self.headline setAlpha:0.0];
}];
it works!!! Why am I not able to move the view across the screen? I am using latest Xcode 4.5.
Thanks for any advice!
UPDATE:
When I add a view manually in code it works. But for the UIViews I create as Outlets in the Interface Builder it doesn't work.
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 200.0, 100.0)];
testLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:testLabel];
[UIView animateWithDuration:3.0 animations:^{
testLabel.center = CGPointMake(0.0, 200);
}];
So obviously I am doing something wrong in the .xib file
Dont do it in viewDidLoad. The view is not pressent at that time yet.
Try it in viewDidAppear.
Well, I think the reason for the missing animation was the fact that I called a different push navigation animation from the view controller that was pushing the actual view on screen:
- (IBAction)goForSelection:(id)sender
{
SelectionViewController *selectionViewController = [[SelectionViewController alloc] initWithNibName:#"SelectionViewController" bundle:nil];
//[self.navigationController pushViewController:selectionViewController animated:YES];
[UIView transitionWithView:self.navigationController.view duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[self.navigationController pushViewController:selectionViewController animated:NO];
} completion:^(BOOL finished) {
[selectionViewController startIntroAnimation];
}];
}
First I checked what happens when I use the default navigation controller segue. And to my surprise the animation did start. Then I inserted the call to the [selectionViewController startIntroAnimation] to the completion block and this works as well.
I want to create something that is basically a clone of what photosynth does for their tutorial page. A small "?" button pops up what looks like a new view in a frame that is slightly smaller than the first view, so that you can still see the first view around the edges.
It's a little tough to see from the pic above, but the part around the edges is the old view that the tutorial display popped up over.
My first guess is that I need to use a container view somehow, but I can't find anything on the web about exactly how to do this. I can currently create a container view, hook it up to a new view controller via a segue, and do whatever I want in that new view controller, but the container view is always visible on the view it is contained within. Any help?
BTW, I'm using storyboarding with ARC.
You can add a transparent view to the key window, add a tap gesture recognizer that would dismiss it and the subviews to show the content:
#define OVERLAY_TAG 997
-(void)showTutorial
{
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView *overlay = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
overlay.backgroundColor = [UIColor clearColor];
overlay.userInteractionEnabled = YES;
[keyWindow addSubview:overlay];
UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissTutorial)];
CGFloat border = 10;
CGRect frame = overlay.bounds;
// 20 is the status bar height (sorry for using the number)
frame = CGRectMake(border, border + 20, frame.size.width - border * 2, frame.size.height - border * 2 - 20);
// the black view in the example is probably a scroll view
UIView *blackView = [[UIView alloc] initWithFrame:frame];
blackView.backgroundColor = [UIColor blackColor];
blackView.alpha = 0.0;
[overlay addSubview:dimView];
// add all the subviews for your tutorial
// make it appear with an animation
[UIView animateWithDuration:0.3
animations:^{dimView.alpha = 1;}
completion:^(BOOL finished){[overlay addGestureRecognizer:tapRecognizer];}];
}
-(void)dismissTutorial
{
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
UIView *overlay = [keyWindow viewWithTag:OVERLAY_TAG];
[UIView animateWithDuration:0.3
animations:^{
overlay.alpha = 0.0;
}
completion:^(BOOL finished){
[overlay removeFromSuperview];
}];
}
This way you would remove the tutorial with a simple tap but you can use a button for instance.
Is it possible to use the PresentModalViewController with the same animation that is shown when using the "pushViewController" method of a navigation controller?
As far as I know, it can't move horizontally. And what's more, when you use presentModalViewController:animated:, the previous view will disappear(be blank). But you can do like this(add your desired view to the top of your window):
UIViewController *modalViewController = [[UIViewController alloc] init];
[modalViewController.view setFrame:CGRectMake(320.0f, 0.0f, 320.0f, 480.0f)];
[modalViewController.view setBackgroundColor:[UIColor redColor]];
[[UIApplication sharedApplication].delegate.window addSubview:modalViewController.view];
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[modalViewController.view setFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)];
}
completion:nil];
[modalViewController release];
I would recommend UIStoryboardSegue instead of the approved answer above. It would seem that it's the proper way to achieve the effect and view hierarchy.
It can be used in conjunction with presentModalViewController:animated: as noted at the end of the documentation under "perform".
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIStoryboardSegue_Class/Reference/Reference.html
I currently show a modal UIViewController in the formSheet style that was presented with the coverVertical animation. I am trying to present another modal UIViewController from it, using currentContext for the presentation style and flipHorizontal for the animation style. It does work, but there is a solid white white background behind the flip as it occurs. Any advice on how to successfully present another formsheet modal UIViewController using the flipHorizontal style from a pre-existing modal UIViewController in the formSheet style would be appreciated please! Thanks
Code:
// Loading of first modalVC
- (void)showModalVC {
Modal1VC *modal1VC = [[Modal1VC alloc] init];
modal1VC.modalPresentationStyle = UIModalPresentationFormSheet;
modal1VC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:modal1VC animated:YES];
[modal1VC release];
modal1VC.view.superview.bounds = CGRectMake(0, 0, 400, 400);
}
// Loading of second modalVC in Modal1VC
- (void)buttonTapped:(id)sender {
UIViewController *modal2VC = [[UIViewController alloc] init];
modal2VC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
modal2VC.modalPresentationStyle = UIModalPresentationCurrentContext;
modal2VC.view.backgroundColor = [UIColor greenColor];
[self presentModalViewController:modal2VC animated:YES];
[modal2VC release];
modal2VC.view.superview.bounds = CGRectMake(0, 0, 400, 400);
}
UIViewController *presentingViewController = //allocate your VC
[modalViewController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
UIViewController *modalViewController = //your modal VC
[presentingViewController presentModalViewController:modalViewController animated:YES];
This is all the code you need ;)
It sounds like your transition is working, but the white background shown on the flip transition is the problem?
During the flip transition, the white background that is shown is actually the window. You can change the color that is shown by setting the backgroundColor property of window in the AppDelegate.
That would seem to be a limitation of presentModalViewController:animated:.
Instead of [self presentModalViewController:modal2VC animated:YES], you may be able to get the effect you want using UIView animations. Perhaps something like this:
[UIView transitionWithView:self.view.window
duration:0.3
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self presentModalViewController:modal2VC animated:NO];
} completion:NULL];