I would like to display an image (width: 320 pixels, height: 1250 pixels) in an image view.
When I compile the application I get no scrolling at all. The view stays fixed.
What I did:
Added an UIScrollView via Interface Builder to my view.
Added an UIImageView via Interface Builder to my view.
Verified that UIImageView is below UIScrollView in Interface Builder.
Set the size of the UIScrollView with ViewDidLoad.
How do I do this?
Code:
- (void)viewDidLoad
{
[super viewDidLoad];
scrollView.contentSize = CGSizeMake(320, 1250);
}
Screenshots:
ImageView:
ScrollView:
I just have done the same task..
Try this one.....
scrollView.delegate = self;
scrollView.scrollEnabled = YES;
int scrollWidth = 120;
scrollView.contentSize = CGSizeMake(scrollWidth,80);
int xOffset = 0;
imageView.image = [UIImage imageNamed:[imagesName objectAtIndex:0]];
for(int index=0; index < [imagesName count]; index++)
{
UIImageView *img = [[UIImageView alloc] init];
img.bounds = CGRectMake(10, 10, 50, 50);
img.frame = CGRectMake(5+xOffset, 0, 50, 50);
NSLog(#"image: %#",[imagesName objectAtIndex:index]);
img.image = [UIImage imageNamed:[imagesName objectAtIndex:index]];
[images insertObject:img atIndex:index];
scrollView.contentSize = CGSizeMake(scrollWidth+xOffset,110);
[scrollView addSubview:[images objectAtIndex:index]];
xOffset += 70;
}
Also set this one....
imagesName = [[NSArray alloc]initWithObjects:#"image1.jpg",#"image2.jpg",#"image3.jpg",#"image4.jpg",#"image5.jpg",#"image6.png",#"image7.png",#"image9.png",nil];
images = [[NSMutableArray alloc]init];
So for me the problem was that setting the content size didn't work in viewDidLoad(). I tried everything and I didn't understand why it wouldn't want to work, and then I tried the same stuff in viewDidAppear() and it magically worked...
From you last screenshot and from your comments it looks like your scrollView is way to big.
The scrollview must be visible on screen completely. For example a full screen UIScrollView on iPhone would have a size of 320 x 460.
If the scrollview is the same size as its content you can't scroll.
The greenish rectangle shows the size of your scrollview, the pinkish the size of your content (your image):
Xcode 11+, Swift 5
You can find the complete solution here.
I came across this same issue on iOS6 and the solution was to programmatically adjust the ContentSize.
So I will just quote from Raja (above) to show this:
CGSize scrollViewContentSize = CGSizeMake(320, 400);
[self.scrollView setContentSize:scrollViewContentSize];
NOTE: I was not having this issue on iOS5.. seems like iOS6 decided to do alot of prank just like the rotation/orientation saga
Since Xcode 5 it does not work like before. Also scrolling to the end of a scrollable text field makes problems. There are also differences between doing it on iPhone or iPad. On iPhone it worked without delayed timer.
This worked for me:
- (void)viewDidLoad
{
[super viewDidLoad];
NSTimer *timerforScrollView;
timerforScrollView =[NSTimer scheduledTimerWithTimeInterval:0.1
target:self selector:#selector(forScrollView)userInfo:nil repeats:NO];
}
- (void) forScrollView {
[scrollviewPad setScrollEnabled:YES];
[scrollviewPad setContentSize:CGSizeMake(768, 1015)]; // must be greater then the size in Storyboard
}
I found I had a similar problem but none of the above code worked. The issue was due to autolayout. I found that if I turned off autolayout by going to the storyboard clicking on Utilities -> File Inspector and unchecked Use Autolayout the scrolling did work (I also set scroll.contentSize = ...).
Sometimes autoLayout checkbox is ticked in the xib. That also creates this issue in xcode 5. Which makes the UIScrollView scrolling off.
Don't forget to add the category protocol to the interface, like this
#interface MyViewController : <UIScrollViewDelegate>
If you don't, you will not be able to set the scroll view delegate to self
(i.e. [MyScrollView setDelegate:self];)
If you do this, it should work.
My code is:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[contentScrollView setDelegate:self];
[contentScrollView setScrollEnabled:YES];
contentScrollView.contentSize = CGSizeMake(310, 500);
contentScrollView.frame = CGRectMake(5, 188, 310, 193);
}
Did you assign the scroll's view delegate? Always remember these:
[self.scrollView setDelegate:self];
[self.scrollView setScrollEnabled:YES];
The image view has to be a subview (so inside AND below) of the scrollview. From your description it seems they are paralell
You forgot one line. Add this to your view load function:
[scrollView setScrollEnabled:YES];
You could try disabling AutoLayout. In XCode 5 I tested all the above answers and I could only scroll it by disabling autolayout and activating all autosizing masks under the Size Inspector. The following code was used too:
self.scrollView.contentSize = CGSizeMake(320, 900);
self.scrollView.delegate = self;
self.scrollView.scrollEnabled = YES;
self.scrollView.frame = self.view.frame;
CGRect scrollViewFrame = CGRectMake(0, 0, 320, 400);
self.scrollView = [[UIScrollView alloc] initWithFrame:scrollViewFrame];
[self.view addSubview:self.scrollView];
CGSize scrollViewContentSize = CGSizeMake(320, 400);
[self.scrollView setContentSize:scrollViewContentSize];
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSUInteger nimages = 0;
CGFloat cx = 0;
for (; ; nimages++) {
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", (nimages + 1)];
UIImage *image = [UIImage imageNamed:imageName];
if (image == nil) {
break;
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.size.height = image.size.height;
rect.size.width = image.size.width;
rect.origin.x = ((scrollView.frame.size.width - image.size.width) / 2) + cx;
rect.origin.y = ((scrollView.frame.size.height - image.size.height) / 2);
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += scrollView.frame.size.width;
}
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
Assuming that scrollView is a subview of view and fills it entirely you can use the following in viewDidLoad:
[scrollView setContentSize: CGSizeMake(self.view.frame.size.width, self.view.frame.size.height)];
I had a UIScrollView that was not scrolling and this allowed it to scroll.
Just add code
scrollView.contentSize = CGSizeMake(WIDTH,HEIGHT);
to method -(void)viewDidLayoutSubviews.
For more information checkout Stanford CS193p Lecture No 8 to understand View Controller Life cycle.
I had the same issue and was looking for the answer in this thread. I tried all the stuff, but nothing works. Then I found this:
.
You just need to deselect "Use Auto Layout" in File Inspector of your ViewController. Ta-Da, it works immediately for me. Enjoy.
- (void)viewDidLoad
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
int numberOfImages = 32;
CGFloat currentX = 0.0f;
for (int i=1; i <= numberOfImages; i++) {
// create image
NSString *imageName = [NSString stringWithFormat:#"page-%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
imageView = [[UIImageView alloc] initWithImage:image];
// put image on correct position
CGRect rect = imageView.frame;
rect.origin.x = currentX;
imageView.frame = rect;
// update currentX
currentX +=454; //mageView.frame.size.width;
[scrollView addSubview:imageView];
[imageView release];
}
[scrollView addGestureRecognizer:tapGesture];
scrollView.contentSize = CGSizeMake(currentX, 800);
scrollView.pagingEnabled=YES;
scrollView.userInteractionEnabled = YES;
scrollView.maximumZoomScale = 15;
scrollView.minimumZoomScale = 0.5;
scrollView.bounces = NO;
scrollView.bouncesZoom = NO;
scrollView.delegate = self;
scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self.view addSubview:scrollView];
[scrollView release];
[super viewDidLoad];
}
}
in above code when i apply zoom or tap event with a single image then it work for that. But when same event apply for array of image then not working. why is it happened?
Its quiet complex to implement zoom in this kind of image flow. Anyway i wil suggest you one idea,
Add the gesture to each imageView. In the method, add a new scrollview, with the respective imageView.. then implement zoom.
EDIT:
In the tapgesture method,
1.Find out the which imageView is visible at that time.
2.Then create a new scrollview,with that single imageview.
3.Implement zoom functionality in that new scrollview.
4.During zoom out,If the new scrollview size is equal to the actual value,remove the new scrollview fro the super view so that the array of images is visible.
Simplest way is create a big wrapper view first, and insert it into ScrollView.
And then add all your imageViews to the wrapper view.
I am using a scrollview to display various items in a horizontal fashion.
How can I "reuse the cells" to conserve memory:
Edit: Apologies for not being clear. I plan to place a few labels and and another ImageView inside each ImageView so I am keen to reuse this each time instead of instantiating new items each time. e.g. change the image's and update the labels instead of re-create it.
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
// load all the images from our bundle and add them to the scroll view
// NSUInteger i;
for (int i = 0; i <= 150; i++)
{
NSString *imageName = #"tempImage.jpg";
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[self.bestSellScrollView addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [self.bestSellScrollView subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[self.bestSellScrollView setContentSize:CGSizeMake((150 * kScrollObjWidth),
[self.bestSellScrollView bounds].size.height)];
}
If you mean like what happens with respect UITableViewCell in a UITableView, then its not possible in the horizontal scroller.
The reusable cells property for a table view is provided by the system and it not applicable for horizontal scroller.
You have to write on your own logic in order to achieve it, perhaps! Its a good question though. Will be tuned to other answers just in case if anything is possible.
If you mean you'd like to keep the UIImageView(s) where they are in the scrollview, but you'd like to change the UIImage that they show, try something like this:
-(void)changeImageViewWithTag:(NSInteger)aTag toImage:(UIImage *)anImage
{
UIImageView *theView = [self.bestSellScrollView viewWithTag:aTag];
if (theView)
{
[theView setImage:anImage];
}
}
I am assuming that you intend to reuse the UIImageView cell instances in the UIScrollView.
I hope that Daniel Tull's implementation may be helpful--
https://github.com/danielctull/DTGridView
You may like to see an Apple sample code on UIScrollView as well(I don't have the link, but u can easily find it on the web)
Thanks!
Ishank
A follow on from the question I asked yesterday.
I have a paging scrollView that only pages in the y-axis. At the moment I have it working that I have an array of UIImageViews containing different UIImages and the photoScroller works as i'd expect but when I try to add the imageView as a subview of another scrollView to allow pinching and zooming it breaks the gallery.
By breaks I mean it only loads the first image but the spaces left there for the other images and not pinching happens.
- (void)loadView{
// Creates 4 images from the file names
UIImage *img0 = [UIImage imageNamed:#"29.png"];
UIImage *img1 = [UIImage imageNamed:#"33.png"];
UIImage *img2 = [UIImage imageNamed:#"IMAG0085.JPG"];
UIImage *img3 = [UIImage imageNamed:#"DSC00081.JPG"];
NSMutableArray *imgArray = [[NSMutableArray alloc] initWithObjects:img0,img1,img2, img3, nil]; //Places images into array
CGRect pagingScrollViewFrame = [[UIScreen mainScreen] bounds]; // Creates initial scrollViewFrame to be the size of the screen
pagingScrollViewFrame.origin.x -= 10; //moves it 10px to the left
pagingScrollViewFrame.size.width += 20; //adds 20px to the right creating a 10px blank buffer either side
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame]; //Creates the pagingScrollView with the size specified with the frame
pagingScrollView.pagingEnabled = YES; //allow paging
pagingScrollView.backgroundColor = [UIColor blackColor]; //background black
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [imgArray count], pagingScrollViewFrame.size.height); //sets the width of the scroll view depending on the number in amges in the array.
self.view = pagingScrollView; //add the pagingScrollView to the main view
for (int i=0; i < [imgArray count]; i++) { //loop to add the images to an imageView and then add them to the paging ScrollView
/*--------Gets the image from the array and places it in an imageView------*/
UIImageView *page = [[UIImageView alloc] initWithImage: [imgArray objectAtIndex:i]];
page.frame = [[UIScreen mainScreen] bounds];
page.contentMode = UIViewContentModeScaleAspectFit;
//[page.setClipsToBounds:YES];
CGRect cgRect = [[UIScreen mainScreen] bounds];
CGSize cgSize = cgRect.size;
[page setFrame:CGRectMake((i*pagingScrollViewFrame.size.width)+10, 0, cgSize.width, cgSize.height)];
/*--------Creates Zooming scrollView and adds the imageView as a subView------*/
UIScrollView *zoomingScrollView = [[UIScrollView alloc] initWithFrame:cgRect];
zoomingScrollView.delegate = self;
zoomingScrollView.maximumZoomScale = 4.0;
zoomingScrollView.clipsToBounds = YES;
[zoomingScrollView addSubview:page];
[pagingScrollView addSubview:zoomingScrollView];
}}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
NSArray *array = [scrollView subviews];
return [array lastObject];
}
zoomingScrollView.frame = CGRectMake((i*pagingScrollViewFrame.size.width)+10, 0, cgSize.width, cgSize.height)];
page.frame = zoomingScrollView.bounds;
I'm ATTEMPTING to learn UIScrollview using Apple's Docs and their sample code http://developer.apple.com/iphone/library/samplecode/Scrolling/index.html but something SO simple is escaping me.
How do you tell what image is currently on the screen, so that if I selected one of the images in the horizontal scrolling view, how would I get the filename of the image, or even a pointer in the array, to then do something further with the image?
I thought with Page Control enable I might be able to find a page # and map it to the image. I thought about counting deceleration to count pages, but a flick no full enough will increment it and give a false number.
The last thing I could think of is to get contentOffSet and divide by image size which will give a 1, 2, 3 and I could point to the array (too tired to try tonight... thought I might ask before I waste a lot more time ;-) ).
Any other ideas? I thought there would be a method somewhere that they use in the photo album app.
PS: Here's the code:
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[scrollView1 setContentSize:CGSizeMake((kNumImages * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
- (void)viewDidLoad
{
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollView1 setBackgroundColor:[UIColor blackColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView1.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
//NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"Card %d.png", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
This was easy after a good sleep!
CGPoint p = scrollView1.contentOffset;
NSLog(#"x = %f, y = %f", p.x, p.y);
Now just divide by 320 (if horizontal and full screen image) and add 1 (because it starts at 0).
Hope this helps someone else!
Paul