My problem is...
I have the object of parent view controller and i wanted to animate second view controller over that.
So i added a subview called backgroundview over the view of parentvc.view and then the view which needs to be drawn over the backgroundView.
But after animation completes for a second, i can see the views the way i want them to be but then it is replaced by a complete black screen.
I think my topmost view is redrawn so how do i rectify this issue.
Code :-
- (void)viewDidLoad {
[super viewDidLoad];
//_colorCaptureOptions = [NSArray arrayWithObjects: #"Camera", #"Color Slider / Color Wheel", nil];
mExtractionQueue = [[NSOperationQueue alloc] init];
[mExtractionQueue setMaxConcurrentOperationCount:1];
CGRect screenRect = [[UIScreen mainScreen] bounds];
//CGRect screenRect = self.view.frame;
self.backgroundView = [[UIView alloc] initWithFrame:screenRect];
self.backgroundView.backgroundColor = [UIColor clearColor];
[self.parentVC addChildViewController:self];
[self.parentVC.view addSubview:self.backgroundView];
//[self didMoveToParentViewController:self.parentVC];
UITapGestureRecognizer *guideTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleScrimSelected)];
[self.backgroundView addGestureRecognizer:guideTap];
[self.backgroundView addSubview:self.view];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat viewHeight = 150;
self.backgroundView.alpha = 0.0;
self.view.alpha = 1;
self.view.frame = CGRectMake(0, screenRect.size.height, screenRect.size.width, viewHeight);
[UIView animateWithDuration:0.2
delay:0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
self.backgroundView.alpha = 1.0;
self.view.frame = CGRectMake(0, screenRect.size.height - viewHeight, screenRect.size.width, viewHeight);
}
completion:^(BOOL _finished) {
}];
}
}
Well, for clarity you'd better to provide few screenshots.
For all the rest:
Possibly, your background view is simply black that leads to black screen. Or it even is [UIColor clearColor]
better not use childViewController, it breaks MVC
better not change frame inside animation directly
If you want present another controller with animation, use this UIViewControllerTransitioningDelegate and this UIViewControllerAnimatedTransitioning in your objects, so do not reinvent transitions. Refer to this custom controller transition tutorial
Hope this may help you
EDIT:
[UIColor clearColor] removes colour entirely, so that means you will have no color at all.
The best solution for you now is rewrite those controllers, split up one from another, get rid of container for viewControllers, change animation to custom and than problem will disappear as a magic. If you solve you problem, do not forget to mark question as resolved, please
Related
I open a modal window from my AppDelegate (actually called from another ViewController, not the best way..):
UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
UIVisualEffectView *myView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
myView.frame = self.main.view.bounds;
myModalWindow.view.frame = self.main.view.bounds;
myModalWindow.view.backgroundColor = [UIColor clearColor];
[myModalWindow.view insertSubview:myView atIndex:0];
myModalWindow.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self.main presentViewController:myModalWindow animated:YES completion:nil];
The i try to minimize that window to attach to the bottom of the screen (from within the modal):
- (void)minimizeToBottom {
[UIView animateWithDuration:ViewFadeInOutTime animations:^{
CGRect frame = self.view.frame;
frame.origin.y = [[UIScreen mainScreen] bounds].size.height - self.menuBar.frame.size.height;
self.view.frame = frame;
} completion:nil];
}
But when I do this, the view in the background can't receive any touches/interaction. How do I still interact with my main view, while having the modal staying at the bottom of the screen. Just like "Spotify's small player" and others.
Any help is appreciated!
EDIT - SOLVED!
Changed from modal to view and then I was doing
[self.window addSubview: myWindow.view];
But I changed that to
[self.window.rootViewController.view addSubview: myWindow.view];
I have a UITableView with custom cells in it. Each cell has 4 UILabels and 3 UIImageViews, all with user interaction disable.
At didSelectRowAtIndexPath, another view controller (with transparent background) is loaded and animated added to the root view. Simulating a pop up:
UIView *rootView = UIApplication.sharedApplication.delegate.window.rootViewController.view;
[rootView addSubview:view];
When the app is first installed in the device (built for debug or release), the subview is not seen when a UITableViewCell is selected, it just appears after the cell receives a long press (~ 15 seconds) and crashes. If I open again it works well, or without the long press, if I just build it again it works as expected too.
Here are the methods:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Cell is selected");
self.popUpViewController = [[PopupViewController alloc] initWithNibName:#"PopupViewController" bundle:nil];
self.popUpViewController.message = [self.arrayOfMessages objectAtIndex:indexPath.row];
[self presentTransparentModalViewController:self.popUpViewController animated:YES withAlpha:1];
}
You can check the called method below:
-(void) presentTransparentModalViewController: (PopupViewController *) aViewController
animated: (BOOL) isAnimated
withAlpha: (CGFloat) anAlpha{
self.popUpViewController = aViewController;
UIView *rootView = UIApplication.sharedApplication.delegate.window.rootViewController.view;
UIView *view = aViewController.view;
view.opaque = NO;
view.alpha = anAlpha;
[view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIView *each = obj;
each.opaque = NO;
each.alpha = anAlpha;
}];
if (isAnimated) {
//Animated
CGRect mainrect = rootView.bounds;
/* In case you want to add to self.view, use the following instead of the line
above:
CGRect mainrect = [[UIScreen mainScreen] bounds];
*/
CGRect newRect = CGRectMake(0, mainrect.size.height, mainrect.size.width, mainrect.size.height);
[rootView addSubview:view];
/* In case you want to add to self.view, use the following instead of the line
above:
[self.view addSubview:view];
*/
view.frame = newRect;
[UIView animateWithDuration:0.25
animations:^{
view.frame = mainrect;
} completion:^(BOOL finished) {
//
}];
}else{
view.frame = [[UIScreen mainScreen] bounds];
[rootView addSubview:view];
}
}
DETAIL: If the view is added as subview of self.view it works as expected. Why it doesn't work for rootViewController.view?
Does anyone knows why it happens and / or how to fix it?
EDIT:
I checked to see if the view is added to rootView.
So, I have rootViewController.view add a subview with transparent background to it.
What should happens: We should see the subview, right?
What actually happens: We don't see any visual change.
How do I know the view is there: If I create an empty view and add my rootView to it, it's shown there.
It happens only after installation, in the first build.
Best regards,
Arthur A.
I'm trying to show a fullscreen picture from a smaller one included in a custom UITableViewCell. My code is highly linked to this article
By the way, in this example, the frame : [[UIScreen mainScreen] bounds]is not the good one for me. It's the an UIScrollView's bounds that I've got. I this to add the main screen through a variable inside the cell directly when each cell is created. So I've customized the previous example like this :
//viewDidLoad
self.globalView.frame = [[UIScreen mainScreen] bounds];
//cellForRowAtIndexPath
[cell setFullScreenView:self.globalView];
//fullScreenMethod
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = imageView.frame;
[imageView setFrame:self.fullScreenView.frame];
}completion:^(BOOL finished){
isFullScreen = YES;
}];
return;
}
My problem is that the imageView's new frame is not a full screen but still the UIScrollView's one.
Thank you for your help !
Best approach is create one temporary UIImageView and Show it in full screen,
For animation simply add the temporary UIImageView to location where the image view exists and animate it to full-screen and do revers for normal
Add tap gesture to UIImageView and add this bannerTapped as selector
//This will create a temporary imaget view and animate it to fullscreen
- (void)bannerTapped:(UIGestureRecognizer *)gestureRecognizer {
NSLog(#"%#", [gestureRecognizer view]);
//create new image
temptumb=(UIImageView *)gestureRecognizer.view;
//fullview is gloabal, So we can acess any time to remove it
fullview=[[UIImageView alloc]init];
[fullview setContentMode:UIViewContentModeScaleAspectFit];
[fullview setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bckgrd.png"]]];
fullview.image = [(UIImageView *)gestureRecognizer.view image];
CGRect point=[self.view convertRect:gestureRecognizer.view.bounds fromView:gestureRecognizer.view];
[fullview setFrame:point];
[self.view addSubview:fullview];
[UIView animateWithDuration:0.5
animations:^{
[fullview setFrame:CGRectMake(0,
0,
self.view.bounds.size.width,
self.view.bounds.size.height)];
}];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(fullimagetapped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[fullview addGestureRecognizer:singleTap];
[fullview setUserInteractionEnabled:YES];
}
//This will remove the full screen and back to original location.
- (void)fullimagetapped:(UIGestureRecognizer *)gestureRecognizer {
CGRect point=[self.view convertRect:temptumb.bounds fromView:temptumb];
gestureRecognizer.view.backgroundColor=[UIColor clearColor];
[UIView animateWithDuration:0.5
animations:^{
[(UIImageView *)gestureRecognizer.view setFrame:point];
}];
[self performSelector:#selector(animationDone:) withObject:[gestureRecognizer view] afterDelay:0.4];
}
//Remove view after animation of remove
-(void)animationDone:(UIView *)view
{
//view.backgroundColor=[UIColor clearColor];
[fullview removeFromSuperview];
fullview=nil;
}
It can't take a full screen frame because its parent view is the scrollView. Either show view modally or somehow move imageView directly under view controller's main view.
I've been struggling with this for a long and I just can't find out what's wrong here. I actually do have an idea - I think that somehow the view I am adding and trying to animate is not yet included to the view hierarchy and that's why core animation isn't wasting cycles to animate. I did some other animations in the project successfully but I am running them in the ViewController's viewDidLoad method. Here is my code:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.opaque = NO;
self.backgroundColor = [UIColor colorWithWhite: 1.0 alpha: 0.7];
[self addTrack];
}
return self;
}
- (void)addTrack
{
//init the track here
UIView *track = [[UIView alloc] initWithFrame: CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)];
track.backgroundColor = [UIColor whiteColor];
[self addSubview: track];
//transform the track for its initial scale
float scaleFactorX = 0.01;
track.layer.anchorPoint = CGPointMake(0, 0);
track.layer.position = CGPointMake(0, 0);
track.transform = CGAffineTransformMakeScale(scaleFactorX, 1.0);
//animate the track here
[UIView animateWithDuration:8 delay:0.3 options:UIViewAnimationOptionCurveEaseOut
animations:^{
NSLog(#"animation is running.");
track.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished) {
NSLog(#"animation finished.");
}];
}
So the result is that the "track" is scaling to its original size immediately. I also tried to call addTrack inside the didMoveToSuperview method so I can make sure that the containing view is added to the view hierarchy but with the same result. I tried other animations inside that class like adding alpha animation to the containing view but with no success again ..
Try calling your animations after loading the view so that you can see it.
-(void)viewDidAppear:(BOOL)animated
{
[self addTrack];
}
You shouldn't have put animations in the init method to start with. Try calling them immediately after your view was actually displayed (added on a superview) and see what happens then.
I have a UIView which is located offscreen and I'm animating the frame so that the view slides in offscreen from the bottom and is visible. I'd like to simultaneously animate the alpha property of a UILabel on the view as well so it fades in. Unfortunately it appears I can't do the alpha animation because the view is offscreen and doesn't appear to take hold. It looks something like this:
nextCell.titleLabel.alpha = 0;
[UIView animateWithDuration:collapsedAnimationDuration animations:^{
CGRect newFrame = lastCell.frame;
newFrame.origin = CGPointMake(lastCell.frame.origin.x , lastCell.frame.origin.y + THREAD_CELL_HEIGHT);
nextCell.frame = newFrame;
nextCell.titleLabel.alpha = 1;
}];
Is it not possible to start animating the alpha of the subview because it's offscreen? If I position the view on screen and then try the animation it looks great but that's not the effect I'm going for. Thanks for your help.
Is this code executed in cellForRowAtIndexPath? If so, try moving it to tableView:willDisplayCell:forRowAtIndexPath:. The table view resets various properties of the cell before displaying it.
From the AppDelegate didFinishLaunching method:
self.myView = [[MyView alloc] initWithFrame:CGRectMake(320, 480, 400, 400)];
self.myView.titleLabel.text = #"test text";
self.myView.titleLabel.alpha = 0;
[UIView animateWithDuration:10.0 animations:^{
CGRect newFrame = self.myView.frame;
newFrame.origin = CGPointMake(0 , 0);
self.myView.frame = newFrame;
self.myView.titleLabel.alpha = 1;
}];
[self.viewController.view addSubview:self.myView];
MyView is just this:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self addSubview:self.titleLabel];
}
return self;
}
- (UILabel *)titleLabel
{
if (!_titleLabel) {
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
}
return _titleLabel;
}
I did no important changes to the code you presented and it worked fine. So assuming you're not doing what Tim mentioned (it won't work if you're doing it), we need more details to help you out.