MyImagePicker展示瞭如何調用系統Photo和Album,並在自定義的UI中進行瀏覽,而這個也是很大衆化的需求。
先看看這個例子的使用流程:
對於這個Sample,我主要關注兩個關鍵點:
- 調用系統Photo和Album
- UI組件的嵌套和組合
IOS提供了類ALAssetsLibrary來取得Photo下面的資源(photo, album, video等),它的主要調用方式是遍歷和block回調:
NSUInteger groupTypes = ALAssetsGroupAlbum | ALAssetsGroupEvent | ALAssetsGroupFaces;
[assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:listGroupBlock failureBlock:failureBlock];
以上代碼就是要遍歷ALAssetsGroupAlbum | ALAssetsGroupEvent | ALAssetsGroupFaces這三種資源,並在遍歷過程中回調listGroupBlock和failureBlock這兩個block,下面看看這兩個block的實現:
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOL *stop) {
if (group) {
[groups addObject:group];
} else {
[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error) {
AssetsDataIsInaccessibleViewController *assetsDataInaccessibleViewController = [[AssetsDataIsInaccessibleViewController alloc] initWithNibName:@"AssetsDataIsInaccessibleViewController" bundle:nil];
NSString *errorMessage = nil;
switch ([error code]) {
case ALAssetsLibraryAccessUserDeniedError:
case ALAssetsLibraryAccessGloballyDeniedError:
errorMessage = @"The user has declined access to it.";
break;
default:
errorMessage = @"Reason unknown.";
break;
}
assetsDataInaccessibleViewController.explanation = errorMessage;
[self presentModalViewController:assetsDataInaccessibleViewController animated:NO];
[assetsDataInaccessibleViewController release];
};
邏輯很簡單,就是在遍歷過程中把資源放入groups數組並刷新tableview。
UI組件的嵌套和組合
本例子的UI由各種UI組件嵌套組合而成,而這也體現了IOS標準化和定製化有效結合。首先看看上圖中間的page,此page是展示某個album下所有photos,每一行展示4個photo縮微圖,點擊某個縮微圖能調轉到下個page,本例子採用的是tableview嵌套自定義的tableViewCell,並在此cell裏嵌套四個自定義的ImageView。代碼如下所示:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
AlbumContentsTableViewCell *cell = (AlbumContentsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"AlbumContentsTableViewCell" owner:self options:nil];
cell = tmpCell;
tmpCell = nil;
}
cell.rowNumber = indexPath.row;
cell.selectionDelegate = self;
// Configure the cell...
NSUInteger firstPhotoInCell = indexPath.row * 4;
NSUInteger lastPhotoInCell = firstPhotoInCell + 4;
if (assets.count <= firstPhotoInCell) {
NSLog(@"We are out of range, asking to start with photo %d but we only have %d", firstPhotoInCell, assets.count);
return nil;
}
NSUInteger currentPhotoIndex = 0;
NSUInteger lastPhotoIndex = MIN(lastPhotoInCell, assets.count);
for ( ; firstPhotoInCell + currentPhotoIndex < lastPhotoIndex ; currentPhotoIndex++) {
ALAsset *asset = [assets objectAtIndex:firstPhotoInCell + currentPhotoIndex];
CGImageRef thumbnailImageRef = [asset thumbnail];
UIImage *thumbnail = [UIImage imageWithCGImage:thumbnailImageRef];
switch (currentPhotoIndex) {
case 0:
[cell photo1].image = thumbnail;
break;
case 1:
[cell photo2].image = thumbnail;
break;
case 2:
[cell photo3].image = thumbnail;
break;
case 3:
[cell photo4].image = thumbnail;
break;
default:
break;
}
}
return cell;
}
在上圖最右邊的那個page中,展示某個photo,最外層是個UIScollView,此view再嵌套一個自定義的imageView,在自定義的imageview中實現多點觸控等功能。代碼如下所示:
- (void)viewDidLoad {
self.title = @"Photo";
UIScrollView *imageScrollView = (UIScrollView *)self.view;
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
ALAssetRepresentation *assetRepresentation = [asset defaultRepresentation];
UIImage *fullScreenImage = [UIImage imageWithCGImage:[assetRepresentation fullScreenImage] scale:[assetRepresentation scale] orientation:(UIImageOrientation)[assetRepresentation orientation]];
// add touch-sensitive image view to the scroll view
TapDetectingImageView *imageView = [[TapDetectingImageView alloc] initWithImage:fullScreenImage];
[imageView setDelegate:self];
[imageView setTag:ZOOM_VIEW_TAG];
[imageScrollView setContentSize:[imageView frame].size];
[imageScrollView addSubview:imageView];
[imageView release];
// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = [imageScrollView frame].size.width / [imageView frame].size.width;
[imageScrollView setMinimumZoomScale:minimumScale];
[imageScrollView zoomToRect:CGRectMake(0.0, 0.0, imageView.frame.size.width, imageView.frame.size.height) animated:NO];
}
所以從這個例子中能學習到如何靈活地嵌套和組合多種UI組件,並把事件偵聽delegate出來。