If you're new here, you may want to subscribe to my RSS feed or follow me on Twitter. Thanks for visiting!
The UIImagePicker is an easy to use and beautiful way to let users pick images from their photo library. But what if you want to let the users pick custom images included with your app?
Unfortunately, the UIImagePicker does not have any functionality to let you display custom images. However, in this tutorial we’ll show you can just create your own picker that looks quite similar and is just as easy to use!
Building the View
The basic idea is we want to have a button that users can tap to “choose a custom image.” Once they tap the button, it should push a new view controller onto the navigation controller stack to display the images. The user should be able to scroll through the images, and tap on the one they like, just like they would with UIImagePicker.
The easiest way to implement this is to create the view programmatically in the viewDidLoad method. We’ll create a UIScrollView to contain the content, which will be a grid of UIButtons set to the images we want the user to choose from.
Let’s assume we have an array called thumbs with 64×64 thumbnails for each image we would like to display, and a parallel array called images with the full sized images. In that case, it looks something like this:
- (void)viewDidLoad { UIScrollView *view = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; int row = 0; int column = 0; for(int i = 0; i < _thumbs.count; ++i) { UIImage *thumb = [_thumbs objectAtIndex:i]; UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(column*100+24, row*80+10, 64, 64); [button setImage:thumb forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; button.tag = i; [view addSubview:button]; if (column == 2) { column = 0; row++; } else { column++; } } [view setContentSize:CGSizeMake(320, (row+1) * 80 + 10)]; self.view = view; [view release]; [super viewDidLoad]; } |
The code should be pretty self explanatory, but there are a few things I’d like to point out:
- I’ve set the tag on the button field to be the index in the thumbs array so it’s easy to identify the offset later.
- Don’t forget to call the setContentSize method on the UIScrollView so the scroll view knows how large the scrollable content area is. Without this, you will get some strange behavior!
- Yeah I know, I should have used more constants for some of the magic numbers in here, but I got lazy :P
Choosing an image
Since we’re using buttons to represent the images, getting notification when the user chooses an image is trivial:
- (IBAction)buttonClicked:(id)sender { UIButton *button = (UIButton *)sender; UIImage *selectedImage = [_images objectAtIndex:button.tag]; // Do something with image! } |
Image sizing
Commonly you want to let the users browse through thumbnails of the images, but once they select the image you want to use the full size image. So what’s the best way to accomplish this? There are two methods:
- Resize the images dynamically. I have a helper function called imageByScalingAndCroppingForSize (included in the sample project) that I often use to scale images on the fly. This has the advantage of not having to make a thumbnail for each image manually and include it in the project (which also saves space). The tradeoff is scaling images can be slow on a device, especially if you are resizing many images.
- Add thumbnails and full size images for each image into your project. This is a bit more work, but is the preferred option if you can spare the space. The main thing to keep in mind is once your app gets over 10MB, users who purchase your app cannot download it wirelessly – they have to be connected via Wi-Fi or synchronize. This may impact sales (anyone have more info/thoughts on if it does in practice)?
Show Me The Code!
Here’s a sample project with the custom image picker described above – feel free to use it in your own projects. Personally, I’ve found it useful in two iPhone projects so far – it seems to be a common need.
Have you had a need for a custom image picker in your project? If so, what have you used it for?
Category: iPhone







Thanks, Its really helpful.
I worked on a project where we wanted to do batch operations on our image library (currently a no-no from Apple’s point of view), and so we went about parsing the Photo Database file (binary header) which describes the database. We were then able to read in all the images on the iPhone/iPod and make our own image picker (of sorts).
I think it’s a shame that apple won’t let you access your own photos just because they are outside the sandbox. that’s why the app was rejected.
Wow, very cool Horseshoe. Too bad about the app but it’s awesome that you figured out how to do that! :]
Hi…Nice tutorial…….i m working on app which require to behave like the Photo app on the iphone i m using uiimagepicker the get photos from iphone library….So now the prob with uiimage picker is tha it provide u the image data for the image which u select from the picker ………to implement the slide show “like photo app” i need to get all the images from a perticular folder ..so can u help me out how can it be possible ………or there is ny other approach to do the same……or ny other valuable info abt thisss………
@kaps – So if I understand what you’re saying, you want to load all of the photos from a user’s photo library without using UIImagePicker?
As Horseshoe was saying, as far as I know that isn’t possible with the current SDK. Check out this thread for more info:
http://stackoverflow.com/questions/818369/how-can-i-load-images-from-a-users-photo-album-on-the-iphone
You could get the user to select images with the UIImagePicker and then make a slideshow out of those, however.
Hi Ray…thanks for ur reply. as u said i could make a slide show using uiimage picker but the problem is i will only get the selectedImage in the function
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingIamge:(UIImage *)image
editingInfo:(NSDictionary*)editingInfo{}
Form UIImagePicker User can select only one image at a time but for slideShow i need info abt all the images in that folder……pls put some light on it… is there is ny better way of doing this…
Sorry, there’s no better way to do this with the current APIs as far as I know.
Thanks Ray…….Hi Horseshoe can u pls help me out in what way u have done parsing Photo Database file (binary header) …….
Hi Ray,
Thanks for the example.
it helped me in creating an ScrollView for ipad.
Regards,
Ganesh Faterpekar
Hi…Nice tutorial.
But as i am a noobie, i want to zoom & pan a selected image from the image gallery as give in your example. please help me with the code
@antogonio: You might be interested in checking out the three20 library, which has a nice photo browser component that allows you to flick between images and zoom in too.
Hi Ray…thanks for ur reply.
Good to see u Ray.
I`m writing a book about iPhone development for beginners.
Can I use your code?
Surely, I will make comment about you. :-)
@NoPD: Sorry I can’t give permission to use materials from this blog in a book, as I may be writing one of my own some day!
I see. :-)
Thank you so much. Ray . It is very helpful.
Thanks.
This is what I need.
Please tell me how to add the UIimageController into my project
@San: This tutorial may be helpful for you:
http://www.raywenderlich.com/1797/how-to-create-a-simple-iphone-app-tutorial-part-1
Damn! I can’t believe that you made a tutorial for every single problem I encounter.
I’ve been searching on how to do that for a short while until I used the good words to come to this page.
Again, thank you Ray :)
thanks for this great tutorial … but what about using a table and adding uibuttons in tableview cells?
don’t you think its better and faster that way?
@Aurelien: Lol glad it came in handy :]
@Zeyad: You could definitely do that. It would probably be more efficient that way as it wouldn’t load the cells until they’re on the screen (while this loads everything at once). However this was simple to implement and worked for my use case, so that’s why I chose this :]