I have 9 images that I need to cross fade. I tried to do animation with animationImages method of imageview. But unfortunately, it does not support cross fading effect between images. Can anybody tell me how to achieve this?
I usually use Core Animation, specifically CABasicAnimation,
I used this recently, an image view with a couple of gesture recognizers for left and right swipe. Check out the fading animations I am using:
_someImageView = [[UIImageView alloc] initWithFrame:myFrame];
_someImageView.image = [myArrayOfImages objectAtIndex:0];
[self.view addSubview:_someImageView];
[_someImageView release];
_currentImageIndex = 0;
_someImageView.userInteractionEnabled = YES;
UISwipeGestureRecognizer *swipeLeftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(changeImage:)];
swipeLeftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[_someImageView addGestureRecognizer:swipeLeftGesture];
[swipeLeftGesture release];
UISwipeGestureRecognizer *swipeRightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(changeImage:)];
swipeRightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[_someImageView addGestureRecognizer:swipeRightGesture];
[swipeRightGesture release];
Then this is called every time I swipe, or if you prefer to do something time based, then have your timer call this, just make sure you increment a counter so that you can loop the images:
- (void)changeImage:(UISwipeGestureRecognizer *)swipe{
NSArray *images = [myArrayOfImages images];
NSInteger nextImageInteger = _currentImageIndex;
if(swipe.direction == UISwipeGestureRecognizerDirectionLeft)
nextImageInteger++;
else
nextImageInteger--;
if(nextImageInteger < 0)
nextImageInteger = images.count -1;
else if(nextImageInteger > images.count - 1)
nextImageInteger = 0;
_currentImageIndex = nextImageInteger;
UIImage *target = [images objectAtIndex:_currentImageIndex];
CABasicAnimation *crossFade = [CABasicAnimation animationWithKeyPath:#"contents"];
crossFade.duration = 0.5;
crossFade.fromValue = _someImageView.image;
crossFade.toValue = target;
[_someImageView.layer addAnimation:crossFade forKey:#"animateContents"];
_someImageView.image = target;
}
Just create two image views and lay them on top of one another. When you want to crossfade to the next image, just set the bottom image view's image to the image you want to fade to, and animate the alpha of the top image view to 0. Rinse and repeat.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIImage *img=[UIImage imageNamed:#"images.jpeg"];
imgview=[[UIImageView alloc]init];
imgview.frame=CGRectMake(30,90, img.size.width, img.size.height);
[self.view addSubview:imgview];
[self animateImages];
}
- (void)animateImages
{
static int count = 0;
NSArray *animationImages = #[[UIImage imageNamed:#"images.jpeg"], [UIImage imageNamed:#"images (1).jpeg"]];
UIImage *image = [animationImages objectAtIndex:(count % [animationImages count])];
[UIView transitionWithView:imgview
duration:2.0f // animation duration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
imgview.image = image;
} completion:^(BOOL finished) {
[self animateImages];
count++;
}];
}
Related
I have used third party lib to show array of images in a slider . The images in an array comes from server, now i want to show the image in a bigger image view on a tap gesture. When anyone of the image user tap it should be shown in big imageview. I have tried some code but it is not working. My code is,
int i=0;
tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(expandImage:)];
tap.numberOfTapsRequired = 1;
[_ImageView setUserInteractionEnabled:YES];
[_ImageView addGestureRecognizer:tap];
tap = [_imagesData objectAtIndex:i];
NSLog(#"TTT %#",tap);
[self.view addSubview:_fullImage];
The method is ,
-(void)expandImage:(UITapGestureRecognizer*)recogniser
{
[self.view addSubview:_fullImage];
UIButton *closeButton = [[UIButton alloc]init];
[closeButton setTitle:#"Close" forState:UIControlStateNormal];
// [closeButton addTarget:self action:#selector(Closetab) forControlEvents:UIControlEventTouchUpInside];
[_fullImage addSubview:closeButton];
UIImageView *photoView = [[UIImageView alloc]init];
[photoView setBackgroundColor:[UIColor blueColor]];
[_fullImage addSubview:photoView];
// photoView.accessibilityIdentifier = #"nature2.png";
[_fullImage addSubview:_fullImage];
}
here I attached the sample project , customize yourself
step1
create the one full screen view for preview the image (use one UIView, one close btn, one imageview)
#interface ViewController () <UIScrollViewDelegate, TAPageControlDelegate>
{
NSTimer *timer;
NSInteger index;
//
IBOutlet UIImageView *imgfull;
IBOutlet UIView *fullimagevie;
IBOutlet UIButton *btnClose;
}
step2
add the gesture for tap the image event and set the frame of your duplicate view as bottom of viewcontroller
- (void)viewDidLoad
{
[super viewDidLoad];
[self setviewframe:self.view.frame.size.height + 10];
self.imagesData = #[#"image1.jpg", #"image2.jpg", #"image3.jpg"];
for(int i=0; i<self.imagesData.count;i++){
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame) * i, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.scrollView.frame))];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.image = [UIImage imageNamed:[self.imagesData objectAtIndex:i]];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(expandImage:)];
tap.numberOfTapsRequired = 1;
tap.view.tag = i;
[imageView setUserInteractionEnabled:YES];
[imageView addGestureRecognizer:tap];
[self.scrollView addSubview:imageView];
}
step3
handle the image tap for preview the image
-(void)expandImage:(UITapGestureRecognizer*)recogniser
{
imgfull.image = [UIImage imageNamed:[self.imagesData objectAtIndex:recogniser.view.tag]];
[UIView transitionWithView:fullimagevie
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self setviewframe:0];
}
completion:NULL];
}
step4
dismiss the bigger image view on tap the close button
- (IBAction)btnClose:(UIButton *)sender {
[UIView transitionWithView:fullimagevie
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self setviewframe:self.view.frame.size.height + 10];
}
completion:NULL];
}
step5
create the common method for set the frame for your bigger imageview
-(void)setviewframe:(CGFloat)coordinate{
CGRect modifyframe = fullimagevie.frame;
modifyframe.origin.y = coordinate;
fullimagevie.frame = modifyframe;
}
Using UIControlpage in my application. load the image and display in page control successfully. but i want to display the images animation like right to left move. Using timer call page control and increase the array count.
//// using NSTimer to call function to show the animation.
[NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(loadNextController)
userInfo:nil
repeats:YES];
ScrollViewPage = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, frameX, frameY)];
ScrollViewPage.pagingEnabled = YES;
ScrollViewPage.backgroundColor=[UIColor redColor];
ScrollViewPage.delegate = self;
ScrollViewPage.backgroundColor = [UIColor clearColor];
ScrollViewPage.contentSize = CGSizeMake(frameX, frameY);
ScrollViewPage.showsHorizontalScrollIndicator = NO;
ScrollViewPage.pagingEnabled = YES;
pageControl = [[UIPageControl alloc] init];
pageControl.frame = CGRectMake(100,self.view.frame.size.height-100,self.view.frame.size.width-200,100);
pageControl.numberOfPages = [_pageImages count];
pageControl.currentPage = 0;
[self.view addSubview: ScrollViewPage];
for(int i = 0; i < [_pageImages count]; i++)
{
NSURL *url = [NSURL URLWithString:[_pageImages objectAtIndex:i]];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *tmpImage = [UIImage imageWithData:data];
_backgroundImageView = [[UIImageView alloc] initWithImage:tmpImage];
_backgroundImageView.frame = CGRectMake(frameX * i, 0.0, frameX, frameY);
[ScrollViewPage addSubview:_backgroundImageView];
}
ScrollViewPage.contentSize = CGSizeMake(frameX*[_pageImages count], frameY);
pageControl.backgroundColor=[UIColor orangeColor];
[self.view addSubview:pageControl];
[pageControl addTarget:self action:#selector(pageTurn:) forControlEvents:UIControlEventValueChanged];
///// Here call the timer function
- (void)loadNextController
{
pageControl.currentPage = (pageControl.currentPage+1)%self.pageImages.count;
ScrollViewPage.contentOffset = CGPointMake(pageControl.currentPage * self.view.bounds.size.width, 0);
}
Here i need to show left to right move in uipagecontrol. help me..
In general you should always write what is your current result, what is the expected result and what have you tried.
I can only guess the issue you are facing is there are no animations.
The scroll view has a method setContentOffset:animated which you can use to animate the transition. Another approach is to use UIView animateWithDuration and sett the offset in the method block.
Try any or both of these...
[ScrollViewPage setContentOffset:CGPointMake(pageControl.currentPage * self.view.bounds.size.width, 0) animated:YES];
Or
[UIView animateWithDuration:0.2 animations:^{
ScrollViewPage.contentOffset = CGPointMake(pageControl.currentPage * self.view.bounds.size.width, 0);
}];
EDIT: Loop images.
To loop images you really only need 2 images on the scroll view at the time. I will show you the concept with 3 and you can try and play around with it.
NSArray *allImages;
NSInteger currentIndex = 0;
UIScrollView *scrollView;
UIImageView *imageViews[3];
- (void)begin {
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width*3.0, scrollView.frame.size.height); // always have 3 images at the time
scrollView.contentOffset = CGPointMake(scrollView.frame.size.width, 0.0); // put to center
for(int i=0; i<3; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(scrollView.frame.size.width*i, 0.0, scrollView.frame.size.width, scrollView.frame.size.height)];
[scrollView addSubview:imageView];
imageView[i] = imageView;
}
[self layoutForIndex:currentIndex];
}
- (void)nextImage {
currentIndex++;
[self layoutForIndex:currentIndex];
scrollView.contentOffset = CGPointZero;
[scrollView setContentOffset:CGPointMake(scrollView.frame.size.width, 0.0) animated:YES]
}
- (void)layoutForIndex:(NSInteger)index {
if(allImages.count > 0) { // we need at least one image to do something
for(int i=0; i<3; i++) {
// do the circling
NSInteger imageIndex = index-1+i;
while(imageIndex < 0) imageIndex+=allImages.count;
while(imageIndex >= allImages.count) imageIndex-=allImages.count;
imageViews[i].image = imageViews[imageIndex];
}
}
}
But in general for what you are doing you do not even need a scroll view. On next you can simply add another image view next to the current one and then use the UIView animation to reposition both of the image views.
I have code for an animating bear but i need to check collision between its animation and a regular UIImageView. Any suggestions? I looked at other answers but my code isn't the same. Here's what I have so far. Or should i use SpriteKit. I'd rather not though.
- (void)viewDidLoad {
NSArray *imageNames = #[#"bear1.gif", #"bear2.gif", #"bear3.gif", #"bear4.gif",
#"bear5.gif", #"bear6.gif"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
// Normal Animation
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(768, 800, 169, 217)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 0.5;
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
[UIView animateWithDuration:7 delay:1 options:UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:INFINITY];
animationImageView.frame = CGRectMake(-10, 800, 169, 217);
} completion:^(BOOL finished) {
animationImageView.hidden = YES;
}];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
In your animations block you can check to see when the frame of your animating view crosses or is about to cross the frame of your UIImageView. When this condition is met, you stop the animation
I am currently trying to build an image viewer that moves to the next photo every 30 seconds, which also allows to swipe left / right to the next/previous photo manually.
So far I have built two separate apps, one with the swiping functionality and the second with the timer. I have tried many tutorials on the web and am looking for someone to point me in the right direction.
This code switches images every thirty seconds
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIImageView *animatedImageView = [[UIImageView alloc]
initWithFrame:CGRectMake(0, 55, 400, 550)];
[self.view addSubview:animatedImageView];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil];
animatedImageView.animationDuration = 30.0 * [animatedImageView.animationImages count];
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
}
This second piece of code has the swiping functionality, I am looking to combine the two
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *image1 = [UIImage imageNamed:#"workExample.jpg"];
UIImage *image2 = [UIImage imageNamed:#"IMG_0054.JPG"];
UIImage *image3 = [UIImage imageNamed:#"IMG_0052.JPG"];
imageArray = [NSArray arrayWithObjects:image1, image2, image3, nil];
for (int i = 0; i < [imageArray count]; i++) {
//This is to create a imageview for every single pagecontrol
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = [imageArray objectAtIndex:i];
[self.scrollView addSubview:imageView];
}
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [imageArray count], scrollView.frame.size.height);
}
I am not using a scrollview and implementing in a different way. I hope it suits your needs
In .h
#interface ViewController : UIViewController
{
NSMutableArray *imagesToAnimate;
UIImageView *animatedImageView;
}
#property (strong, nonatomic) IBOutlet UIView *imageGalleryView;
Im viewDidLoad
animatedImageView = [[UIImageView alloc] initWithFrame:self.imageGalleryView.bounds];
imagesToAnimate = [NSMutableArray arrayWithArray:[NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil]];
[self.imageGalleryView addSubview:animatedImageView];
//Start a timer
[NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:#selector(changeImge) userInfo:nil repeats:YES];
animatedImageView.image = imagesToAnimate[0];
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(gallerySwiped)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imageGalleryView addGestureRecognizer:swipeGesture];
//Give the gallery a border
self.imageGalleryView.layer.borderColor = [UIColor grayColor].CGColor;
self.imageGalleryView.layer.borderWidth = 2.0f;
self.imageGalleryView.layer.cornerRadius = 15.0f;
Now function to update the image as as per scheduled time
-(void)changeImge
{
int index = [imagesToAnimate indexOfObject:animatedImageView.image];
index++;
//this is for the left to right animation ;
CATransition *transition = [CATransition new];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
if (index > imagesToAnimate.count-1) {
animatedImageView.image = imagesToAnimate [0];
}else {
animatedImageView.image = imagesToAnimate[index];
}
[animatedImageView.layer addAnimation:transition forKey:#"transition"];
}
this would handle the swipe
-(void)gallerySwiped
{
[self changeImge];
}
To stop the timer store it in a global variable and call invalidate.I hope this helps.
I am working on with a simple animation that I have 10 button and "on click" of one button ( for example 5) all button should start animate one by on but they are animating the same time, please let me know what can be done or ..... Thanks
NSMutableArray* imagesArray = [[NSMutableArray alloc] init];
for (int images = 0; images < 15; images++) {
UIImage* buttonImage = [UIImage imageNamed:[NSString stringWithFormat:#"aaqqq00%02d.png", images]];
[imagesArray addObject:buttonImage];
}
NSArray* reversedAnim = [[imagesArray reverseObjectEnumerator] allObjects];
int buttonTag = button.tag;
for (int images = 1; images <= 10; images++) {
UIButton *animButton = (UIButton *)[self.view viewWithTag:images];
if (images <= buttonTag) {
animButton.imageView.animationImages = imagesArray;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0014.png"] forState:UIControlStateNormal];
animButton.adjustsImageWhenHighlighted = NO;
animButton.imageView.animationDuration = 1; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
} else {
if (currentButtonTag_ >= images) {
animButton.imageView.animationImages = reversedAnim;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0000.png"] forState:UIControlStateNormal];
animButton.adjustsImageWhenHighlighted = NO;
animButton.imageView.animationDuration = 0.2; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
}
}
}
As you iterate through your loop, have a variable that holds the desired delay, and add to it at the end of each loop. We'll call this delay.
Now, instead of calling:
[animButton.imageView startAnimating];
Do this:
[animButton.imageView performSelector:#selector(startAnimating) withObject:nil afterDelay:delay];
And each button will start animating after the accumulated delay.
You need to give some delay time and duration time.
[UIView animateWithDuration:0.6
delay:2.0
options: UIViewAnimationCurveEaseOut
animations:^{S1Button.frame = CGRectMake(20, 10, 50, 10);S1buttonA.alpha = 0;}
completion:nil];
Set this for every animation.