I followed the tutorial about how to create a scrollView Page Control: http://www.iosdevnotes.com/2011/03/uiscrollview-paging/
This tutorial is really good and I implement well the code. Here my question:
I want to put a space between the my PageViews, but when it change the page it show the space between the views in the next page. The scroll must stop after the space when I change the page.
I changed the tutorial code here:
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil];
#define space 20
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = (self.scrollView.frame.size.width + space) * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
[subview release];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count+ space*(colors.count-1), self.scrollView.frame.size.height);
}
It sounds like you want a “gutter” between the pages, so that each page fills the scroll view and the gutter is only visible while the user is dragging the view. The built-in Photos app does this, for example.
Make your scroll view wider by space points. For example, if you want the scroll view to appear to be as wide as the screen (320 points), with a 20 point margin between items, then make the scroll view 340 points wide, with the extra 20 points hanging off the right edge of the screen.
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil];
#define kGutterWidth 20
UIScrollView *scrollView = self.scrollView;
CGRect scrollViewFrame = scrollView.frame;
scrollViewFrame.size.width += kGutterWidth;
scrollView.frame = scrollViewFrame;
CGSize scrollViewSize = scrollView.bounds.size;
for (int i = 0; i < colors.count; i++) {
CGRect frame = CGRectMake(scrollViewSize.width * i, 0,
scrollViewSize.width - kGutterWidth, scrollViewSize.height);
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[scrollView addSubview:subview];
[subview release];
}
scrollView.contentSize = CGSizeMake(
colors.count * scrollViewSize.width,
scrollViewSize.height);
}
I've been down this road before, and I would advise laying out the scroll view as the tutorial code recommends, with no space between the subviews.
Instead, give each subview another subview whose frame is inset from it's parent...
CGRect scrollViewFrame = self.scrollView.frame;
for (int i=0; i<colors.count; i++) {
CGRect frame = CGRectMake(scrollViewFrame.size.width * i, 0, scrollViewFrame.size.width, scrollViewFrame.size.height);
// this will be our framing view, full size with no gaps
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [UIColor whiteColor];
// here's the trick - use CGRectInset on the framing view's bounds
UIView *colorView = [[UIView alloc] initWithFrame:CGRectInset(subview.bounds, 10, 10)];
colorView.backgroundColor = [colors objectAtIndex:i];
[subview addSubview:colorView];
[self.scrollView addSubview:subview];
// aren't you using ARC? your tutorial is probably older than ARC
// would strongly suggest converting to ARC
[subview release];
[colorView release];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
The benefit of this approach is that the math for the top level subview layout remains a simple multiple of the width. The only place you'll refer to that inset constant is on the CGRectInset where it belongs.
Related
I am attempting to make a basic scroll view with a connected page control, and I have run into some problems with my code. My viewDidLoad method looks like this:
- (void)viewDidLoad{
[super viewDidLoad];
NSLog (#"View did load");
// Do any additional setup after loading the view, typically from a nib.
scrollView.delegate = self;
scrollView.pagingEnabled=YES;
NSArray *frames = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil];
for (int i = 0; i < frames.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [frames objectAtIndex:i];
[self.scrollView addSubview:subview];
NSLog (#"Looped, i = %i color = %#", i, [frames objectAtIndex:i]);
}
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * frames.count, scrollView.frame.size.height);
NSLog(#"The width is: %f", self.scrollView.frame.size.width);
}
The problem seems to be that the coloured frames I attempt to add to the view never appear (not even the first one). If I didn't have ARC enabled, I would have released the CGRect frame at the end of each loop, but it really should do that itself with ARC, right?
When I run the app, both in the simulator and on my actual phone, I get a black screen with the UIPageControl dots at the bottom. When I swipe my finger across the ScrollView nothing happens, but if I pull it very far to one side, the pageControl moves to the next "dot".
The last NSLog sentence always outputs 0.0000, indicating that none of the views have been added to the scroll view.
All help is very appreciated :)
The problem is doing it in viewDidLoad. Move your code to viewDidAppear: and it should work fine. Frames are not yet set in viewDidLoad.
I am trying to add set of imageviews on a UIScrollView. My problem is that the imageviews are overlapping with each other even though I increase the x value. What's also weird is that this problem is only for devices with ios 4.2.1, but works on simulator 4.2 and other device ios.
Here is my code:
- (void)addScrollView {
[self setImages];
scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
scrollView.delegate = self;
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
[self addSubview:scrollView];
NSUInteger nimages;
CGFloat cx = 0;
for (nimages = 1; nimages < [imagesArray count] ; nimages++) {
UIImage *image = [UIImage imageNamed:[imagesArray objectAtIndex:nimages]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.origin.x = cx;
rect.origin.y = 0;
rect.size.width = 320;
rect.size.height = 480;
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += rect.size.width;
}
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
}
Called from here:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addScrollView];
UIImage *handImg;
UIImageView *longhand = [[UIImageView alloc] init];
minuteHand = [[UIView alloc] initWithFrame:CGRectMake(0, 55, 320, 480)];
handImg = [UIImage imageNamed:#"clock_long_hand.png"];
longhand.image = handImg;
/************** TRY COMMENT OUT HERE **************/
longhand.frame = CGRectMake(155 - (handImg.size.width / 2), 240 - handImg.size.height, handImg.size.width, handImg.size.height);
[minuteHand addSubview:longhand];
[self addSubview:minuteHand];
/************** END COMMENT OUT HERE **************/
[longhand release];
}
return self;
}
UPDATE:
This code is in a UIView subclass which is why I use [self...] instead of [self.view...].
I tried experimenting and found that when I comment out the indicated parts, the scrollview works fine. But when it is included, this is when the imageviews are overlapped.
I know that the scrollview's content size is correct because its indicator continues to scroll, with just a plain black background.
I am really confused why this works on some ios and not on others. Hope you can help.
This might have something to do with autoresizing mask. The width actual images, I mean .png files is bigger than 320, right?
- (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 need to create a horizontal UIScrollView which to hold hundreds of thumbnail images, just like a slide of thumbnails.
For example, there will be 10 thumbnails showing in a single screen, each of them are horizontally adjacent to each other.
My problem is that I don't know how to make a horizontal UIScrollView to hold the multiple thumbnails which showing at the same time ?
A sample photo is as below. See the bottom part of the screen.
Thanks.
You can add all the thumbnails programatically to your scrollview and use the setContentSize method of UIScrollView. you have to pass 2 values in contentOffset. 1 for width and 1 for height. Please follow link to explore more on this. If you need further help please leave a comment.
Hope it helps.
Please consider Following example.
- (void)setupHorizontalScrollView
{
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = NO;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
NSUInteger nimages = 0;
NSInteger tot=0;
CGFloat cx = 0;
for (; ; nimages++) {
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", (nimages + 1)];
UIImage *image = [UIImage imageNamed:imageName];
if (tot==15) {
break;
}
if (4==nimages) {
nimages=0;
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect rect = imageView.frame;
rect.size.height = 40;
rect.size.width = 40;
rect.origin.x = cx;
rect.origin.y = 0;
imageView.frame = rect;
[scrollView addSubview:imageView];
[imageView release];
cx += imageView.frame.size.width+5;
tot++;
}
self.pageControl.numberOfPages = nimages;
[scrollView setContentSize:CGSizeMake(cx, [scrollView bounds].size.height)];
}
I suggest you to look at nimbus
Check out bjhomer's HSImageSidebarView project. It lets you load a scrollview horizontally or vertically and load in the images. Super easy to implement.
First of all, at storyboard drag and drop the scroll view and make the outlet of scrollview named scrollView. Two array one is mutable and one is immutable.
#property(nonatomic,strong)IBOutlet UIScrollView *scrollView;
#property(nonatomic,strong)NSMutableArray *images;
#property(nonatomic,strong)NSArray *imagesName;
The immutable array only store the images which we want to show on the scroll view.Make sure UIscrollview delegate is defined.
In viewcontoller.m file in didload function do following code:
imagesName = [[NSArray alloc]initWithObjects:#"centipede.jpg",#"ladybug.jpg",#"potatoBug.jpg",#"wolfSpider.jpg", #"ladybug.jpg",#"potatoBug.jpg",#"centipede.jpg",#"wolfSpider.jpg",nil];
// mutable array used to show the images on scrollview dynamic becaus after one
// image when scroll other will come
images = [[NSMutableArray alloc]init];
scrollView.delegate = self;
scrollView.scrollEnabled = YES;
int scrollWidth = 120;
scrollView.contentSize = CGSizeMake(scrollWidth,80);
int xOffset = 0;
//the loop go till all images will load
for(int index=0; index < [imagesName count]; index++)
{
UIImageView *img = [[UIImageView alloc] init];
// make the imageview object because in scrollview we need image
img.frame = CGRectMake(5+xOffset, 0, 160, 110);
// the offset represent the values, used so that topleft for each image will
// change with(5+xOffset, 0)and the bottomright(160, 110)
NSLog(#"image: %#",[imagesName objectAtIndex:index]);
img.image = [UIImage imageNamed:[imagesName objectAtIndex:index]];
// The image will put on the img object
[images insertObject:img atIndex:index];
// Put the img object at the images array which is mutable array
scrollView.contentSize = CGSizeMake(scrollWidth+xOffset,110);
//scroll view size show after 125 width the scroll view enabled
[scrollView addSubview:[images objectAtIndex:index]];
// set images on scroll view
xOffset += 170;
}
You can calculate content size width of the scrollview as width = number of images * size of each image. Then set contentSize of the scrollview to this width and the height that you want (scrollView.contentSize = CGSizeMake(width, height))
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;