I have started trying to understand the way apple implements the photoviewer app for the iPhone after watching both videos from WWDC 2009 and 2010 about scrollViews and paging through photographs and I am taking each step very slowly to understand the processes very well before I implement it all into my app.
I have run into a couple of problems at the moment:
Firstly I have it set up to have a paging scroll view to swipe left and right between photos with a bit of space in between like on the videos but when I add an image inside a UIImageView th image is too big for the screen, I have tried adding UIViewContentModeScaleAspectFit; to no effect.
When I go through the for loop to look at each element of the array containing the images the UIViews overlap and show one photograph on top of the other, I would like to know how to separate them into the next section of the paging scroll view.
- (void)loadView{
UIImage *img0 = [UIImage imageNamed:#"29.png"];
UIImage *img1 = [UIImage imageNamed:#"33.png"];
NSMutableArray *imgArray = [[NSMutableArray alloc] initWithObjects:img0, img2, nil];
CGRect pagingScrollViewFrame = [[UIScreen mainScreen] bounds];
pagingScrollViewFrame.origin.x -= 10;
pagingScrollViewFrame.size.width += 20;
pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
pagingScrollView.pagingEnabled = YES;
pagingScrollView.backgroundColor = [UIColor blackColor];
pagingScrollView.contentSize = CGSizeMake(pagingScrollViewFrame.size.width * [imgArray count], pagingScrollViewFrame.size.height);
self.view = pagingScrollView;
for (int i=0; i < [imgArray count]; i++) {
UIImageView *page = [[UIImageView alloc] initWithImage: [imgArray objectAtIndex:i]];
page.contentMode = UIViewContentModeScaleAspectFit;
[pagingScrollView addSubview:page];
}}
As I have mentioned I am fairly new to programming for the iPhone and am taking things slowly to fully understand, eventually this program will mimic the native app with pinching and tapping for zoom.
If you're using UIImageViews, you should make sure that your view has its clipsToBounds field set to yes. Try adding:
UIImageView *page = [[UIImageView alloc]
initWithImage:[imgArray objectAtIndex:i]];
[page setContentMode:UIViewContentModeScaleAspectFit];
[page setClipsToBounds:YES];
[pagingScrollView addSubview:page];
Then, make sure you are setting your image's frame to the correct offset within the scroll view. The frame's origin.x needs to be the width of the frame times the image index. So you need something like this:
[page setFrame:CGRectMake(i*pagingScrollViewFrame.size.width, y, width, height)];
where i is your index from your for loop.
Though in the sample code from the WWDC session you're referring to, this is done in a method called -configurePage. Have you downloaded the sample code?
-[UIImageView initWithImage:] sets the frame to be the image's size. You'll need to use page.frame = [[UIScreen mainScreen] bounds] or similar to scale images to the correct size.
Related
I am making one iPhone app in which i need to show some images inside UIScrollView, on left and right there will be two buttons user can click on button and it will show the next or previous image. Also at the bottom there is one button, when user will click on that button it will show the image which we have selected in scrollview.I would like to know how do we show multiple images inside that scrollview and while selecting bottom button, how to find which image was there inside scrollview.
An example from danielbeard.wordpress.com
In case your image names aren't just numbers:
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[scrollView setPagingEnabled:YES];
[scrollView setAlwaysBounceVertical:NO];
NSArray *imagesArray = [NSArray arrayWithObjects:#"img1.png", #"img2.png", #"img3.png", nil];
for (int i = 0; i < [imagesArray count]; i++)
{
CGFloat xOrigin = i * scrollView.frame.size.width;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin, 0, scrollView.frame.size.width, scrollView.frame.size.height)];
[imageView setImage:[UIImage imageNamed:[imagesArray objectAtIndex:i]]];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[scrollView addSubview:imageView];
}
[scrollView setContentSize:CGSizeMake(scrollView.frame.size.width * [imagesArray count], scrollView.frame.size.height)];
have look on to this example:
http://danielbeard.wordpress.com/2012/09/17/adding-a-uiscrollview-to-a-uiview-ios/
Apple.developer PhotoScroller demonstrates the use of embedded UIScrollViews and CATiledLayer to create a rich user experience for displaying and paginating photos that can be individually panned and zoomed.
CATiledLayer is used to increase the performance of paging, panning, and zooming with high-resolution images or large sets of photos.
you just simply first
create a new view on runtime and image and assign tag all views like 1000 or 100 and increment on tag value and then add this view to scrollview and two buttons for left and right moving and make their outlet actions and add all the scrollview sub views in to an mutable array like this
indexStart=100;
UIView *AddView=[[UIView alloc]initWithFrame:CGRectMake(55, 0, 100, 100)];
AddView.tag=indexStart;
btnTap.tag=indexStart;
UIImageView *imgview=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
[AddView addSubview:imgview];
imgview.image=image;
imgview.tag=1000;
[ScrollView addSubview:AddView];
[imgArray addObject:AddView];
you use loop to do this and on left and right button you use this code and in this code editImgeView is the image view inbetween left and right button where you show the image you just simple indexstart ++ or -- if user choose right or left button
for (int index = 0; index < [imgAddArrayAfter count]; index ++ ) {
NSLog(#"index %d",index);
UIView *vc=[imgArray objectAtIndex:index];
NSLog(#"view tag %d",vc.tag);
if(vc.tag == indexStart)
{
UIImageView *modalView=(UIImageView *) [vc viewWithTag:1000];
editImgeView.image=modalView.image;
}
}
i hope you understand ;-)
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
scrollView.contentSize = CGSizeMake(320, 465);
[scrollView setScrollEnabled:YES];
[scrollView setPagingEnabled:YES];
[scrollView setAlwaysBounceVertical:NO];
[self.view addSubview:scrollView];
NSMutableArray *arrImage = [NSMutableArray arrayWithObjects:#"food1.jpeg", #"food2.jpeg", #"food3.jpeg",#"food4.jpeg", #"food5.jpeg", #"food6.jpeg",#"food7.jpeg", #"food8.jpeg", #"foo9.jpeg",#"food10.jpeg", #"food11.jpeg", #"food12.jpeg",#"food13.jpeg", #"food14.jpeg", #"food15.jpeg", #"food16.jpeg", nil];
for (int i = 0; i < [arrImage count]; i++)
{
CGFloat xOrigin = i * scrollView.frame.size.width;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOrigin, 0, scrollView.frame.size.width, scrollView.frame.size.height)];
[imageView setImage:[UIImage imageNamed:[arrImage objectAtIndex:i]]];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[scrollView addSubview:imageView];
}
[scrollView setContentSize:CGSizeMake(scrollView.frame.size.width * [arrImage count], scrollView.frame.size.height)];
}
I know this thread is old, but I think the problem with loading lot's of images in the scroll view still exists. If you ever want to load images in the scroll view you will face a problem of memory usage. The images most likely will consume most of your device's memory. The only way of doing is to create reusable scroll view that works similar to the uitableview - the scroll view that has pool of views (with images) ready to display. This can be quite complex to create.
I have created open source project to support reusable loading images in the scroll view. It is very easy to implement. You need to call couple of delegate and data source methods and that's it. There is also sample project for obj-c and swift in order to make easy to understand. Please feel free to contribute. I hope it will be useful.
here is a source: https://github.com/sumofighter666/ReusableScrollView
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))
I've use a imagepicker to select image from my photo library, then i display that image in an uiimageview. Landscape photo works fine but there is some weirdness to the portrait image. The portrait image suppose to fill up the left and right empty space but it's not.
Cant figure out why the picture wont fill up the left and right space cause the imageview frame did specify the mainScreen bounds.
If i take away the aspectfit then the potrait image is nicely display but the landscape image is stretched to fill up the whole imageview.
My code is as follow:
CGRect frame = [[UIScreen mainScreen] bounds];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:frame];
UIImageView *selectedImageView = [[UIImageView alloc] initWithFrame:frame];
selectedImageView.image = image;
selectedImageView.contentMode = UIViewContentModeScaleAspectFit;
[scrollView addSubview:selectedImageView];
[selectedImageView release];
scrollView.delegate = self;
[self.view addSubview:scrollView];
[scrollView release];
Here is what it looks like:
Edit: My goal is to display the photo like it's been display in Photos album, start out as fitting in the view and allow zoom in to a certain limit.
Try out
UIImageView *logoImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo_bg.png"]];
[logoImageView setFrame:CGRectMake(0, 0, 320, [UIImage imageNamed:#"logo_bg.png"].size.height)];
[mainView addSubview:logoImageView];
I'm building a comic viewer app, that consists of two view controllers, the root viewcontroller basically displays a view where a user decides what comic they want to read by pressing a button. The second viewController actually displays the comic as a uiscrollview with a toolbar and a title at the top.
So the problem I am having is that the comic image panels themselves are not changing from whatever the first comic you go to if you select another comic after viewing the first one. The way I set it up, and I admit it's not exactly mvc, so please don't hate, anyway the way I set it up is each comic uiscrollview consists of x number of jpg images where each comic set's image names have a common prefix and then a number like 'funny1.jpg', 'funny2.jpg', 'funny3.jpg' and 'soda1.jpg', 'soda2.jpg', 'soda3.jpg', etc...
so when a user selects a comic to view in the root controller it makes a call to the delegate and sets ivars on instances of the comicviewcontroller that belongs to the delegate (mainDelegate.comicViewController.property) I set the number of panels in that comic, the comic name for the title label, and the image prefix.
The number of images changes(or at least the number that you can scroll through), and the title changes but for some reason the images are the same ones as whatever comic you clicked on initially.
I'm basing this whole app off of the 'scrolling' code sample from apple.
I thought if I added a viewWillAppear:(BOOL) animated call to the comicViewController everytime the user clicked the button that would fix it but it didn't, after all that is where the scrollview is laid out.
Anyway here is some code from each of the two controllers:
RootController:
-(IBAction) launchComic2{
AppDelegate *mainDelegate = [(AppDelegate *) [UIApplication sharedApplication] delegate];
mainDelegate.myViewController.comicPageCount = 3;
mainDelegate.myViewController.comicTitle.text = #"\"Death by ETOH\"";
mainDelegate.myViewController.comicImagePrefix = #"etoh";
[mainDelegate.myViewController viewWillAppear:YES];
[mainDelegate.window addSubview: mainDelegate.myViewController.view];
comicViewController:
-(void) viewWillAppear:(BOOL)animated {
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 whiteColor]];
[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 <= self.comicPageCount; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#%d.jpg", self.comicImagePrefix, i];
NSLog(#"%#%d.jpg", self.comicImagePrefix, 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
}
- (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((self.comicPageCount * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
Any help would be appreciated on this.
Nick
So what I ended up doing is just making multiple instances of the comic controller inside the delegate instead of just re-using the one. Will update this if I run into problems.
Nick
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