The following Objective-C source code applies to this article, based on the KTPhotoBrowser project.
UCImageGalleryList.h file:
#import <Foundation/Foundation.h>
#import <GXFlexibleClient/GXFlexibleClient.h>
#import <MessageUI/MessageUI.h>
#import "KTThumbsViewController.h"
#import "KTPhotoBrowserDataSource.h"
#import "KTPhotoView.h"
#import "UCImageGalleryDataSource.h"
#import "UCImageGalleryDetail.h"
@interface UCImageGalleryList : GXControlGridBase <KTThumbsViewDataSource, UCImageGalleryDetailDelegate, UCImageGalleryDataSource, MFMailComposeViewControllerDelegate>
{
NSArray *_photos; // The list of attributes of type Photo
UCImageGalleryDetail *_detail;
NSMutableArray *_selectedImageIndexes;
BOOL _isSelecting;
}
@end
UCImageGalleryList.m file.
#import "KTPhotoBrowserDataSource.h"
#import "KTPhotoBrowserGlobal.h"
#import "KTPhotoView+SDWebImage.h"
#import "KTThumbView+SDWebImage.h"
#import "KTPhotoScrollViewController.h"
#import "UCImageGalleryList.h"
@interface UCImageGalleryList (Private)
- (void)loadData:(NSInteger)count;
- (NSInteger)numberOfPhotos;
- (void)reloadActionBarItems;
@end
#pragma mark -
@interface UCImageGalleryList (InternalProperties)
- (KTThumbsView *)thumbsView;
- (NSString *)dataAttribute;
- (NSString *)dataFieldSpecifier;
- (NSString *)titleAttribute;
- (NSString *)titleFieldSpecifier;
- (NSString *)subtitleAttribute;
- (NSString *)subtitleFieldSpecifier;
- (BOOL)enableShareAction;
@end
#pragma mark -
@interface UCImageGalleryList (Actions)
- (void)shareButtonTapped:(id)sender;
- (void)emailSelectedImages:(id)sender;
@end
#pragma mark -
@implementation UCImageGalleryList
#pragma mark - Internal properties
- (KTThumbsView *)thumbsView {
return (KTThumbsView *)[self gridView];
}
- (NSString *)dataAttribute {
NSString *propVal = [ [self properties] getPropertyValueString:@"@UCImageGalleryDataAtt"];
if (!propVal) {
for(id <GXEntityDataFieldDescriptor> fieldDescriptor in [ [self.entityDataListProvider entityDataDescriptor] entityDataFieldDescriptors]) {
id <GXEntityDataFieldInfo> fInfo = [fieldDescriptor entityDataFieldInfo];
if (([fInfo entityDataFieldInfoSpecialDomain] == GXSpecialDomainPhoto)
|| ([fInfo entityDataFieldInfoDataType] == GXDataTypeBitmap))
{
propVal = [fieldDescriptor entityDataFieldName];
break;
}
}
}
return propVal;
}
- (NSString *)dataFieldSpecifier {
return [ [self properties] getPropertyValueString:@"@UCImageGalleryDataField"];
}
- (NSString *)titleAttribute {
return [ [self properties] getPropertyValueString:@"@UCImageGalleryTitleAtt"];
}
- (NSString *)titleFieldSpecifier {
return [ [self properties] getPropertyValueString:@"@UCImageGalleryTitleField"];
}
- (NSString *)subtitleAttribute {
return [ [self properties] getPropertyValueString:@"@UCImageGallerySubtitleAtt"];
}
- (NSString *)subtitleFieldSpecifier {
return [ [self properties] getPropertyValueString:@"@UCImageGallerySubtitleField"];
}
- (BOOL)enableShareAction {
return [ [self properties] getPropertyValueBool:@"@UCImageGalleryEnableShare"];
}
- (UIView *)newGridViewWithFrame:(CGRect)frame {
KTThumbsView *thumbs = [ [KTThumbsView alloc] initWithFrame:frame];
[thumbs setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[thumbs setScrollsToTop:YES];
[thumbs setScrollEnabled:YES];
[thumbs setAlwaysBounceVertical:YES];
[thumbs setBackgroundColor:[UIColor clearColor]];
[thumbs setDataSource:self];
[thumbs setTag:NSIntegerMax];
if (CURRENT_DEVICE_IPAD) {
[thumbs setThumbSize:CGSizeMake(120, 120)];
}
else {
[thumbs setThumbSize:CGSizeMake(75, 75)];
}
return thumbs;
}
- (void)reloadData {
[self loadData:[ [self entityDataListProvider] numberOfLoadedEntitiesInSection:0]];
}
- (NSString *)titleForImageAtIndex:(NSInteger)index {
return [self fieldValueAtIndex:index
forFieldName:[self titleAttribute]
fieldSpecifier:[self titleFieldSpecifier]
];
}
- (NSString *)captionForImageAtIndex:(NSInteger)index {
return [self fieldValueAtIndex:index
forFieldName:[self subtitleAttribute]
fieldSpecifier:[self subtitleFieldSpecifier]
];
}
#pragma mark - KTThumbsViewDataSource
- (NSInteger)thumbsViewNumberOfThumbs:(KTThumbsView *)thumbsView {
return [self numberOfPhotos];
}
- (KTThumbView *)thumbsView:(KTThumbsView *)thumbsView thumbForIndex:(NSInteger)index {
KTThumbView *thumbView = [thumbsView dequeueReusableThumbView];
if (!thumbView) {
thumbView = [ [ [KTThumbView alloc] initWithFrame:CGRectZero] autorelease];
}
[thumbView setController:self];
// Set thumbnail image asynchronously.
if (index < [_photos count]) {
NSURL *url = [_photos objectAtIndex:index];
if ([url isKindOfClass:[NSNull class]]) {
[thumbView setImage:[GXUtilities placeHolderImage] forState:UIControlStateNormal];
}
else {
[thumbView setImageWithURL:url placeholderImage:[GXUtilities placeHolderImage]];
}
}
else {
if (_autoLoad) {
//[thumbView setActivityIndicatorVisible:YES];
[thumbView setImage:nil forState:UIControlStateNormal];
NSInteger totalCount = [ [self entityDataListProvider] totalCount];
switch (totalCount) {
case kTotalCountUnknownLocal:
case kTotalCountUnknownRemote:
case kTotalCountUnknownPendingRemote:
[ [self entityDataListProvider] load];
break;
default:
break;
}
}
else {
[thumbView setImage:KTLoadImageFromBundle(@"refreshIcon.png") forState:UIControlStateNormal];
}
}
BOOL isSelected = NO;
for (NSNumber *num in _selectedImageIndexes) {
if ([num unsignedIntValue] == index) {
isSelected = YES;
break;
}
}
[thumbView setSelected:isSelected];
return thumbView;
}
- (void)didSelectThumbAtIndex:(NSUInteger)index {
if (index >= [_photos count]) {
_autoLoad = YES;
[ [self entityDataListProvider] load];
return;
}
if (_isSelecting) {
UIView *thumb = [ [self thumbsView] viewWithTag:index];
BOOL selected = NO;
if ([thumb isKindOfClass:[KTThumbView class]]) {
selected = ![(KTThumbView *)thumb isSelected];
[(KTThumbView *)thumb setSelected:selected];
}
if (selected) {
[_selectedImageIndexes addObject:[NSNumber numberWithUnsignedInt:index]];
}
else {
for (NSNumber *num in _selectedImageIndexes) {
if (index == [num unsignedIntValue]) {
[_selectedImageIndexes removeObject:num];
break;
}
}
}
}
else {
if (TRUE) {
if (!_detail) {
_detail = [ [UCImageGalleryDetail alloc] initWithFrame:CGRectZero];
[_detail setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[_detail setDataSource:self];
[_detail setDelegate:self];
}
[ [self view] addSubview:_detail];
[UIView animateWithDuration:0.3f
animations:^ {
[_detail setFrame:self.view.bounds];
}
completion:^(BOOL finished) {
[_detail setCurrentIndex:index];
[_detail scrollToCurrentIndex];
[self reloadActionBarItems];
}
];
}
else {
[self presentDetailViewForPhotoAtIndex:index];
}
}
}
#pragma mark - Private
- (void)loadData:(NSInteger)count{
// This method reads the information of the entities and extracts the images
NSMutableArray *tmpPhotos = [ [NSMutableArray alloc] initWithCapacity:count];
NSString *photoAttName = [self dataAttribute];
NSString *photoFieldSpecifier = [self dataFieldSpecifier];
if (photoAttName){
for(NSUInteger i = 0; i < count; i++) {
NSString *value = [self valueForEntityDataFieldName:photoAttName
fieldSpecifier:photoFieldSpecifier indexPath:[NSIndexPath indexPathForRow:i inSection:0]
];
NSURL *url = [GXEntityHelper urlFromFieldValue:value];
if (url) {
[tmpPhotos addObject:url];
}
else {
[tmpPhotos addObject:[NSNull null]];
}
}
}
_photos = [tmpPhotos retain];
[tmpPhotos release];
[ [self thumbsView] reloadData];
}
- (NSInteger)numberOfPhotos {
NSInteger numberOfRows = 0;
NSInteger totalCount = [self.entityDataListProvider totalCount];
if (totalCount == kTotalCountUnknownLocal) {
numberOfRows = 1;
}
else {
numberOfRows = [self.entityDataListProvider numberOfLoadedEntitiesInSection:0];
switch (totalCount) {
case kTotalCountUnknownRemote:
case kTotalCountUnknownPendingRemote:
{
numberOfRows++; // "Load More..." or "Loading..." Cell
break;
}
default:
{
if (totalCount > numberOfRows)
numberOfRows++; // "Load More..." or "Loading..." Cell
break;
}
}
}
return numberOfRows;
}
- (void)reloadActionBarItems {
[ [ [self context] controlWithActionBarItemsDelegate] controlWithActionBarItemsNeedsReloadActions:self];
}
#pragma mark - UCImageGalleryDataSource
- (NSUInteger)count {
return [_photos count];
}
- (NSURL *)photoURLAtIndex:(NSUInteger)index {
return [_photos objectAtIndex:index];
}
- (NSString *)titleAtIndex:(NSUInteger)index {
return [self titleForImageAtIndex:index];
}
- (NSString *)captionAtIndex:(NSUInteger)index {
return [self captionForImageAtIndex:index];
}
#pragma mark - GXControlWithActionBarItems
- (NSArray *)controlRequiredNavigationBarRightItems {
NSArray *actionBarItemsArray = nil;
if ([self enableShareAction]) {
UIBarButtonSystemItem buttonSystemItem = _isSelecting ? UIBarButtonSystemItemDone : UIBarButtonSystemItemAction;
UIBarButtonItem *barButton = _isSelecting ? [ [UIBarButtonItem alloc] initWithTitle:[GXResources translationFor:@"GXM_Done"]
style:UIBarButtonItemStyleDone
target:self
action:@selector(shareButtonTapped:)]
: [ [UIBarButtonItem alloc] initWithBarButtonSystemItem:buttonSystemItem
target:self
action:@selector(shareButtonTapped:)
];
actionBarItemsArray = [NSArray arrayWithObject:barButton];
[barButton release];
}
return actionBarItemsArray;
}
#pragma mark - Actions
- (void)shareButtonTapped:(id)sender {
if (_detail) {
[_selectedImageIndexes removeAllObjects];
[_selectedImageIndexes addObject:[NSNumber numberWithUnsignedInt:[_detail currentIndex]]];
[self emailSelectedImages:sender];
}
else {
if (_isSelecting) {
[self emailSelectedImages:sender];
}
_isSelecting = !_isSelecting;
[self reloadActionBarItems];
}
}
- (void)emailSelectedImages:(id)sender {
if ([_selectedImageIndexes count]) {
MFMailComposeViewController *picker = [ [MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setMessageBody:@"" isHTML:NO];
for (int index = 0; index < _selectedImageIndexes.count; index++) {
NSUInteger photoIndex = [ [_selectedImageIndexes objectAtIndex:index] unsignedIntValue];
UIImage *image = [ [SDWebImageManager2 sharedManager] imageWithURL:[_photos objectAtIndex:photoIndex]];
NSData *data = UIImagePNGRepresentation(image);
NSString *imageName = [NSString stringWithFormat:@"SelectedImage_%d", index];
[picker addAttachmentData:data mimeType:@"image/png" fileName:imageName];
UIView *thumb = [ [self thumbsView] viewWithTag:photoIndex];
if ([thumb isKindOfClass:[KTThumbView class]]) {
[(KTThumbView *)thumb setSelected:NO];
}
}
[ [ [self context] entityViewController] presentModalViewController:picker animated:YES];
[picker release];
[_selectedImageIndexes removeAllObjects];
}
}
#pragma mark - MFMailComposeViewControllerDelegate
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
{
[ [ [self context] entityViewController] dismissModalViewControllerAnimated:YES];
}
#pragma mark - Memory management
- (void)dealloc {
[_selectedImageIndexes release], _selectedImageIndexes = nil;
[_photos release], _photos = nil;
[_detail release], _detail = nil;
[super dealloc];
}
@end
UCImageGalleryDataSource.h file
#import <Foundation/Foundation.h>
@protocol UCImageGalleryDataSource <NSObject>
- (NSUInteger)count;
- (NSURL *)photoURLAtIndex:(NSUInteger)index;
- (NSString *)titleAtIndex:(NSUInteger)index;
- (NSString *)captionAtIndex:(NSUInteger)index;
@end
UCImageGalleryDetail.h file
#import <UIKit/UIKit.h>
#import <GXFlexibleClient/GXFlexibleClient.h>
#import "UCImageGalleryDataSource.h"
#import "KTPhotoView.h"
@class UCImageGalleryDetail;
#pragma mark -
@protocol UCImageGalleryDetailDelegate <NSObject>
- (void)ucimageGalleryDetailDidTapCloseButton:(UCImageGalleryDetail *)detail;
- (void)ucimageGalleryDetail:(UCImageGalleryDetail *)detail didTapImageAtIndex:(NSInteger)index;
@end
#pragma mark -
@interface UCImageGalleryDetail : UIView <UIScrollViewDelegate> {
UIScrollView *_scrollView;
UIToolbar *_toolbar;
UIButton *_closeButton;
UILabel *_titleView;
UILabel *_captionView;
id<UCImageGalleryDataSource> _dataSource;
id<UCImageGalleryDetailDelegate> _delegate;
NSUInteger _currentIndex;
NSMutableArray *_photoViews;
}
@property (nonatomic, assign) id<UCImageGalleryDataSource> dataSource;
@property (nonatomic, assign) NSUInteger currentIndex;
@property (nonatomic, assign) id<UCImageGalleryDetailDelegate> delegate;
- (void)scrollToCurrentIndex;
@end
UCImageGalleryDetail.m file
#import "UCImageGalleryDetail.h"
#import "KTPhotoView.h"
#import "KTPhotoView+SDWebImage.h"
#import "KTPhotoBrowserGlobal.h"
#define kCaptionPadding 10
#define kCloseButtonWidth 44
#define kCloseButtonHeight 44
#define kDefaultLineHeight 21
@interface UCImageGalleryDetail (Private)
- (void)setScrollViewContentSize;
- (void)createPhotoViewsCache;
- (void)scrollToIndex:(NSInteger)index;
- (void)loadPhoto:(NSInteger)index;
- (void)unloadPhoto:(NSInteger)index;
- (CGRect)frameForPageAtIndex:(NSUInteger)index;
- (void)setTitleWithCurrentPhotoIndex;
- (void)setCaptionWithCurrentPhotoIndex;
- (UILabel *)newLabel;
@end
#pragma mark -
@interface UCImageGalleryDetail (ActionHandlers)
- (void)closeView:(id)sender;
@end
#pragma mark -
@implementation UCImageGalleryDetail
#pragma mark - Init & dealloc
- (id)init {
return [self initWithFrame:CGRectZero];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_dataSource = nil;
_scrollView = [ [UIScrollView alloc] initWithFrame:frame];
[_scrollView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[_scrollView setDelegate:self];
[_scrollView setBackgroundColor:[UIColor blackColor]];
[_scrollView setAutoresizesSubviews:YES];
[_scrollView setPagingEnabled:YES];
[_scrollView setShowsVerticalScrollIndicator:NO];
[_scrollView setShowsHorizontalScrollIndicator:NO];
[self addSubview:_scrollView];
GXTheme *theme = [GXThemeHelper currentTheme];
_titleView = [self newLabel];
[_titleView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[_titleView setNumberOfLines:1];
[_titleView applyThemeClass:[theme themeClassAttributeTitle]];
[self addSubview:_titleView];
_captionView = [self newLabel];
[_captionView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
[_captionView setNumberOfLines:2];
[_captionView applyThemeClass:[theme themeClassAttributeSubtitle]];
[self addSubview:_captionView];
_closeButton = [ [UIButton buttonWithType:UIButtonTypeCustom] retain];
[_closeButton setImage:KTLoadImageFromBundle(@"closeIcon.png") forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(closeView:) forControlEvents:UIControlEventTouchUpInside];
[_closeButton setFrame:CGRectMake(frame.size.width - kCloseButtonWidth,
0,
kCloseButtonWidth,
kCloseButtonHeight)
];
[_closeButton setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
[self addSubview:_closeButton];
}
return self;
}
- (UILabel *)newLabel {
UILabel *label = [ [UILabel alloc] initWithFrame:CGRectZero];
[label setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f]];
[label setTextColor:[UIColor whiteColor]];
[label setTextAlignment:UITextAlignmentCenter];
return label;
}
- (void)dealloc {
[_scrollView release], _scrollView = nil;
[_closeButton release], _closeButton = nil;
[_titleView release], _titleView = nil;
[_captionView release], _captionView = nil;
[_photoViews release], _photoViews = nil;
[super dealloc];
}
#pragma mark - Properties
@synthesize dataSource = _dataSource;
- (void)setDataSource:(id<UCImageGalleryDataSource>)dataSource {
_dataSource = dataSource;
[self createPhotoViewsCache];
}
@synthesize currentIndex = _currentIndex;
- (void)setCurrentIndex:(NSUInteger)index {
_currentIndex = index;
[self loadPhoto:index];
[self loadPhoto:index + 1];
[self loadPhoto:index - 1];
[self unloadPhoto:index + 2];
[self unloadPhoto:index - 2];
[self setTitleWithCurrentPhotoIndex];
[self setCaptionWithCurrentPhotoIndex];
}
@synthesize delegate = _delegate;
#pragma mark - Public
- (void)scrollToCurrentIndex {
[self setScrollViewContentSize];
[self scrollToIndex:_currentIndex];
}
#pragma mark - UIView
- (void)layoutSubviews {
[super layoutSubviews];
[_scrollView setDelegate:nil]; // don't want the rotation to change the current page
CGRect bounds = self.bounds;
for (int index = 0; index < [_photoViews count]; index++) {
id item = [_photoViews objectAtIndex:index];
if ([item isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)item;
CGRect viewFrame = CGRectMake(index * bounds.size.width,
0,
bounds.size.width,
bounds.size.height);
[view setFrame:viewFrame];
}
}
[_scrollView setDelegate:self];
}
- (void)setFrame:(CGRect)frame {
[_scrollView setDelegate:nil]; // don't want the rotation to change the current page
[super setFrame:frame];
if (!CGSizeEqualToSize(CGSizeZero, frame.size)) {
for (int index = 0; index < [_photoViews count]; index++) {
id item = [_photoViews objectAtIndex:index];
if ([item isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)item;
CGRect viewFrame = CGRectMake(index * frame.size.width,
0,
frame.size.width,
frame.size.height);
[view setFrame:viewFrame];
}
}
[self scrollToCurrentIndex];
}
[_scrollView setDelegate:self];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = scrollView.frame.size.width;
float fractionalPage = scrollView.contentOffset.x / pageWidth;
NSInteger page = floor(fractionalPage);
if (page < 0) {
page = 0;
}
if (page != _currentIndex) {
[self setCurrentIndex:page];
}
}
#pragma mark - KTPhotoViewTouchDelegate
- (void)photoViewDidReceiveTouch:(KTPhotoView *)photoView {
[_delegate ucimageGalleryDetail:self didTapImageAtIndex:photoView.index];
}
#pragma mark - Private
- (void)setScrollViewContentSize {
NSInteger pageCount = [_dataSource count];
if (pageCount == 0) {
pageCount = 1;
}
CGSize size = CGSizeMake(_scrollView.frame.size.width * pageCount,
_scrollView.frame.size.height / 2); // Cut in half to prevent horizontal scrolling.
[_scrollView setContentSize:size];
}
- (void)createPhotoViewsCache {
if (_photoViews) {
[_photoViews release];
}
NSUInteger photoCount = [_dataSource count];
_photoViews = [ [NSMutableArray alloc] initWithCapacity:photoCount];
for (int i=0; i < photoCount; i++) {
[_photoViews addObject:[NSNull null]];
}
}
- (void)scrollToIndex:(NSInteger)index {
CGRect frame = _scrollView.frame;
frame.origin.x = frame.size.width * index;
frame.origin.y = 0;
[_scrollView scrollRectToVisible:frame animated:NO];
}
- (void)loadPhoto:(NSInteger)index {
if (index < 0 || index >= [_dataSource count]) {
return;
}
if (!_photoViews) {
[self createPhotoViewsCache];
}
id currentPhotoView = [_photoViews objectAtIndex:index];
if (NO == [currentPhotoView isKindOfClass:[KTPhotoView class]]) {
// Load the photo view.
CGRect frame = [self frameForPageAtIndex:index];
KTPhotoView *photoView = [ [KTPhotoView alloc] initWithFrame:frame];
[photoView setIndex:index];
[photoView setBackgroundColor:[UIColor clearColor]];
// Set the photo image.
if (index < [_dataSource count]) {
NSURL *url = [_dataSource photoURLAtIndex:index];
if ([url isKindOfClass:[NSNull class]]) {
[photoView setImage:[GXUtilities placeHolderImage]];
}
else {
[photoView setImageWithURL:url placeholderImage:[GXUtilities placeHolderImage]];
}
}
[_scrollView addSubview:photoView];
[_photoViews replaceObjectAtIndex:index withObject:photoView];
[photoView release];
} else {
// Turn off zooming.
[currentPhotoView turnOffZoom];
}
}
- (void)unloadPhoto:(NSInteger)index {
if (index < 0 || index >= [_dataSource count]) {
return;
}
id currentPhotoView = [_photoViews objectAtIndex:index];
if ([currentPhotoView isKindOfClass:[KTPhotoView class]]) {
[currentPhotoView removeFromSuperview];
[_photoViews replaceObjectAtIndex:index withObject:[NSNull null]];
}
}
- (CGRect)frameForPageAtIndex:(NSUInteger)index {
CGRect bounds = [_scrollView bounds];
CGRect pageFrame = bounds;
pageFrame.origin.x = bounds.size.width * index;
return pageFrame;
}
- (void)setTitleWithCurrentPhotoIndex {
NSString *formatString = NSLocalizedString(@"%1$i of %2$i", @"Picture X out of Y total.");
NSString *title = [_dataSource titleAtIndex:_currentIndex];
title = title ? : [NSString stringWithFormat:formatString, _currentIndex + 1, [_dataSource count], nil];
CGRect frame = self.bounds;
[_titleView setFrame:CGRectMake(0, 0, frame.size.width, kDefaultLineHeight)];
[_titleView setText:title];
}
- (void) setCaptionWithCurrentPhotoIndex {
NSString *caption = [_dataSource captionAtIndex:_currentIndex];
if (caption) {
CGRect frame = self.bounds;
CGFloat maxHeight = [_captionView numberOfLines] * kDefaultLineHeight + kCaptionPadding * 2;
CGSize maximumSize = CGSizeMake(frame.size.width, maxHeight);
UIFont *font = _captionView.font;
CGSize lSize = [caption sizeWithFont:font constrainedToSize:maximumSize];
lSize.width = frame.size.width;
lSize.height += kCaptionPadding * 2;
if (lSize.height > maxHeight) {
lSize.height = maxHeight;
}
CGFloat toolbarOriginY = frame.size.height;
[_captionView setFrame:CGRectMake(0,
toolbarOriginY - lSize.height,
frame.size.width,
lSize.height
)
];
[_captionView setText:caption];
}
}
#pragma mark - ActionHandlers
- (void)closeView:(id)sender {
if (_delegate) {
[_delegate ucimageGalleryDetailDidTapCloseButton:self];
}
else {
[self removeFromSuperview];
}
// unload all photos in cache
for (int index = 0; index < [_dataSource count]; index++) {
[self unloadPhoto:index];
}
}
@end