Selecting image during Animation - ios

I have an outlet called myImage for an imageView that is set up with an animation of 5 images. With a Tap Gesture Recognizer on it, I want to have the users tap on the correct image as it quickly passes to move onto the next level.
There is an error in my code and this does not work:
- (void)viewDidLoad {
[super viewDidLoad];
self.myImage.animationImages =
[NSArray arrayWithObjects:
[UIImage imageNamed:#"examplePic1.png"],
[UIImage imageNamed:#"examplePic2.png"],
[UIImage imageNamed:#"correctPic.png"],
[UIImage imageNamed:#"examplePic4.png"],
[UIImage imageNamed:#"examplePic5.png"],
nil];
[self.myImage setAnimationRepeatCount:0];
self.myImage.animationDuration = 1;
[self.myImage startAnimating];
}
- (IBAction)TapGestureRecognizer:(id)sender {
if (self.myImage.image = [UIImage imageNamed:#"correctPic.png"]) {
// Launch next level
}
else {
// Vibrate Device and subtract points from score
}
}

You have a fundamental misconception in your code about objects and equality. I assume that you meant "==" in your TapGestureRecognizer method. However, even if you changed the = to == would not give you what you want.
The expressions like
[UIImage imageNamed:#"examplePic1.png"]
call a class method of UIImage that creates a new UIImage object. You have created 5 of these objects, put them into an array, an set the animationImage array of your UIImage object to these images. These objects are all different objects from myView.image: I can tell because I can see from your code that you have assigned 5 new objects to the animationObjects array. Your == test cannot ever work because you are comparing self.image to a brand new UIImage object.
What you are trying to do is determine which image the user touched. There is no method in UIImageView that tells you which animation UIImage is currently showing. You are assuming that the image property of the view will be changed as the animation images are displayed, but there is no reason for this assumption to be true: it is certainly not stated in the documentation. Even if you corrected your code (by doing something like this):
if(self.image == [self.animationImages objectAtIndex:2]){
}
your code would not be correct.
If I were trying to do what you want, I would create a UIView with 5 UIImageView as subview, each with their own gesture recognizer. I would use the frame property of each subview to do my animation.

Looks like the options are to determine which image "should" be showing based upon the startTime of the animation.
Determine which of its animationImages a UIImageView is displaying?
Or, just use a timer to set the currently displayed image.
Detect which image was clicked in UIImageView with animationImages

Related

Should I use GIF file or animation code on iOS?

I intend to make a splash screen on iOS consists of a person, a chair objects. Each of these objects has seperated aspects like the hands, head, body and feets that animated together. I wonder which is better way to go? Importing a GIF file or coding CALayer objects then adding animation?
You can't use GIF files or any code for animation for your launchscreen (splash screen), you can only use a static image, a PNG or JPG (if the launchscreen is a storyboard).
So, if you want your app's startup with some animation then you should manage it in your first view controller.
You can animate imageview with image sets like,
UIImageView* myImageViewForAnimation = [[UIImageView alloc] initWithFrame:self.view.bounds];
myImageViewForAnimation.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1"],
[UIImage imageNamed:#"image2"],
[UIImage imageNamed:#"image3"],
[UIImage imageNamed:#"image4"], nil];
myImageViewForAnimation.animationDuration = 1.0f;
myImageViewForAnimation.animationRepeatCount = 0;
[myImageViewForAnimation startAnimating];
[self.view addSubview: myImageViewForAnimation];
Update (as asked in comment) :
You can get your view on which you have added gesture recognizer in your action method or you can set tag to every imageview and handle it in action method.
For example,
-(void)tapOnProfileImage : (UITapGestureRecognizer*)recog{
UIImageView *tempView = (UIImageView *)recog.view;
// or
if (recog.view.tag == 1) {
// image 1
}
if (recog.view.tag == 2) {
//image 2
}
}
So, on every image view, you should add target with selector - tapOnProfileImage and you can differentiate it as mentioned in above code snippet!
You can use gif image but not directly on launch xib. You create one view controller and load gif image on that view controller, once animation is completed then remove this controller from navigation stack. https://github.com/Flipboard/FLAnimatedImage use this gif image view control.

Morphing with CoreAnimation

I am creating an Navigation Button. When user presses it, the image of the button should change, reflecting it's state (e.g. menu opened / closed). I decided to do a morphing-liek animation for this. Is it possible to implement with CoreAnimation? What animation type do I need to use?
I attached the picture to clearly illustrate what I want. Also, you might see these animations in "Pimp My Ride" show.
You can use animationImages property of UIImageView for this, like this:
myImageView = [[UIImageView alloc] initWithFrame:myImageViewbounds];
//Add images which will be used for the animation using an array. These should exist in your project and bundle already.
myImageView.animationImages = #[[UIImage imageNamed:#"1.png"], [UIImage imageNamed:#"2.png"],[UIImage imageNamed:#"3.png"], [UIImage imageNamed:#"4.png"],[UIImage imageNamed:#"5.png"]];
//Set the duration of the entire animation
myImageView.animationDuration = 0.5;
//Set the repeat count. If you don't set that value, by default will be a loop (infinite)
myImageView.animationRepeatCount = 1;
//Start the animation
[myImageView startAnimating];
To ensure smooth morphing like transition you may check out GPUImage which has many great blur filters. Ideally you should be able to wrap a blur animation between two image animations to achieve what you want.

How can I make an animation correlate to the current position of a UIImageView?

I have an ImageView that changes between 2 different images. When an event happens and it's in ImageView1, I want it to play a specific animation. And when an event happens and it's in ImageView2, I want it to play a specific, different animation. My code set up so far is essentially
if (ImageView1 == YES)
{
ImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"ImageAnimate1.png"],
[UIImage imageNamed:#"ImageAnimate2.png"],
[UIImage imageNamed:#"ImageAnimate3.png"],
[UIImage imageNamed:#"ImageAnimate4.png"], nil];
[ImageView setAnimationRepeatCount:1];
ImageView.animationDuration = 1;
[ImageView startAnimating];
}
else
{
ImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"ImageAnimate5.png"],
[UIImage imageNamed:#"ImageAnimate6.png"],
[UIImage imageNamed:#"ImageAnimate7.png"],
[UIImage imageNamed:#"ImageAnimate8.png"], nil];
[ImageView setAnimationRepeatCount:1];
ImageView.animationDuration = 1;
[ImageView startAnimating];
}
I'm aware it doesn't need to have 2 different sets of animation repeats and duration, but that was just the beginning in the event they change later.
The main problem is, the first set of animations only plays if i'm currently setting it to ImageView1. What I mean is, If i'm tapping/ touching the screen to the left it creates ImageView1, and if i'm tapping to the right it creates ImageView2. How can I change it from having to currently be tapping to the left to play that animation, to just playing the animation when the ImageView is currently displayed as such?
It might be as simple as setting it to the current UIImage, but i'm not exactly sure how to do it.
In other words, I would want to somehow write.
if (UIImage ImageViewLeft = YES)
ImageView.animationImages etc etc etc.
else ImageView.animationImages would be the second variation.
EDIT: I just changed it to
if (ImageView.image == [UIImage imageNamed:#"ImageLeft.png"])
{ code here
What happens is though now i cant change direction until another event happens. Essentially it will be stuck in either left or right until the event happens and then it correlates to the correct image then. .
A simple way would be to create a BOOL for imageIsRight. You set it to YES when you start playing an animation on the right, you set it to NO, when it goes left. Then create a timer which fires every .05 seconds (or whatever works). That timer can call a method which checks the BOOL you created and either repeats/continues the current animation or stops it and starts the other.
The above details may not be perfect for your scenario, which is a bit fuzzy to me, but the approach should get you where you need to be.

Change Back And Forth UIImages

Hi I’m trying to get an image to change on a method call and if the method is recalled the original image comes back
-(void)change
{
if ((player.image = [UIImage imageNamed:#"first.png"]))
{
player.image = [UIImage imageNamed:#"second.png"]));
}
else
{
player.image = [UIImage imageNamed:#"first.png"]));
}
}
This works change the "first.png" image to "second.png" but when called again it doesn’t.
Where am I going wrong?
As pointed out by Michael Dautermann, the way you're comparing two UIImages is wrong. Can't you simply keep an NSString property that tells you the image you're showing?
-(void)change
{
if ([self.displayedImageTitle isEqualToString:#"first.png"]){
player.image = [UIImage imageNamed:#"second.png"]));
self.displayedImageTitle = #"second.png";
}
else{
player.image = [UIImage imageNamed:#"first.png"]));
self.displayedImageTitle = #"first.png";
}
}
In your code above, you're making an invalid assumption that "[UIImage imageNamed: #"first.png"]" will always be the same UIImage object when you do a comparison. That isn't true. Every time you call the "imageNamed" API, you may be creating a brand new UIImage object.
Now, since UIImage object doesn't know anything about file names or image titles, you need to keep track of which image is being displayed and then toggle on that.
I'd suggest creating a subclassed UIImage object that has a filename or title property (that you would also need to set), or have your two UIImages as properties or ivars loaded into memory (that is, if these aren't giant memory hogging images) and then do your toggling.

new created UIImageViews do not show up when added as subview

upon a tap, I want to let a few UIImageView objects appear on an underlaying UIView.
So I created the following action:
- (IBAction)startStars: (id) sender
{
UIView* that = (UIView*) sender; // an UIButton, invisible, but reacting to Touch Down events
int tag = that.tag;
UIView* page = [self getViewByTag:mPages index:tag]; // getting a page currently being viewed
if ( page != nil )
{
int i;
UIImage* image = [UIImage imageNamed:#"some.png"];
for ( i = 0 ; i < 10 ; ++i )
{
// create a new UIImageView at the position of the tapped UIView
UIImageView* zap = [[UIImageView alloc] initWithFrame:that.frame];
// assigning the UIImage
zap.image = image;
// make a modification to the position so we can see all instances
CGPoint start = that.layer.frame.origin;
start.x += i*20;
zap.layer.position = start;
[page addSubview:zap]; // add to the UIView
[zap setNeedsDisplay]; // please please redraw
[zap release]; // release, since page will retain zap
}
[image release];
}
}
Unfortunately, nothing shows up. The code gets called, the objects created, the image is loaded, even the properties are as expected.
Page itself is a real basic UIView, created with interface builder to contain other views and controls.
Still, nothing of this can be seen....
Has anyone an idea what I am doing wrong? Do I need to set the alpha property (or others)?
Thanks
Zuppa
A couple of things I would check:
Logging to make sure this section of code is actually being called.
Use the designated initializer for UIImageView:
[[UIImageView alloc] initWithImage:image];
This will ensure that your new view has the correct size for the image - what are the relative sizes of zap and your image? It could be out of the frame.
Ensure that the image actually exists and is created
Try not adjusting the layer properties, but setting the center of the image view instead. In fact, in the first instance don't adjust it at all and just see if you can see anything. I'm not sure but I think position might be moving the layer within the view so could be moving your image out of sight. Try:
CGPoint newCenter = that.frame.origin;
newCenter.y += zap.bounds.size.height/2;
newCenter.x += i*20;
zap.center = origin;
setNeedsDisplay is not required. Obviously from your comments it was an act of desparation!
Is your UIImage nil?
You don't need to have the .png extension for imageNamed: to work. It might not even work correctly if you put it in, I'm not sure. You're also overreleasing your image. imageNamed: returns an autoreleased image so there is no reason to call release on the image unless you're also calling retain on it somewhere.
I see a potential error: on second invocation you will re-add another copy, so take care about removing subviews before adding anew copy. Yu can alternatively move a previous view.
99% of my cases about non-visible views with images are wrong names, so as suggested, load using a temp var:
UIImage img = [UIImage imageNamed..];
and test img.

Resources