scrolling images in ios automatically - ios

i have multiple images in array and a scrollView all the images should scroll automatically and when i clicked the image it should navigate to other view and display its details. after completing images scrolling from 0 to end of the array it should Again load 1st image i.e 0. in Animating i have lot of problem please help me....
iam using this code
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
- (void) onTimer {
// Updates the variable h, adding 100 (put your own value here!)
h += 100;
//This makes the scrollView scroll to the desired position
yourScrollView.contentOffset = CGPointMake(0, h);
}

try iCarousel library for scrolling the images, use autoscrolling example for the reference, set wrap property to yes if you want to repeat the content in the loop. add image array to carousel and implement carousel datasource and delegate methods to scroll the images. you can change different types like linear, rotary or overflow etc.

you can create image outlet after that
NSMutableArray *imgArray = [[NSMutableArray alloc]init];
for (int i =0; i<imgUrlArray.count; i++) {
NSString *imgStr = [serviceImgArray objectAtIndex:i];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imgStr]];
[imgArray addObject:[UIImage imageWithData:imageData]];
}
yourimageView.animationImages = imgArray;
yourimageView.animationDuration = 10;
[yourimageView startAnimating];
that's it.

Related

Changing the properties of a UIImageView

I have picked up programming as a hobby, so please bear with any 'old school' or completely wrong practices!
I am trying to move three images across the view using a timer. They then need to be dodged by another UIImageView. The obstacles are in an array:
objArray = [NSMutableArray arrayWithObjects:[UIImage imageNamed:#"img-1.png"],
[UIImage imageNamed:#"img-2.png"],
[UIImage imageNamed:#"img-3.png"], nil];
I then have a for loop to create these views, and it's here that I think the problems start.
count = [objArray count];
for(int i=0; i < count; i++)
{
NSLog (#"Element %i = %#", i, [objArray objectAtIndex: i]);
randX = arc4random_uniform(450);
randX = randx + 50;
randY = arc4random_uniform(236);
randY = randy + 45;
imgObj = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[objArray objectAtIndex:i]]];
imgObj.center = CGPointMake(randX, randY);
[self.view addSubview:imgObj];
[self startAnimation];
All three images display ok. The problem is getting these to move.
I understand the need for the timer, which is initiated in the startAnimation method. I have tried setting a tag in the for loop. However this always results in the last object "img-3.png", which then moves ok.
My question is: how do I differentiate the three views I create in the loop so I can call them elsewhere?
Assigning tags to you UIImageViews should work:
imgObj.tag = i+1; //skipping 0 here since other subviews may have this tag
Then you should be able to access the views via
[self.view viewWithTag:tag];
Or you could create another NSMutableArray and store the UIImageViews in it.

I want to pause the image from an array

I am creating an animation using the below code:
NSMutableArray *dashBoy = [NSMutableArray array];
for (int i = 1; i<= 20; i++) {
butterfly = [NSString stringWithFormat:#"5c_%d.jpg", i];
if ((image = [UIImage imageNamed:butterfly]))
[dashBoy addObject:image];
}
[stgImageView setAnimationImages:dashBoy];
[stgImageView setAnimationDuration:7.0f];
[stgImageView setAnimationRepeatCount:-1];
[stgImageView startAnimating];
My requirement is if dashBoy is 5c_10.jpg, then pause the image for about 5 sec and then resume animation and another if dashBoy is 5c_20.jpg, then pause the image again for about 5 sec and resume again. Is it possible?
You can't use variable speeds for UIImageView animations like this.
There are a couple of ways around it though.
1. Do it all yourself.
For this you would use something like an NSTimer and have it fire a method repeatedly to change the images for you. Using this you can time each image individually (you could even create a data object that holds an image and the length of time to show it and then create and array of these.
2. Manipulate the current method.
If you have 20 images and you want to show them all in 7 seconds then thats... 0.35 seconds per image. So a 5 second pause is about 14 images worth.
So instead of adding each image once you can add 1-9 once and then add 10 fourteen times. 11-19 once and then 20 fourteen times.
This will then swap like it is doing but when it reaches 10 it will swap it for another copy of the same image so it will look like it's pausing.
You will then have to increase the duration... to 17 seconds to get a similar duration for each image.
Which I'd do?
Although it sounds like a hack (because it is) I think I'd give the second method a go first. It's a lot easier to get working so if it does fail you haven't spent a long time setting it up.
The first method is a lot more work to set up but will allow for greater control of the animation.
Quick and dirty example for method 1
Create an object something like...
MyTimedImage
------------
UIImage *image
CGFloat duration
So for instance...
// probably want this as a property
NSMutableArray *timedImages = [NSMutableArray array];
MyTimedImage *timedImage = [MyTimedImage new];
timedImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"5c_%d.jpg", i]];
timedImage.duration = 0.4;
[timedImages addObject:timedImage];
Then you want a way of displaying them...
//set up properties something like this...
#property (nonatomic, assign) NSInteger currentIndex;
#property (nonatomic, assign) BOOL paused;
#property (nonatomic, assign) NSTimer *imageTimer;
- (void)displayNextImage
{
if (self.paused) {
return;
}
NSInteger nextIndex = self.currentIndex + 1;
if (nextIndex == [self.timedImages count]) {
nextIndex = 0;
}
MyTimedImage *nextImage = self.timedImages[nextIndex];
self.currentIndex = nextIndex;
self.imageView.image = nextImage.image;
self.imageTimer = [NSTimer scheduledTimerWithInterval:nextImage.duration target:self selector:#selector(displayNextImage) userInfo:nil repeats:NO];
}
Using the properties that you've exposed you can pause the image view on the current image from a button press (for example).
To start the process just run [self displayNextImage]; you can start anywhere in the loop of images too.
using UIImageView animation, this is not possible, you may need to create your own animation logic like loading all UIImages in array and through timer, switch to next animation frame and when you desire to pause, invalidate the timer.

How can I take the current integer value out of my array loop when I press my button on Xcode?

I need to take the current value of mtype and pass it forward to Mselect so that the image pushed forward is the same as the one rotating in the animation.
here is the code sample
- (void)viewDidLoad
{
//Array to hold Images
NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:Mush_Count];
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
//make button
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
Mselect = mtype;
}
}
-(IBAction)Selection:(id)sender{
[self Placement];
}
-(void)Placement{
if (Place1Occ == NO) {
[self Place1];
}
}
-(void)Place1{
if (Place1Occ == NO) {
Place1.image =[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", Mselect]];
Place1Occ = YES;
}
}
The animation loops just fine and the selection of the images works but it's not selecting the image the is currently on the screen it selects the last image on the Array.
Any suggestions?
for (mtype = 1; mtype < Mush_Count; mtype++)
{
[imageArray addObject:[UIImage imageNamed:[NSString stringWithFormat:#"Mush%i.png", mtype]]];
}
That loop is enough to build the array of images - you don't need to set the imageView's animation images until this loop completes and the array is populated.
As it stands, you reset the animation images each loop and set Mselect to type each iteration: this is why you always get the last image index stored in Mselect
This code should be after the for loop:
SelectBt.imageView.animationImages = [NSArray arrayWithArray:imageArray];
SelectBt.imageView.animationDuration = 5;
[SelectBt.imageView startAnimating];
As far as I know, you can't get the current frame of the animation directly - you have to create a timer when you start the animation and have this count the number of frames (by increasing your Mselect value. Then use that to load the current image
Is SelectBT a subclass of UIButton? if so is it the (id)sender coming from your IBAction?
If so then you can just grab the image directly from the SelectBT instance by calling sender.imageView.image
As an aside, objective-C convention is to capitalize ClassNames, but start instances with lowerCase like this ClassName *instanceOfClassName and you're likely to take flack for it around here if you don't adhere to that convention
Update
Could you bump your imageArray into a class variable or a property? It already contains all the fully loaded UIImages, which you can get back out by calling [imageArray objectAtIndex:i]
Then you just have to keep track of which numeric index is facing your user, or which index they tapped and pull the corresponding image.
Feel free to post your whole class if you'd like us to explain more.

Scroll view is not smooth

I'm working in a project (iOS7 & ARC) in which, I want to display N number of images in the scroll view.These Images already stored into sandbox directory. My App has only landscape orientation I'm facing a problem that ScrollView is not smooth, it stuck after 2-3 times scroll
This is how I configure ScrollView
[self.containerScroll setAutoresizesSubviews:NO];
self.containerScroll.pagingEnabled = YES;
self.containerScroll.showsHorizontalScrollIndicator = NO;
self.containerScroll.showsVerticalScrollIndicator = NO;
self.containerScroll.scrollsToTop = NO;
self.containerScroll.maximumZoomScale = 5.0;
self.containerScroll.minimumZoomScale = 1.0;
self.containerScroll.delegate = self;
I'm maintaining only three Images in the scrollView at a time.
I'm loading Images in ScrollView in below method
-(void) loadScrollViewWithPage:(int) page{
if (page >= self.numberOfSlides)
return;
float image_width;
float image_height;
if(self.isFromListView){
if(IS_IPHONE5){
image_width = 568.0f;
image_height = 320.0f;
} else{
// iPhone retina-3.5 inch
image_width = 480.0f;
image_height = 320.0f;
}
}
else{
image_width = IMAGE_WIDTH;
image_height = IMAGE_HEIGHT;
}
CGFloat xPos = page * image_width;
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(xPos, 0.0f, image_width, image_height)];
imgView.tag = page;
NSString *imgPath = [self.storageDirPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d%#", page, Image_Extension_JPG]];
NSFileManager *fileManager = [NSFileManager defaultManager];
__block UIImage *img = nil;
if(![fileManager fileExistsAtPath:imgPath]){
[imgView setContentMode:UIViewContentModeCenter];
img = [UIImage imageNamed:#"icon-loader.png"];
[imgView setImage:img];
}
else{
[imgView setContentMode:UIViewContentModeScaleAspectFit];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
img = [[UIImage alloc] initWithCGImage:[[UIImage imageWithData:[NSData dataWithContentsOfFile:imgPath]] CGImage] scale:1.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
[imgView setImage:img];
});
});
}
[self.containerScroll addSubview:imgView];
img = nil;
fileManager = nil;
imgView = nil;
}
and this how my ScrollView Delegate methods goes...
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
self.containerScroll.scrollEnabled = YES;
float page = self.containerScroll.contentOffset.x/self.view.frame.size.width;
showingSlide = (UInt16) roundf(page);
if(scrollView == self.containerScroll){
// switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = CGRectGetWidth(self.containerScroll.frame);
NSUInteger pageNo = floor((self.containerScroll.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:pageNo - 1];
[self loadScrollViewWithPage:pageNo];
[self loadScrollViewWithPage:pageNo + 1];
// a possible optimization would be to unload the views+controllers which are no longer visible
if(scrollView == self.containerScroll)
{
[self.previewTableView reloadData];
[self.previewTableView setContentOffset:CGPointMake(0, (page*220)+64) animated:NO];
[self.previewTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:page inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
[self updateSlideNumber];
[self flashSlideNumber];
}
//unload unnecessary imageviews from scroll view
for (UIView* view in self.containerScroll.subviews) {
if ([view isKindOfClass:[UIImageView class]] && view.tag != page && view.tag != page-1 && view.tag != page+1) {
[view removeFromSuperview];
}
}
}
}
Now the problem is smoothness of scrollView. When I start scrolling it scrolls fine but after 2 or 3 (or after any random number) pages scroll, it stuck and after trying 2-3 times only it moves again and I have to swipe hard to scroll. Thanks in advance.
I think it's a problem of memory somewhere Try #autorelease pool in your code.
using scrollview is not a good approach for showing images, I will recommend you to either use tableview or collevtionview for the same.
Your app's memory will keep on increasing with every scroll because scollview doesn't reuse the memory, on the other hand tableview and collectionview reuses the memory.
As the most effective way to become better, scroll really slowly (one at a time) while you monitor the memory usage in your App. You'll be able to watch it go up as each new image is added to the view, especially if you haven't done any optimisation on the images.
The other thing is that while your code does look like is deallocc-ing the images, you still need to remember that it still has to try to reload the images as you scroll. You're creating your images on the main thread so you're never going to get the smoothness of a UITableView. While I realise that you're creating your image views on async threads, the act of adding and scrolling them is still being taken care of by the mainthread.
I would suggest a UITableView to solve your problem, or a UICollectionView. If you're set on using the scrollview, I would suggest using a crusher of some type to get the image size to as small as possible, while still keeping quality decent.
If you need help on the TableView implementation you should find plenty of information around SO. Probably a good option if you still want it to look like a scroll view is just to make all seperators, headers etc to nil, and then just use lazy loading for the images.
You make two the mistake. At first: never use imageNamed for non graphics content (example, use imageNamed for button background). And second: you try load a big images in real time. So you scroll view have lags therefore. If you load all images before you show the scroll view the amination end lagging. But you can get memory warnings. So, you need optimise it. P.S. Sorry for my english

How can I do a infinite scroller?

I have a scrollview which automatically pass an image to another. It has 7 images, I want to that when you get to the seventh image pass me a first in the same way as the rest of transitions
and not moving quickly to the first position.
It is what is commonly called infinite scroll. Any help is appreciated.
- (void)viewDidLoad
{
for (int i = 1; i < 8 ; i++) {
UIImageView *imagen = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"C%d.png",i]]];
imagen.frame = CGRectMake((i-1)*580,35, 580, 300);
[_scroller addSubview:imagen];
_scroller.indicatorStyle = UIScrollViewIndicatorStyleWhite;
}
_scroller.delegate = self;
_scroller.contentSize = CGSizeMake(580*7, 300);
_scroller.pagingEnabled = YES;
if (scrollingTimer == nil)
{
scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:6
target:self selector:#selector(scrollPages) userInfo:nil repeats:YES];
}
}
-(void)scrollToPage:(NSInteger)aPage{
float myPageWidth = [_scroller frame].size.width;
[_scroller setContentOffset:CGPointMake (aPage * myPageWidth, 0) animated:YES];
}
-(void)scrollPages{
[self scrollToPage:currentPage%7];
currentPage++;
}
One way to implement infinite scolling in a paging UIScrollView is to put a duplicate of the first page at the end of the scroll view (and vice versa, if you want infinite scrolling in both directions).
This article uses a UICollectionView instead, but the concept is the same for a paging UIScrollView. When the user scrolls to the duplicate of the first page at the end of the scroll view, set the content offset back to the actual first page (without animation, so the user doesn't know it's happened).
Here's some other resources I found useful:
Creating Circular and Infinite UIScrollViews
Apple has a sample project demonstrating infinite scrolling called StreetScroller
This answer to a similar question about infinite scrolling on SO

Resources