I have taken some code from other SO questions, but I must be doing something wonky. The app jumps from the first view to the third. What I'm trying to achieve is:
ViewController 1 Image 1 - loads with an image. Quickly cross-disolves into ViewController 1 image 2.
ViewController 1 Image 2 - flips to ViewController 2.
The cross-disolve happens but takes me to VC2. I've battered at this for most of the day. It's time to ask for help while I go sit in a bathtub.
Here's what I've been doing:
- (void)viewDidLoad
{
NSLog(#"%s", __FUNCTION__);
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"%s", __FUNCTION__);
sleep (2);
[self transition1]; //showing image 1
}
- (void) transition1 {
NSLog(#"%s", __FUNCTION__);
/*
[UIView transitionFromView:firstView
toView:secondView
duration:3.0
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished) {
[firstView removeFromSuperview];
}];
*/
//this transition doesn't happen
UIImage * secondImage = [UIImage imageNamed:#"image2.png"];
[UIView transitionWithView:self.firstView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = secondImage;
} completion:NULL];
sleep (2);
[self transition2];
}
- (void) transition2 {
NSLog(#"%s", __FUNCTION__);
self.patterns = [[PatternViewController alloc] initWithNibName:#"PatternView_iPad" bundle:nil];
self.patterns.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:patterns animated:YES completion:nil];
}
Thanks for any help.
UPDATE
I've updated my code per Moxy's suggestions as follows:
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"%s", __FUNCTION__);
[self performSelector:#selector(transition1)
withObject:nil
afterDelay:2.0f];
}
-(void)transition1
{
NSLog(#"%s", __FUNCTION__);
UIImage * secondImage = [UIImage imageNamed:#"image2.png"];
[UIView transitionWithView:self.firstView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = secondImage;
}
completion:^(BOOL finished){
[self performSelector:#selector(transition2)
withObject:nil
afterDelay:2.0f];
}];
}
-(void)transition2
{
NSLog(#"%s", __FUNCTION__);
self.patterns = [[PatternViewController alloc] initWithNibName:#"PatternView_iPad"
bundle:nil];
self.patterns.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:patterns
animated:YES
completion:nil];
}
All you need to do is to start your second animation in the first animation's completion block.
Sleep() is something you probably shouldn't be using.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"%s", __FUNCTION__);
[self performSelector:#selector(transition1)
withObject:nil
afterDelay:2.0f]
}
-(void)transition1
{
NSLog(#"%s", __FUNCTION__);
UIImage * secondImage = [UIImage imageNamed:#"image2.png"];
[UIView transitionWithView:self.firstView
duration:5.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageView.image = secondImage;
}
completion:^(BOOL finished){
[self performSelector:#selector(transition2)
withObject:nil
afterDelay:2.0f]
}];
}
-(void)transition2
{
NSLog(#"%s", __FUNCTION__);
self.patterns = [[PatternViewController alloc] initWithNibName:#"PatternView_iPad"
bundle:nil];
self.patterns.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:patterns
animated:YES
completion:nil];
}
Related
I cant seem to present my custom ShareViewController. I inherited UIViewController, not SLComposeViewController, added it to the Storyboard, but when i select an image to share, ShareViewController is not presented. Here is my entire code:
Header file:
#import <UIKit/UIKit.h>
#import <Social/Social.h>
#interface ShareViewController : UIViewController
#end
Implementation file:
#implementation ShareViewController
- (void)viewDidLoad{
[super viewDidLoad];
self.view.alpha = 0;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.view.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height);
[UIView animateWithDuration:0.25 animations:^
{
self.view.transform = CGAffineTransformIdentity;
}];
}
- (void)dismiss
{
[UIView animateWithDuration:0.20 animations:^
{
self.view.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height);
}
completion:^(BOOL finished)
{
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
}];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
for (NSItemProvider* itemProvider in ((NSExtensionItem*)self.extensionContext.inputItems[0]).attachments )
{
if([itemProvider hasItemConformingToTypeIdentifier:#"public.image"])
{
[itemProvider loadItemForTypeIdentifier:#"public.image" options:nil completionHandler:
^(id<NSSecureCoding> item, NSError *error)
{
UIImage *sharedImage = nil;
if([(NSObject*)item isKindOfClass:[NSURL class]])
{
sharedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:(NSURL*)item]];
}
if([(NSObject*)item isKindOfClass:[UIImage class]])
{
sharedImage = (UIImage*)item;
}
}];
}
}
}
#end
Breakpoint indicates that runtime does execute the code, even grabs image, but the custom view controller is not presented for some reason. Any help?
It was so stupid and it took me a while to figure it out, but for some reason, by default, custom ShareViewController view's background color is set to [UIColor clearColor]. Very stupid of Apple :), but i solved this case
I want to do continuous animation in 3 imageviews back to back I have use the below code but it shows me animation in only first imageview.I debug Code, it will Go in method but it won't show Any animation in remaining.Below is my Code
-(void)imageNewsAnimation
{
[UIView animateWithDuration:0.35f animations:^{
_imgNews.animationImages=arrnews;
_imgNews.animationDuration=1;
_imgNews.animationRepeatCount=1;
_imgNews.image = [_imgNews.animationImages lastObject];
[_imgNews startAnimating];
} completion:^(BOOL finished) {
[_imgNews stopAnimating];
[self imageEventAnimation];
} ];
}
-(void)imageEventAnimation
{
[UIView animateWithDuration:0.35f delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
_imgEvents.animationImages=arrEvents;
_imgEvents.animationDuration=1;
_imgEvents.animationRepeatCount=1;
_imgEvents.image = [_imgEvents.animationImages lastObject];
[_imgEvents startAnimating];
} completion:^(BOOL finished) {
[self imageDirectoryAnimation];
} ];
}
-(void)imageDirectoryAnimation
{
[UIView animateWithDuration:0.35f animations:^{
_imgDirectory.animationImages=arrdir;
_imgDirectory.animationDuration=1;
_imgDirectory.animationRepeatCount=1;
_imgDirectory.image = [_imgDirectory.animationImages lastObject];
[_imgDirectory startAnimating];
} completion:^(BOOL finished) {
[self imageInfoAnimation];
} ];
}
-(void)imageInfoAnimation
{
[UIView animateWithDuration:0.35f animations:^{
_imgInfo.animationImages=arrinfo;
_imgInfo.animationDuration=1;
_imgInfo.animationRepeatCount=1;
_imgInfo.image = [_imgInfo.animationImages lastObject];
[_imgInfo startAnimating];
} completion:^(BOOL finished) {
[self imageDirectoryAnimation];
} ];
}
Since startAnimating doesn't have a completion handler, I would set up something like this:
CycleImageView.h
#import <UIKit/UIKit.h>
typedef void (^CycleCompletion)(BOOL finished);
#interface CycleImageView : UIImageView
- (void)startAnimatingWithImages:(NSArray<UIImage *>*)images completion:(CycleCompletion)completion;
#end
CycleImageView.m
#import "CycleImageView.h"
#interface CycleImageView()
#property (nonatomic, copy) CycleCompletion completion;
#end
#implementation CycleImageView
- (void)startAnimatingWithImages:(NSArray<UIImage *>*)images completion:(CycleCompletion)completion {
self.completion = completion;
NSMutableArray *imageRefs = [NSMutableArray array];
for (NSInteger i = 0; i < images.count; i++) {
[imageRefs addObject:(id)images[i].CGImage];
}
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"contents"];
animation.delegate = self;
animation.calculationMode = kCAAnimationDiscrete;
animation.duration = 1;
animation.values = imageRefs;
animation.repeatCount = 1;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation forKey:#"animation"];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
if (self.completion != nil) {
self.completion(flag);
self.completion = nil;
}
}
#end
To use it:
Make imgNews, imgEvents, imgDirectory, and imgInfo all subclasses of CycleImageView. Then, using your supplied methods and variables, the implementation would change to this:
- (void)imageNewsAnimation {
[_imgNews startAnimatingWithImages:arrnews completion:^(BOOL finished) {
if (finished) {
[self imageEventAnimation];
}
}];
}
- (void)imageEventAnimation {
[_imgEvent startAnimatingWithImages:arrEvents completion:^(BOOL finished) {
if (finished) {
[self imageDirectoryAnimation];
}
}];
}
- (void)imageDirectoryAnimation {
[_imgDirectory startAnimatingWithImages:arrdir completion:^(BOOL finished) {
if (finished) {
[self imageInfoAnimation];
}
}];
}
- (void)imageInfoAnimation {
[_imgInfo startAnimatingWithImages:arrinfo completion:^(BOOL finished) {
if (finished) {
// NOTE: Are you intentionally creating this indefinite animation loop?
[self imageDirectoryAnimation];
}
}];
}
Edit:
Created a gist for CycleImageView, as well.
Perform animation with timer like
In viewDidLoad:
timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(imageAnimation:) userInfo:nil repeats:YES];
i = 0;
then
- (void)imageAnimation:(UIImage *) image {
i++;
if (i > 2) {
i = 0;
}
NSArray *arr = #[[UIImage imageNamed:#"img1"],[UIImage imageNamed:#"img2"],[UIImage imageNamed:#"img3"]];
UIImage * toImage = [arr objectAtIndex:i];
[UIView transitionWithView:self.view
duration:2
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.imageview.image = toImage;
} completion:NULL];
}
Hope this help!
I am making an image editor application.
I am able to change the UIImage of a UIImageView but I want it to be more efficient and beautiful.
Currently I am changing UIImage as
if(image)
{
userImageView.image = image;
}
It directly changes the UIImage. How can I make a fadeIn-fadeOut effect?
UIImage *image = [UIImage imageWithData:imageData];
[UIView transitionWithView:YourUIImageView
duration:2.0f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
YourUIImageView.image = image;
} completion:nil];
And Do some googling before asking this question already has and answer.
Check THIs
try this...
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.fadeDuration=1;
}
return self;
}
-(void)setImage:(UIImage *)newImage{
if(!self.image||self.fadeDuration<=0){
super.image=newImage;
} else {
UIImageView *iv=[[UIImageView alloc] initWithFrame:self.bounds];
iv.contentMode=self.contentMode;
iv.image=super.image;
iv.alpha=1;
[self addSubview:iv];
super.image=newImage;
[UIView animateWithDuration:self.fadeDuration delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
iv.alpha=0;
} completion:^(BOOL finished) {
[iv removeFromSuperview];
}];
}
}
Try something like this:
-(void)fade{
//fade out
[UIView animateWithDuration:1.0f animations:^{
[userImageView setAlpha:0.0f];
} completion:^(BOOL finished) {
//fade in
[UIView animateWithDuration:1.0f animations:^{
userImageView.image = image;
[userImageView setAlpha:1.0f];
} completion:nil];
}];
}
Based on the Apple documentation I came up with the following method to switch between controllers in a containment controller. When there is an oldC I am getting Unbalanced calls to begin/end appearance transitions for <...> on the console.
- (void) showController:(UIViewController*)newC withView:(UIView*)contentView animated:(BOOL)animated
{
UIViewController *oldC = self.childViewControllers.firstObject;
if (oldC == newC) {
return;
}
[oldC willMoveToParentViewController:nil];
[self addChildViewController:newC];
newC.view.frame = (CGRect){ 0, 0, contentView.frame.size };
[contentView addSubview:newC.view];
if (animated && oldC != nil) {
oldC.view.alpha = 1.0f;
newC.view.alpha = 0.0f;
[self transitionFromViewController:oldC toViewController:newC duration:0.25f options:0 animations:^{
oldC.view.alpha = 0.0f;
newC.view.alpha = 1.0f;
} completion:^(BOOL finished) {
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}];
} else {
oldC.view.alpha = 0.0f;
newC.view.alpha = 1.0f;
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}
}
This is how I call it:
- (IBAction) buttonSignIn:(id)sender
{
[self showController:self.signInViewController withView:self.contentView animated:(sender != nil)];
}
- (IBAction) buttonSignUp:(id)sender
{
[self showController:self.signUpViewController withView:self.contentView animated:(sender != nil)];
}
To track this down I am logging the appearance transitions
-(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated
{
[super beginAppearanceTransition:isAppearing animated:animated];
NSLog(#"**begin %#", self);
}
-(void)endAppearanceTransition
{
[super endAppearanceTransition];
NSLog(#"**end** %#", self);
}
This is what the log looks like:
] **begin <SignInViewController: 0x10c769a20>
] **begin <SignUpViewController: 0x10c768770>
] Unbalanced calls to begin/end appearance transitions for <SignUpViewController: 0x10c768770>.
] **end** <SignUpViewController: 0x10c768770>
] **end** <SignInViewController: 0x10c769a20>
Now I am a little puzzled. What's the problem here?
Turns out transitionFromViewController:toViewController:duration:options:animations:completion: also adds the view.
This method adds the second view controller’s view to the view hierarchy and then performs the animations defined in your animations block. After the animation completes, it removes the first view controller’s view from the view hierarchy.
Which means the addSubview needs to be adjusted accordingly.
- (void) showController:(UIViewController*)newC withView:(UIView*)contentView animated:(BOOL)animated
{
UIViewController *oldC = self.childViewControllers.firstObject;
if (oldC == newC) {
return;
}
[oldC willMoveToParentViewController:nil];
[self addChildViewController:newC];
newC.view.frame = (CGRect){ 0, 0, contentView.frame.size };
if (animated && oldC != nil) {
oldC.view.alpha = 1.0f;
newC.view.alpha = 0.0f;
[self transitionFromViewController:oldC toViewController:newC duration:0.25f options:0 animations:^{
oldC.view.alpha = 0.0f;
newC.view.alpha = 1.0f;
} completion:^(BOOL finished) {
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}];
} else {
[contentView addSubview:newC.view];
oldC.view.alpha = 0.0f;
newC.view.alpha = 1.0f;
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}
}
old code
[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self.view addSubview:toVC.view];
[toVC.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
}];
[self transitionFromViewController:fromVC
toViewController:toVC duration:0
options:UIViewAnimationOptionTransitionNone
animations:^{
} completion:^(BOOL finished) {
[fromVC.view removeFromSuperview];
[fromVC removeFromParentViewController];
[toVC didMoveToParentViewController:self];
self.currentVC = toVC;
}];
new code, it's ok
[self addChildViewController:toVC];
[fromVC willMoveToParentViewController:nil];
[self transitionFromViewController:fromVC
toViewController:toVC duration:0
options:UIViewAnimationOptionTransitionNone
animations:^{
} completion:^(BOOL finished) {
[fromVC.view removeFromSuperview];
[fromVC removeFromParentViewController];
[toVC didMoveToParentViewController:self];
self.currentVC = toVC;
}];
I set the duration to 0, which means animation:NO for the transitionFromViewControllercall.
I am trying to use dismissModalViewController:Animated: to dismiss my view, but it is not dismissing it, no matter what I try. You can see my attempts to release the view in the hideSplash method at the bottom. Please, if anyone can help it would be greatly appreciated. My code posted below:
#import "SplashViewController.h"
#implementation SplashViewController
- (void) didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void) viewDidUnload {
}
- (void) dealloc {
[super dealloc];
}
-(void) showSplash {
modalViewController = [[UIViewController alloc] init];
modalViewController.view = modelView;
[self presentModalViewController:modalViewController animated:NO];
[activityIndicator startAnimating ];
//[self bigcalculation];
//[self performSelector:#selector(hideSplash) withObject:nil afterDelay:2.0];
}
- (void) viewDidAppear:(BOOL)animated {
NSLog(#"View Did Appear");
[self bigcalculation];
}
- (void) bigcalculation {
NSLog(#"Big Calc Start");
for (int i = 0; i <= 648230; i++) {
for (int j = 0; j <= 1200; j++) {
}
}
NSLog(#"Big Calc End");
[self performSelector:#selector(hideSplash) withObject:nil];
}
- (void) hideSplash {
NSLog(#"Hide");
//[self dismissModalViewControllerAnimated:NO];
//[[self parentViewController] dismissModalViewControllerAnimated:YES];
[[self modalViewController] dismissModalViewControllerAnimated:YES];
NSLog(#"End Hide");
}
#end
The modal view controller is not responsible for dismissal. That burden is placed on the view controller that called the modalViewController.
Try replacing:
[[self modalviewController] dismissModalViewControllerAnimated:YES];
with
[self dismissModalViewControllerAnimated:YES];
Try to use this:
[self.parentViewController dismissModalViewControllerAnimated:NO];
I found the solution in case anyone else has this issue the line
[self performSelector:#selector(hideSplash) withObject:nil];
Should be
[self performSelector:#selector(hideSplash) withObject:nil afterDelay:0.0];