NSArray *imageNames = #[#"2_00000.png", #"2_00001.png", #"2_00002.png", #"2_00003.png",
#"2_00004.png", #"2_00005.png", #"2_00006.png", #"2_00007.png",
#"2_00008.png", #"2_00009.png", #"2_00010.png", #"2_00011.png",
#"2_00012.png", #"2_00013.png", #"2_00014.png", #"2_00015.png",
#"2_00016.png", #"2_00017.png", #"2_00018.png", #"2_00019.png",
#"2_00020.png", #"2_00021.png", #"2_00022.png", #"2_00023.png",
#"2_00024.png", #"2_00025.png", #"2_00026.png", #"2_00027.png",
#"2_00028.png", #"2_00029.png", #"2_00030.png", #"2_00031.png",
#"2_00032.png", #"2_00033.png", #"2_00034.png", #"2_00035.png",
#"2_00036.png", #"2_00037.png", #"2_00038.png", #"2_00039.png",
#"2_00040.png", #"2_00041.png", #"2_00042.png", #"2_00043.png",
#"2_00044.png", #"2_00045.png", #"2_00046.png", #"2_00047.png",
#"2_00048.png", #"2_00049.png", #"2_00050.png", #"2_00051.png",
#"2_00052.png", #"2_00053.png", #"2_00054.png", #"2_00055.png",
#"2_00056.png", #"2_00057.png", #"2_00058.png", #"2_00059.png",
#"2_00060.png", #"2_00061.png", #"2_00062.png", #"2_00063.png"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 1; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
// Normal Animation
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(-6, 40, 200, 1034)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 2;
animationImageView.animationRepeatCount = 0;
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
If you know the animationRepeatCount before starting your animation
animationImageView.animationRepeatCount = 1 //For 1 loop
animationImageView.image = animationImageView.animationImages.lastObject;
For stoping animation dynamically
animationImageView.animationRepeatCount = 0 //infinite loop
When you need to stop the animation
[animationImageView stopAnimating];
animationImageView.image = animationImageView.animationImages.lastObject;
first set the animationRepeatCount to 1 and after starting the animation create a block that fires after the animation duration in this block set the animationImageView image to the last image .
dispatch_time_t dispatchAfter = dispatch_time(DISPATCH_TIME_NOW, animationImageView.animationDuration * NSEC_PER_SEC);
dispatch_after(dispatchAfter, dispatch_get_main_queue(), ^(void){
animationImageView.image = [images lastObject];
});
You could use transitionWithView:duration:options:animation:completion: of UIView for animating your UIImageView.
- (void)animatePictureTransition:(NSMutableArray *)arrayImages{
[UIView transitionWithView:imageViewButton
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
UIImage *newImage = (UIImage *)arrayImages.firstObject;
imageViewButton.image = newImage;
} completion:^(BOOL finished){
[arrayImages removeObjectAtIndex:0];
if(arrayImages.count) {
[self animatePicturesTransition:arrayImages];
}
}];
}
You could use this recursive, and call the method again inside the completion blog and pass through the remaining UIImages this way there shouldn't be a problem to stop at the last UIImages.
I would also recommend you, to load the UIImages dynamically from the resource folder in this way:
- (NSMutableArray *)getImagesWithSuffix:(NSString *)start andEndSuffix:(NSString *)end{
NSMutableArray *imageArray = [[NSMutableArray alloc] init];
for (int i = 1; i < 100; i++) {
NSString *fileName = [NSString stringWithFormat:#"%#%d%#.png", start, i, end];
if([self fileExistsInProject:fileName]){
[imageArray addObject:[UIImage imageNamed:fileName]];
} else {
break;
}
}
return imageArray;
}
Always writing all names of your UIImages takes a lot of time and can cause any problems. This way you just have to order your pictures so you can loop over.
To use this code, create a category of NSMutableArray and you can use it!
problem is with this line..
animationImageView.animationRepeatCount = 0;
by setting animationRepeatCount = 0 its set to infinite by default.
if u want it stop at last image you can go with
animationImageView.animationRepeatCount = 1; // specify no of times u need to run your animation.
Related
I'm trying to animate an imageview by providing it with an array of images. These images have been extracted from a spritesheet having lots of images one after the other.
Here is my code:
-(NSMutableArray*)getIndividualImagesFromImage:(UIImage*)collectionOfEmoticonImages
{
NSMutableArray *imagesArray = [[NSMutableArray alloc] init];
//Let's find out the total number of images in this big image
int totalEmoticonImages = collectionOfEmoticonImages.size.width/WIDTH_HEIGHT_OF_EMOTICONS;
for(int emoticonIndex = 0; emoticonIndex < totalEmoticonImages; emoticonIndex++)
{
//crop the image at each index and put smaller images in the array
UIImage *croppedImage = [[UIImage alloc] init];
croppedImage = [self cropImage:collectionOfEmoticonImages atIndex:emoticonIndex];
[imagesArray addObject:croppedImage];
}
return imagesArray;
}
-(void)getEmoticonImageViewAnimating:(NSInteger)index
{
imagesArray = [self getIndividualImagesFromImage:[emoticonsPNGImages objectAtIndex:index]];
//Animate using the images in imagesArray
emoImageView.animationImages = [NSArray arrayWithArray:imagesArray];
emoImageView.animationDuration = 2;
emoImageView.animationRepeatCount = 1;
[emoImageView startAnimating];
[self performSelector:#selector(animationDidFinish) withObject:nil
afterDelay:emoImageView.animationDuration];
}
Everything works fine if I comment [emoImageView startAnimating]; line. But with this statement, animation works fine for 6 times but then I get a semaphore_wait_trap on trying to run it 7th time.
Any pointers?
I am interested in obtaining an animation that not only animates from point A to point B but also changes the background image.
Say the initial position is 0,0 and the finis one is 0,100 ; the duration is 1 second, and i have 4 images for the background, then i want the background to change every 0/4 seconds and 25 px.
Until now I have the next code that animates the images but i still need to implement the movement and I don't know how to do just that.
Thanks in advance and here is what code I have until now:
UIImageView * animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50,50)];
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"test_1.png"], [UIImage imageNamed:#"test_2.png"], [UIImage imageNamed:#"test_3.png"],nil];
animTime =3.0;
[animatedImageView setAnimationImages:testArray] ;
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];
UPDATE:
I have implemented the answer of Mobile Project Lab into my code
// I have a pathArray that is in C style and is bidimensional, that stores the path in reverse
// the maps is a 2d tile map
// the dimensions of the tiles are 64x64 px
//thes size of the character is 128x128
for (int possitionInThePathArray = sizeOfPathArray - 1; possitionInThePathArray >= 0; possitionInThePathArray--) {
xWalkingDirection = pathArray[possitionInThePathArray-1][1] - pathArray[possitionInThePathArray][1];
yWalkingDirection = pathArray[possitionInThePathArray-1][0] - pathArray[possitionInThePathArray][0];
if (xWalkingDirection== 0 && yWalkingDirection == -1){
//walking animation to North for 1 tile
NSArray *testArray;
float animTime;
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"scientist_s0.png"],
[UIImage imageNamed:#"scientist_s1.png"],
[UIImage imageNamed:#"scientist_s2.png"],
[UIImage imageNamed:#"scientist_s3.png"],
[UIImage imageNamed:#"scientist_s4.png"],
[UIImage imageNamed:#"scientist_s5.png"],
[UIImage imageNamed:#"scientist_s6.png"],
[UIImage imageNamed:#"scientist_s7.png"],
[UIImage imageNamed:#"scientist_s8.png"],
[UIImage imageNamed:#"scientist_s9.png"], nil]; // 4th image added
animTime = 10.0; // time is changed to 10.0
[myCharacterFrame setAnimationImages:testArray];
myCharacterFrame.animationDuration = animTime;
myCharacterFrame.animationRepeatCount = 1;
[myCharacterFrame startAnimating];
[UIView animateWithDuration:animTime
animations:^{
myCharacterFrame.frame = CGRectOffset(myCharacterFrame.frame, 0.0f, -64.0f); // move 100 on x axis, 0 on y axis
}
completion:^(BOOL finished){
NSLog(#"animation done");
}];
yMyCharacterFrame = yMyCharacterFrame-64.0;
myCharacterFrame.frame = CGRectMake(xMyCharacterFrame, yMyCharacterFrame, 128, 128);
myCharacterFrame.image = [UIImage imageNamed:#"scientist_s0.png"];
}else if (xWalkingDirection== 1 && yWalkingDirection == 0){
//walking animation to Est for 1 tile
.....
//and so on for all the four directions of walking
The issue that I am facing now is that the animation are not triggered correctly, so that one animation takes places before the code moves on
NSArray *testArray;
float animTime;
UIImageView *animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
testArray = [[NSArray alloc] initWithObjects:[UIImage imageNamed:#"test_001.png"], [UIImage imageNamed:#"test_002.png"],[UIImage imageNamed:#"test_001.png"], [UIImage imageNamed:#"test_002.png"], nil]; // 4th image added
animTime = 1.0; // time is changed to 1.0
[animatedImageView setAnimationImages:testArray];
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];
[UIView animateWithDuration:animTime
animations:^{
animatedImageView.frame = CGRectOffset(animatedImageView.frame, 100.0f, 0.0f); // move 100 on x axis, 0 on y axis
}
completion:^(BOOL finished){
NSLog(#"animation done");
}];
How can i keep a UIVIew highlighted ( change alpha ) until another one is tapped? I have a uiscrollview in which i have loaded several uiview in order to achieve the thumbnail effect. I create them using this method :
_thumbnailScroll.delegate = self;
[_thumbnailScroll setBackgroundColor:[UIColor clearColor]];
[_thumbnailScroll setCanCancelContentTouches:NO];
_thumbnailScroll.indicatorStyle = UIScrollViewIndicatorStyleWhite;
_thumbnailScroll.clipsToBounds = NO;
_thumbnailScroll.scrollEnabled = YES;
_thumbnailScroll.pagingEnabled = YES;
NSUInteger nimages = 0;
NSInteger tot=0;
CGFloat cx = 0;
for (nimages = 0; nimages < 5 ; nimages++) {
// NSString *imageName = [NSString stringWithFormat:#"thumb%lu.png", (nimages + 1)];
UIImage *image = [UIImage imageWithContentsOfFile:[path stringByAppendingPathComponent:#"newPics/thumb/thumb1.png" ]];
if (tot==5) {
break;
}
if (5==nimages) {
nimages=0;
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.size.height = 150;
rect.size.width = 150;
rect.origin.x = cx;
rect.origin.y = 0;
imageView.frame = rect;
// NSString *propertyName = [NSString stringWithFormat:#"image%lu", (unsigned long)nimages];
//UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapGestureCapturedFor1:)];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onSingleTapGestureRecognized:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
singleTap.delegate = self;
// [imageView add]
[imageView addGestureRecognizer:singleTap];
//[singleTap1 release];
imageView.userInteractionEnabled = YES;
[_thumbnailScroll addSubview:imageView];
_thumbnailScroll.userInteractionEnabled = YES;
// [imageView release];
cx += imageView.frame.size.width+100;
tot++;
}
The above method initializes the image views inside the scroll view and adds a tap gesture to be captured in the following method :
- (void)onSingleTapGestureRecognized:(UITapGestureRecognizer *)singleTapGestureRecognizer
{
UIView *tappedView = [_thumbnailScroll hitTest:[singleTapGestureRecognizer locationInView: _thumbnailScroll] withEvent:nil];
// tappedView.alpha =1.0;
// NSLog(#"image view tag %ld" , (long)tappedView.tag);
// NSLog(#" Description %# " , tappedView.description );
// label.highlighted = YES;
tappedView.alpha = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
tappedView.alpha = 1.0;;
});
}
Now this method highlights the tapped uiview for almost 5 seconds, i am trying to keep it highlighted until i tap on another uiview. How can i achieve that?
Remove this code:
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 5.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
tappedView.alpha = 1.0;;
});
And replace with this:
for(UIView *view in _thumbnailScroll.subviews) {
view.alpha = 1.0;
}
This prevents the alpha in your tapped view from going back to 1 after 5 seconds and ensures all the other views have an alpha of zero. Or for a more performant approach, set a pointer to the last view clicked, and instead of looping through each of your ScrollView's subviews, simply set the alpha of the view you've referenced to 1.0. So instead, you'd add a property called lastTappedView and then replace the above code with:
_lastTappedView.alpha = 1.0;
_lastTappedView = tappedView;
singleTap.numberOfTouchesRequired = 1;
numberOfTouch is read-only.
I'am searching for a (very) simple way to crossfade images within animationDuration time. I tried using NSTimer and some other stuff I found here, but no solution satisfy or helps me.
I create this stuff in a method (without comments) ...
- (UIImageView *)playSequence{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is the part where the method is called ...
- (void)justPlaySelection
{
UIView *justPlaySelection = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
// some background music code ...
// add play sequence
[justPlaySelection addSubview:self.playSequence];
// add close button
// { ... }
[self presentSemiView:justPlaySelection];
}
- (UIImageView *)playSequence
{
if (_playSequence == nil)
{
NSArray *structureArray = self.contenManager.ImageViewControllerSize;
NSMutableArray *structuresToPlay = [[NSMutableArray alloc] init];
// walk thru current collection
for(NSInteger i = 0; i < [self.currentCollection count]; i++)
{
NSInteger index = [[self.currentCollection objectAtIndex:i] integerValue];
[structuresToPlay addObject:[UIImage imageNamed:[structureArray objectAtIndex:index]]];
}
_playSequence = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
}
_playSequence.animationImages = structuresToPlay;
_playSequence.animationDuration = 5 * structuresToPlay.count;
[_playSequence startAnimating];
return _playSequence;
}
Here is another way to switch between to UIImageViews, it wouldn't be hard to add in the fade in and out.
- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum
{
int index = indexNum.intValue;
BOOL completedSequece = index >= [self.frames count];
if (completedSequece) return;
UIImageView *imgIn;
UIImageView *imgOut;
if (index % 2 == 0) {
imgIn = self.animationImageViewOne;
imgOut = self.animationImageViewTwo;
}
else {
imgIn = self.animationImageViewTwo;
imgOut = self.animationImageViewOne;
}
imgIn.image = [self.frames objectAtIndex:index];
[self.view sendSubviewToBack:imgOut];
double speed = 0.1;
[self performSelector:#selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index + 1] afterDelay:speed];
}
I created a project that does exactly what you describe (an effect like UIImageView animation sequence, but with a cross-fade between images.)
The project is on github: https://github.com/DuncanMC/Animate-Img
You need to have 2 image views.
The trick I use is to stack them on top of each other, and simply animate the top image view from alpha 1 -> 0, then switch images in the top image view and animate it from alpha 0 -> 1.0, so the new image is revealed.
The project demos a morph transition using only 5 frames. Each frame is marked with a number so you can see the frame changes. It has a switch which lets you turn cross-fading on or off.
For a certain UIImageView animationImages, I wish to create 2 arrays - one per each direction.
I have png files I can load into one of the directions, and I wish to flip each image and add it to second direction array.
I tried to do something like this:
_movingLeftImages = [NSMutableArray array];
_movingRightImages = [NSMutableArray array];
int imagesCounter = 0;
while (imagesCounter <= 8)
{
NSString* imageName = [NSString stringWithFormat:#"movingImg-%i", imagesCounter];
UIImage* moveLeftImage = [UIImage imageNamed:imageName];
[_movingLeftImages addObject:moveLeftImage];
UIImage* moveRightImage = [UIImage imageWithCGImage:moveLeftImage.CGImage scale:moveLeftImage.scale orientation:UIImageOrientationUpMirrored];
[_movingRightImages addObject:moveRightImage];
imagesCounter++;
}
Upon the relevant event, I load the UIImageView animationImages with the relevant array; like this:
if ( /*should move LEFT event*/ )
{
movingImageView.animationImages = [NSArray arrayWithArray:_movingLeftImages];
}
if ( /*should move RIGHT event*/ )
{
movingImageView.animationImages = [NSArray arrayWithArray:_movingRightImages];
}
The images are not flipped. They remain as they where.
Any idea how to handle this?
use this code for animating images
UIImageView * animatedImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200,200)];
NSArray *imageNames = #[#"bird1.png", #"bird2.png"];
animTime =.0;
[animatedImageView setAnimationImages:imageNames] ;
animatedImageView.animationDuration = animTime;
animatedImageView.animationRepeatCount = 1;
[self.view addSubview: animatedImageView];
[animatedImageView startAnimating];