ios mwphotobrowserr怎么用

当前访客身份:游客 [
当前位置:
mwphotobrowser
标签代码列表(0)
当前标签下
暂无代码!
开源从代码分享开始
TOP40活跃贡献者
红薯[1418]
hacxlly...[6]
piggy_x...[4]
panqian...[2]
ym1623...[1]
flipclo...[4]
Python...[4]
zakured...[9]
Python...[9]
月亮上好冷[4]
skyway1...[1]
JavaScr...[1]
丛俊龙[11]
SwordHu...[2]
黄昏武士[1]
x565178...[3]
Python...[3]
webx32...[1]
JavaScr...[1]
JavaScr...[11]
skyline...[1]
JavaScr...[1]
simanan...[12]
JonyZha...[4]
JavaScr...[3]
Csharp能...[1]
茗迹周[11]
mikeszh...[5]
Python...[2]
jockcho...[2]
jUnion...[8]
bravegu...[1]
本月热门代码语言TOP5关于MWPhotoBrowser对6 plus的适配问题
[问题点数:40分]
关于MWPhotoBrowser对6 plus的适配问题
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。当前访客身份:游客 [
当前位置:
mwphotobrowser
标签代码列表(0)
当前标签下
暂无代码!
开源从代码分享开始
TOP40活跃贡献者
sidawan...[36]
Huang_H...[29]
wangsid...[19]
araralo...[42]
yanyahu...[18]
小胖的傷[20]
gongzhq...[17]
Google ...[17]
Python...[19]
会飞的章鱼[15]
郑岸以[18]
Python...[16]
波仔糕[25]
清风婷[10]
岑泉鄅[12]
Scharf...[9]
tentent...[6]
Python...[7]
深沉500[23]
誓言也在笑[8]
djh122...[7]
王维来[18]
沐浴星光[5]
魔神翼[10]
songlee...[6]
daleshe...[8]
xiaohua...[5]
Sean_M...[4]
谦谦君子[5]
优雅先生[136]
JavaScr...[41]
逍遥天下...[4]
Apprent...[5]
奔跑的蛮牛[4]
DsonKin...[11]
Google ...[25]
荔枝壳[17]
smiths...[16]
兰穆达[51]
本月热门代码语言TOP5FB-Gallery-master
FB Gallery
MWPhotoBrowser
MBProgressHUD
README.mdown
SDWebImage
MWPhotoBrowser.bundle
Checkmark.png
Checkmark@2x.png
UIBarButtonItemArrowLeft.png
UIBarButtonItemArrowLeft@2x.png
UIBarButtonItemArrowRight.png
UIBarButtonItemArrowRight@2x.png
MWPhotoBrowser.xcodeproj
xcuserdata
ericwang.xcuserdatad
MWPhotoBrowser.xcscheme
xcschememanagement.plist
seitk.xcuserdatad
MWPhotoBrowser.xcscheme
xcschememanagement.plist
project.pbxproj
MWPhotoBrowser-Prefix.pch
FB Gallery Example
FB Gallery Example
PYTimelineViewController.xib
InfoPlist.strings
Default-568h@2x.png
Default.png
Default@2x.png
FB Gallery Example-Info.plist
FB Gallery Example-Prefix.pch
FB Gallery Example.xcodeproj
project.xcworkspace
xcuserdata
ericwang.xcuserdatad
UserInterfaceState.xcuserstate
seitk.xcuserdatad
WorkspaceSettings.xcsettings
contents.xcworkspacedata
xcuserdata
ericwang.xcuserdatad
FB Gallery Example.xcscheme
xcschememanagement.plist
seitk.xcuserdatad
xcdebugger
Breakpoints.xcbkptlist
FB Gallery Example.xcscheme
xcschememanagement.plist
project.pbxproj
FB Gallery Example with Storyboard
FB Gallery Example with Storyboard
InfoPlist.strings
MainStoryboard.storyboard
Default-568h@2x.png
Default.png
Default@2x.png
FB Gallery Example with Storyboard-Info.plist
FB Gallery Example with Storyboard-Prefix.pch
FB Gallery Example with Storyboard.xcodeproj
project.xcworkspace
contents.xcworkspacedata
xcuserdata
seitk.xcuserdatad
FB Gallery Example with Storyboard.xcscheme
xcschememanagement.plist
project.pbxproj
.gitignore
FB-Gallery-master
FB Gallery
MWPhotoBrowser
MBProgressHUD
._README.mdown
SDWebImage
._README.md
._MBProgressHUD
._SDWebImage
MWPhotoBrowser.bundle
._Checkmark.png
._Checkmark@2x.png
._UIBarButtonItemArrowLeft.png
._UIBarButtonItemArrowLeft@2x.png
._UIBarButtonItemArrowRight.png
._UIBarButtonItemArrowRight@2x.png
MWPhotoBrowser.xcodeproj
xcuserdata
seitk.xcuserdatad
._MWPhotoBrowser.xcscheme
._xcschememanagement.plist
._xcschemes
._seitk.xcuserdatad
._project.pbxproj
._xcuserdata
._Libraries
._MWPhotoBrowser-Prefix.pch
._MWPhotoBrowser.bundle
._MWPhotoBrowser.xcodeproj
._MWPhotoBrowser
FB Gallery Example
FB Gallery Example
._PYTimelineViewController.xib
._InfoPlist.strings
._Default-568h@2x.png
._Default.png
._Default@2x.png
._en.lproj
._FB Gallery Example-Info.plist
._FB Gallery Example-Prefix.pch
FB Gallery Example.xcodeproj
project.xcworkspace
xcuserdata
seitk.xcuserdatad
._WorkspaceSettings.xcsettings
._seitk.xcuserdatad
._contents.xcworkspacedata
._xcuserdata
xcuserdata
seitk.xcuserdatad
xcdebugger
._Breakpoints.xcbkptlist
._FB Gallery Example.xcscheme
._xcschememanagement.plist
._xcdebugger
._xcschemes
._seitk.xcuserdatad
._project.xcworkspace
._xcuserdata
._.DS_Store
._FB Gallery Example
FB Gallery Example with Storyboard
FB Gallery Example with Storyboard
._InfoPlist.strings
._MainStoryboard.storyboard
._Default-568h@2x.png
._Default.png
._Default@2x.png
._en.lproj
._FB Gallery Example with Storyboard-Info.plist
._FB Gallery Example with Storyboard-Prefix.pch
FB Gallery Example with Storyboard.xcodeproj
project.xcworkspace
._contents.xcworkspacedata
xcuserdata
seitk.xcuserdatad
._FB Gallery Example with Storyboard.xcscheme
._xcschememanagement.plist
._xcschemes
._seitk.xcuserdatad
._project.pbxproj
._project.xcworkspace
._xcuserdata
._FB Gallery Example with Storyboard
._FB Gallery Example with Storyboard.xcodeproj
._.DS_Store
._.gitignore
._FB Gallery
._FB Gallery Example
._FB Gallery Example with Storyboard
._README.md
._Resource
._FB-Gallery-master
MWPhotoBrowser.m
MWPhotoBrowser
Created by Michael Waterfall on 14/10/2010.
Copyright 2010 d3i. All rights reserved.
#import &QuartzCore/QuartzCore.h&
#import &MWPhotoBrowser.h&
#import &MWZoomingScrollView.h&
#import &MBProgressHUD.h&
#import &SDImageCache.h&
#import &UIView+viewController.h&
#define SYSTEM_VERSION_EQUAL_TO(v)
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)
([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
#define PADDING
#define PAGE_INDEX_TAG_OFFSET
#define PAGE_INDEX(page)
([(page) tag] - PAGE_INDEX_TAG_OFFSET)
// FB Photo Browser
#import &QuartzCore/QuartzCore.h&
#define kAnimationDuration 0.3
#define kBGpushBackRatio 0.92
#define tagScreenshot 1000
// Private
@interface MWPhotoBrowser () {
id &MWPhotoBrowserDelegate& _
NSUInteger _photoC
NSMutableArray *_
NSArray *_depreciatedPhotoD // Depreciated
UIScrollView *_pagingScrollV
NSMutableSet *_visiblePages, *_recycledP
NSUInteger _currentPageI
NSUInteger _pageIndexBeforeR
// Navigation & controls
UIToolbar *_
NSTimer *_controlVisibilityT
UIBarButtonItem *_previousButton, *_nextButton, *_actionB
UIActionSheet *_actionsS
MBProgressHUD *_progressHUD;
// Appearance
UIImage *_navigationBarBackgroundImageDefault,
*_navigationBarBackgroundImageLandscapeP
UIColor *_previousNavBarTintC
UIBarStyle _previousNavBarS
UIStatusBarStyle _previousStatusBarS
UIBarButtonItem *_previousViewControllerBackB
BOOL _displayActionB
BOOL _performingL
BOOL _viewIsA // active as in it's in the view heirarchy
BOOL _didSavePreviousStateOfNavB
// Private Properties
@property (nonatomic, retain) UIColor *previousNavBarTintC
@property (nonatomic, retain) UIBarButtonItem *previousViewControllerBackB
@property (nonatomic, retain) UIImage *navigationBarBackgroundImageDefault, *navigationBarBackgroundImageLandscapeP
@property (nonatomic, retain) UIActionSheet *actionsS
@property (nonatomic, retain) MBProgressHUD *progressHUD;
// Private Methods
- (void)performL
// Nav Bar Appearance
- (void)setNavBarAppearance:(BOOL)
- (void)storePreviousNavBarA
- (void)restorePreviousNavBarAppearance:(BOOL)
- (void)tileP
- (BOOL)isDisplayingPageForIndex:(NSUInteger)
- (MWZoomingScrollView *)pageDisplayedAtIndex:(NSUInteger)
- (MWZoomingScrollView *)pageDisplayingPhoto:(id&MWPhoto&)
- (MWZoomingScrollView *)dequeueRecycledP
- (void)configurePage:(MWZoomingScrollView *)page forIndex:(NSUInteger)
- (void)didStartViewingPageAtIndex:(NSUInteger)
- (CGRect)frameForPagingScrollV
- (CGRect)frameForPageAtIndex:(NSUInteger)
- (CGSize)contentSizeForPagingScrollV
- (CGPoint)contentOffsetForPageAtIndex:(NSUInteger)
- (CGRect)frameForToolbarAtOrientation:(UIInterfaceOrientation)
- (CGRect)frameForCaptionView:(MWCaptionView *)captionView atIndex:(NSUInteger)
// Navigation
- (void)updateN
- (void)jumpToPageAtIndex:(NSUInteger)
- (void)gotoPreviousP
- (void)gotoNextP
// Controls
- (void)cancelControlH
- (void)hideControlsAfterD
- (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated permanent:(BOOL)
- (void)toggleC
- (BOOL)areControlsH
- (NSUInteger)numberOfP
- (id&MWPhoto&)photoAtIndex:(NSUInteger)
- (UIImage *)imageForPhoto:(id&MWPhoto&)
- (void)loadAdjacentPhotosIfNecessary:(id&MWPhoto&)
- (void)releaseAllUnderlyingP
// Actions
- (void)saveP
- (void)copyP
- (void)emailP
// Handle depreciations and supress hide warnings
@interface UIApplication (DepreciationWarningSuppresion)
- (void)setStatusBarHidden:(BOOL)hidden animated:(BOOL)
// MWPhotoBrowser
@implementation MWPhotoBrowser
// Properties
@synthesize previousNavBarTintColor = _previousNavBarTintC
@synthesize navigationBarBackgroundImageDefault = _navigationBarBackgroundImageDefault,
navigationBarBackgroundImageLandscapePhone = _navigationBarBackgroundImageLandscapeP
@synthesize displayActionButton = _displayActionButton, actionsSheet = _actionsS
@synthesize progressHUD = _progressHUD;
@synthesize previousViewControllerBackButton = _previousViewControllerBackB
// FB PhotoBrowser
@synthesize screenshot, entranceI
@synthesize screenshotView, entranceImgM
#pragma mark - NSObject
- (id)init {
if ((self = [super init])) {
// Defaults
self.wantsFullScreenLayout = YES;
self.hidesBottomBarWhenPushed = YES;
_photoCount = NSNotF
_currentPageIndex = 0;
_performingLayout = NO; // Reset on view did appear
_rotating = NO;
_viewIsActive = NO;
_visiblePages = [[NSMutableSet alloc] init];
_recycledPages = [[NSMutableSet alloc] init];
_photos = [[NSMutableArray alloc] init];
_displayActionButton = NO;
_didSavePreviousStateOfNavBar = NO;
// Listen for MWPhoto notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMWPhotoLoadingDidEndNotification:)
name:MWPHOTO_LOADING_DID_END_NOTIFICATION
object:nil];
- (id)initWithDelegate:(id &MWPhotoBrowserDelegate&)delegate {
if ((self = [self init])) {
_delegate =
- (id)initWithPhotos:(NSArray *)photosArray {
if ((self = [self init])) {
_depreciatedPhotoData = [photosArray retain];
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_previousNavBarTintColor release];
[_navigationBarBackgroundImageDefault release];
[_navigationBarBackgroundImageLandscapePhone release];
[_previousViewControllerBackButton release];
[_pagingScrollView release];
[_visiblePages release];
[_recycledPages release];
[_toolbar release];
[_previousButton release];
[_nextButton release];
[_actionButton release];
[_depreciatedPhotoData release];
[self releaseAllUnderlyingPhotos];
[[SDImageCache sharedImageCache] clearMemory]; // clear memory
[_photos release];
[_progressHUD release];
[super dealloc];
- (void)releaseAllUnderlyingPhotos {
for (id p in _photos) { if (p != [NSNull null]) [p unloadUnderlyingImage]; } // Release photos
- (void)didReceiveMemoryWarning {
// Release any cached data, images, etc that aren't in use.
[self releaseAllUnderlyingPhotos];
[_recycledPages removeAllObjects];
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
#pragma mark - View Loading
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
self.view.backgroundColor = [UIColor blackColor];
// Setup paging scrolling view
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
_pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame];
_pagingScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleH
_pagingScrollView.pagingEnabled = YES;
_pagingScrollView.delegate =
_pagingScrollView.showsHorizontalScrollIndicator = NO;
_pagingScrollView.showsVerticalScrollIndicator = NO;
_pagingScrollView.backgroundColor = [UIColor clearColor];
_pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
[self.view addSubview:_pagingScrollView];
// Toolbar
_toolbar = [[UIToolbar alloc] initWithFrame:[self frameForToolbarAtOrientation:self.interfaceOrientation]];
_toolbar.tintColor =
if ([[UIToolbar class] respondsToSelector:@selector(appearance)]) {
[_toolbar setBackgroundImage:nil forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[_toolbar setBackgroundImage:nil forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsLandscapePhone];
_toolbar.barStyle = UIBarStyleBlackT
_toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleW
_toolbar.hidden = YES;
// Toolbar Items
_previousButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@&MWPhotoBrowser.bundle/images/UIBarButtonItemArrowLeft.png&] style:UIBarButtonItemStylePlain target:self action:@selector(gotoPreviousPage)];
_nextButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@&MWPhotoBrowser.bundle/images/UIBarButtonItemArrowRight.png&] style:UIBarButtonItemStylePlain target:self action:@selector(gotoNextPage)];
_actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionButtonPressed:)];
// FB Photo Browser
[_pagingScrollView setHidden:YES];
// Offset for screenshot without status bar
screenshotView = [[UIView alloc] initWithFrame:screenshot.frame];
[screenshotView shiftViewPositionY:20];
[screenshot setTag:tagScreenshot];
entranceImgMask = [[UIView alloc] initWithFrame:CGRectMake(0, 0, entranceImg.frame.size.width, entranceImg.frame.size.height)];
entranceImgMask.backgroundColor = [UIColor blackColor];
[self.entranceImg addSubview:entranceImgMask];
[self.screenshotView addSubview:screenshot];
[self.view insertSubview:screenshotView belowSubview:_pagingScrollView];
[self.view insertSubview:entranceImg aboveSubview:screenshot];
[self startAnimation];
[self reloadData];
[super viewDidLoad];
- (void) startAnimation
// Calculate new image size and position
float scaleRatio = self.view.frame.size.width / entranceImg.image.size.
float newHeight = scaleRatio * entranceImg.image.size.
float originCenterY = entranceImg.center.y;
[entranceImg setHidden:YES];
UIImageView *eImgCopy = [[UIImageView alloc] initWithFrame:entranceImg.frame];
eImgCopy.image = entranceImg.
eImgCopy.contentMode = UIViewContentModeScaleAspectF
[self.view addSubview:eImgCopy];
[UIView animateWithDuration:kAnimationDuration delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
screenshot.alpha = 0.0;
[self pushDownBgView:YES];
[eImgCopy setContentMode:UIViewContentModeScaleAspectFill];
[eImgCopy setFrame:CGRectMake(0, self.view.frame.size.height / 2 - newHeight / 2, self.view.frame.size.width, newHeight)];
} completion:^(BOOL finished) {
// Bounce animation
[self bounceView:eImgCopy distance:(originCenterY - eImgCopy.center.y) completent:^{
[eImgCopy removeFromSuperview];
[_pagingScrollView setHidden:NO];
// Add original image to screenshot
[entranceImg shiftViewPositionY:-20];
[self.screenshotView addSubview:entranceImg];
- (void) exitBrowserView:(UIImageView *)currentImg
// Clone current image and perform animation
UIImageView *tempImg = [[UIImageView alloc] initWithFrame:currentImg.frame];
tempImg.contentMode = UIViewContentModeScaleAspectF
tempImg.image = currentImg.
tempImg.clipsToBounds = YES;
[_pagingScrollView setHidden:YES];
currentImg.userInteractionEnabled = NO;
[self.view addSubview:tempImg];
CGRect tempImgFrame = entranceImg.
screenshotView.alpha = 1.0;
CGRect outScreenFrame = tempImg.
outScreenFrame.origin.y = tempImg.center.y & self.view.frame.size.height / 2 ? self.view.frame.size.height + outScreenFrame.size.height : -outScreenFrame.size.
if (currentImg.image != entranceImg.image)
tempImgFrame.origin.y += 20;
[UIView animateWithDuration:kAnimationDuration delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
if (currentImg.image == entranceImg.image)
[tempImg setFrame:tempImgFrame];
[tempImg setFrame:outScreenFrame];
} completion:^(BOOL finished) {
// Back to timeline view when animation ended
[self dismissViewControllerAnimated:NO completion:nil];
[self pushDownBgView:NO];
#pragma marks - Animations
- (void) pushDownBgView:(bool)push
CABasicAnimation *
animation=[CABasicAnimation animationWithKeyPath:@&transform.scale&];
animation.delegate =
animation.duration = kAnimationD
animation.repeatCount = 0;
animation.removedOnCompletion = FALSE;
animation.fillMode = kCAFillModeF
animation.fromValue = push ? [NSNumber numberWithFloat:1] : [NSNumber numberWithFloat:kBGpushBackRatio];
animation.toValue = push ? [NSNumber numberWithFloat:kBGpushBackRatio] : [NSNumber numberWithFloat:1.0];
[screenshotView.layer addAnimation:animation forKey:nil];
- (void) setTransparentForScreenshot:(float)alpha
self.screenshot.alpha =
self.entranceImgMask.alpha = 1 -
- (void) bounceView:(UIView *)view distance:(float)distance completent:(void (^)(void))completion
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
completion();
// Bound photo based on distance
CABasicAnimation *
animation=[CABasicAnimation animationWithKeyPath:@&transform.translation.y&];
animation.delegate =
animation.duration = kAnimationDuration / 2
animation.repeatCount = 0;
animation.removedOnCompletion = YES;
animation.fillMode = kCAFillModeF
animation.autoreverses = YES;
animation.fromValue = [NSNumber numberWithFloat:0.0];
animation.toValue = [NSNumber numberWithFloat:distance * -0.02];
[view.layer addAnimation:animation forKey:@&transform.translation.y&];
} [CATransaction commit];
// Photo Browser ended
- (void)performLayout {
_performingLayout = YES;
NSUInteger numberOfPhotos = [self numberOfPhotos];
// Setup pages
[_visiblePages removeAllObjects];
[_recycledPages removeAllObjects];
// Toolbar
if (numberOfPhotos & 1 || _displayActionButton) {
[self.view addSubview:_toolbar];
[_toolbar removeFromSuperview];
// Toolbar items & navigation
UIBarButtonItem *fixedLeftSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil] autorelease];
fixedLeftSpace.width = 32; // To balance action button
UIBarButtonItem *flexSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil] autorelease];
NSMutableArray *items = [[NSMutableArray alloc] init];
if (_displayActionButton) [items addObject:fixedLeftSpace];
[items addObject:flexSpace];
if (numberOfPhotos & 1) [items addObject:_previousButton];
[items addObject:flexSpace];
if (numberOfPhotos & 1) [items addObject:_nextButton];
[items addObject:flexSpace];
if (_displayActionButton) [items addObject:_actionButton];
[_toolbar setItems:items];
[items release];
[self updateNavigation];
// Navigation buttons
if ([self.navigationController.viewControllers objectAtIndex:0] == self) {
// We're first on stack so show done button
UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@&Done&, nil) style:UIBarButtonItemStylePlain target:self action:@selector(doneButtonPressed:)] autorelease];
// Set appearance
if ([UIBarButtonItem respondsToSelector:@selector(appearance)]) {
[doneButton setBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[doneButton setBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
[doneButton setBackgroundImage:nil forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[doneButton setBackgroundImage:nil forState:UIControlStateHighlighted barMetrics:UIBarMetricsLandscapePhone];
[doneButton setTitleTextAttributes:[NSDictionary dictionary] forState:UIControlStateNormal];
[doneButton setTitleTextAttributes:[NSDictionary dictionary] forState:UIControlStateHighlighted];
self.navigationItem.rightBarButtonItem = doneB
// We're not first so show back button
UIViewController *previousViewController = [self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2];
NSString *backButtonTitle = previousViewController.navigationItem.backBarButtonItem ? previousViewController.navigationItem.backBarButtonItem.title : previousViewController.
UIBarButtonItem *newBackButton = [[[UIBarButtonItem alloc] initWithTitle:backButtonTitle style:UIBarButtonItemStylePlain target:nil action:nil] autorelease];
// Appearance
if ([UIBarButtonItem respondsToSelector:@selector(appearance)]) {
[newBackButton setBackButtonBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[newBackButton setBackButtonBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone];
[newBackButton setBackButtonBackgroundImage:nil forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[newBackButton setBackButtonBackgroundImage:nil forState:UIControlStateHighlighted barMetrics:UIBarMetricsLandscapePhone];
[newBackButton setTitleTextAttributes:[NSDictionary dictionary] forState:UIControlStateNormal];
[newBackButton setTitleTextAttributes:[NSDictionary dictionary] forState:UIControlStateHighlighted];
self.previousViewControllerBackButton = previousViewController.navigationItem.backBarButtonI // remember previous
previousViewController.navigationItem.backBarButtonItem = newBackB
// Content offset
_pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:_currentPageIndex];
[self tilePages];
_performingLayout = NO;
// Release any retained subviews of the main view.
- (void)viewDidUnload {
_currentPageIndex = 0;
[_pagingScrollView release], _pagingScrollView =
[_visiblePages release], _visiblePages =
[_recycledPages release], _recycledPages =
[_toolbar release], _toolbar =
[_previousButton release], _previousButton =
[_nextButton release], _nextButton =
self.progressHUD =
[super viewDidUnload];
#pragma mark - Appearance
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Layout manually (iOS & 5)
if (SYSTEM_VERSION_LESS_THAN(@&5&)) [self viewWillLayoutSubviews];
// Status bar
if (self.wantsFullScreenLayout && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
_previousStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:animated];
// Navigation bar appearance
if (!_viewIsActive && [self.navigationController.viewControllers objectAtIndex:0] != self) {
[self storePreviousNavBarAppearance];
[self setNavBarAppearance:animated];
// Update UI
[self hideControlsAfterDelay];
- (void)viewWillDisappear:(BOOL)animated {
// Check that we're being popped for good
if ([self.navigationController.viewControllers objectAtIndex:0] != self &&
![self.navigationController.viewControllers containsObject:self]) {
_viewIsActive = NO;
// Bar state / appearance
[self restorePreviousNavBarAppearance:animated];
// Controls
[self.navigationController.navigationBar.layer removeAllAnimations]; // Stop all animations on nav bar
[NSObject cancelPreviousPerformRequestsWithTarget:self]; // Cancel any pending toggles from taps
[self setControlsHidden:NO animated:NO permanent:YES];
// Status bar
if (self.wantsFullScreenLayout && UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[[UIApplication sharedApplication] setStatusBarStyle:_previousStatusBarStyle animated:animated];
[super viewWillDisappear:animated];
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
_viewIsActive = YES;
#pragma mark - Nav Bar Appearance
- (void)setNavBarAppearance:(BOOL)animated {
self.navigationController.navigationBar.tintColor =
self.navigationController.navigationBar.barStyle = UIBarStyleBlackT
if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsLandscapePhone];
- (void)storePreviousNavBarAppearance {
_didSavePreviousStateOfNavBar = YES;
self.previousNavBarTintColor = self.navigationController.navigationBar.tintC
_previousNavBarStyle = self.navigationController.navigationBar.barS
if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
self.navigationBarBackgroundImageDefault = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
self.navigationBarBackgroundImageLandscapePhone = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsLandscapePhone];
- (void)restorePreviousNavBarAppearance:(BOOL)animated {
if (_didSavePreviousStateOfNavBar) {
self.navigationController.navigationBar.tintColor = _previousNavBarTintC
self.navigationController.navigationBar.barStyle = _previousNavBarS
if ([[UINavigationBar class] respondsToSelector:@selector(appearance)]) {
[self.navigationController.navigationBar setBackgroundImage:_navigationBarBackgroundImageDefault forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setBackgroundImage:_navigationBarBackgroundImageLandscapePhone forBarMetrics:UIBarMetricsLandscapePhone];
// Restore back button if we need to
if (_previousViewControllerBackButton) {
UIViewController *previousViewController = [self.navigationController topViewController]; // We've disappeared so previous is now top
previousViewController.navigationItem.backBarButtonItem = _previousViewControllerBackB
self.previousViewControllerBackButton =
#pragma mark - Layout
- (void)viewWillLayoutSubviews {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@&5&)) [super viewWillLayoutSubviews];
_performingLayout = YES;
// Toolbar
_toolbar.frame = [self frameForToolbarAtOrientation:self.interfaceOrientation];
// Remember index
NSUInteger indexPriorToLayout = _currentPageI
// Get paging scroll view frame to determine if anything needs changing
CGRect pagingScrollViewFrame = [self frameForPagingScrollView];
// Frame needs changing
_pagingScrollView.frame = pagingScrollViewF
// Recalculate contentSize based on current orientation
_pagingScrollView.contentSize = [self contentSizeForPagingScrollView];
// Adjust frames and configuration of each visible page
for (MWZoomingScrollView *page in _visiblePages) {
NSUInteger index = PAGE_INDEX(page);
page.frame = [self frameForPageAtIndex:index];
page.captionView.frame = [self frameForCaptionView:page.captionView atIndex:index];
[page setMaxMinZoomScalesForCurrentBounds];
// Adjust contentOffset to preserve page location based on values collected prior to location
_pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:indexPriorToLayout];
[self didStartViewingPageAtIndex:_currentPageIndex]; // initial
_currentPageIndex = indexPriorToL
_performingLayout = NO;
#pragma mark - Rotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// Remember page index before rotation
_pageIndexBeforeRotation = _currentPageI
_rotating = YES;
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// Perform layout
_currentPageIndex = _pageIndexBeforeR
// Layout manually (iOS & 5)
if (SYSTEM_VERSION_LESS_THAN(@&5&)) [self viewWillLayoutSubviews];
// Delay control holding
[self hideControlsAfterDelay];
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
_rotating = NO;
#pragma mark - Data
- (void)reloadData {
_photoCount = NSNotF
// Get data
NSUInteger numberOfPhotos = [self numberOfPhotos];
[self releaseAllUnderlyingPhotos];
[_photos removeAllObjects];
for (int i = 0; i & numberOfP i++) [_photos addObject:[NSNull null]];
[self performLayout];
if (SYSTEM_VERSION_LESS_THAN(@&5&)) [self viewWillLayoutSubviews];
else [self.view setNeedsLayout];
- (NSUInteger)numberOfPhotos {
if (_photoCount == NSNotFound) {
if ([_delegate respondsToSelector:@selector(numberOfPhotosInPhotoBrowser:)]) {
_photoCount = [_delegate numberOfPhotosInPhotoBrowser:self];
} else if (_depreciatedPhotoData) {
_photoCount = _depreciatedPhotoData.
if (_photoCount == NSNotFound) _photoCount = 0;
return _photoC
- (id&MWPhoto&)photoAtIndex:(NSUInteger)index {
id &MWPhoto& photo =
if (index & _photos.count) {
if ([_photos objectAtIndex:index] == [NSNull null]) {
if ([_delegate respondsToSelector:@selector(photoBrowser:photoAtIndex:)]) {
photo = [_delegate photoBrowser:self photoAtIndex:index];
} else if (_depreciatedPhotoData && index & _depreciatedPhotoData.count) {
photo = [_depreciatedPhotoData objectAtIndex:index];
if (photo) [_photos replaceObjectAtIndex:index withObject:photo];
photo = [_photos objectAtIndex:index];
- (MWCaptionView *)captionViewForPhotoAtIndex:(NSUInteger)index {
MWCaptionView *captionView =
if ([_delegate respondsToSelector:@selector(photoBrowser:captionViewForPhotoAtIndex:)]) {
captionView = [_delegate photoBrowser:self captionViewForPhotoAtIndex:index];
id &MWPhoto& photo = [self photoAtIndex:index];
if ([photo respondsToSelector:@selector(caption)]) {
if ([photo caption]) captionView = [[[MWCaptionView alloc] initWithPhoto:photo] autorelease];
captionView.alpha = [self areControlsHidden] ? 0 : 1; // Initial alpha
return captionV
- (UIImage *)imageForPhoto:(id&MWPhoto&)photo {
if (photo) {
// Get image or obtain in background
if ([photo underlyingImage]) {
return [photo underlyingImage];
[photo loadUnderlyingImageAndNotify];
- (void)loadAdjacentPhotosIfNecessary:(id&MWPhoto&)photo {
MWZoomingScrollView *page = [self pageDisplayingPhoto:photo];
if (page) {
// If page is current page then initiate loading of previous and next pages
NSUInteger pageIndex = PAGE_INDEX(page);
if (_currentPageIndex == pageIndex) {
if (pageIndex & 0) {
// Preload index - 1
id &MWPhoto& photo = [self photoAtIndex:pageIndex-1];
if (![photo underlyingImage]) {
[photo loadUnderlyingImageAndNotify];
MWLog(@&Pre-loading image at index %i&, pageIndex-1);
if (pageIndex & [self numberOfPhotos] - 1) {
// Preload index + 1
id &MWPhoto& photo = [self photoAtIndex:pageIndex+1];
if (![photo underlyingImage]) {
[photo loadUnderlyingImageAndNotify];
MWLog(@&Pre-loading image at index %i&, pageIndex+1);
#pragma mark - MWPhoto Loading Notification
- (void)handleMWPhotoLoadingDidEndNotification:(NSNotification *)notification {
id &MWPhoto& photo = [notification object];
MWZoomingScrollView *page = [self pageDisplayingPhoto:photo];
if (page) {
if ([photo underlyingImage]) {
// Successful load
[page displayImage];
[self loadAdjacentPhotosIfNecessary:photo];
// Failed to load
[page displayImageFailure];
#pragma mark - Paging
- (void)tilePages {
// Calculate which pages should be visible
// Ignore padding as paging bounces encroach on that
// and lead to false page loads
CGRect visibleBounds = _pagingScrollView.
int iFirstIndex = (int)floorf((CGRectGetMinX(visibleBounds)+PADDING*2) / CGRectGetWidth(visibleBounds));
int iLastIndex
= (int)floorf((CGRectGetMaxX(visibleBounds)-PADDING*2-1) / CGRectGetWidth(visibleBounds));
if (iFirstIndex & 0) iFirstIndex = 0;
if (iFirstIndex & [self numberOfPhotos] - 1) iFirstIndex = [self numberOfPhotos] - 1;
if (iLastIndex & 0) iLastIndex = 0;
if (iLastIndex & [self numberOfPhotos] - 1) iLastIndex = [self numberOfPhotos] - 1;
// Recycle no longer needed pages
NSInteger pageI
for (MWZoomingScrollView *page in _visiblePages) {
pageIndex = PAGE_INDEX(page);
if (pageIndex & (NSUInteger)iFirstIndex || pageIndex & (NSUInteger)iLastIndex) {
[_recycledPages addObject:page];
[page prepareForReuse];
[page removeFromSuperview];
MWLog(@&Removed page at index %i&, PAGE_INDEX(page));
[_visiblePages minusSet:_recycledPages];
while (_recycledPages.count & 2) // Only keep 2 recycled pages
[_recycledPages removeObject:[_recycledPages anyObject]];
// Add missing pages
for (NSUInteger index = (NSUInteger)iFirstI index &= (NSUInteger)iLastI index++) {
if (![self isDisplayingPageForIndex:index]) {
// Add new page
MWZoomingScrollView *page = [self dequeueRecycledPage];
if (!page) {
page = [[[MWZoomingScrollView alloc] initWithPhotoBrowser:self] autorelease];
[self configurePage:page forIndex:index];
[_visiblePages addObject:page];
[_pagingScrollView addSubview:page];
MWLog(@&Added page at index %i&, index);
// Add caption
MWCaptionView *captionView = [self captionViewForPhotoAtIndex:index];
captionView.frame = [self frameForCaptionView:captionView atIndex:index];
[_pagingScrollView addSubview:captionView];
page.captionView = captionV
- (BOOL)isDisplayingPageForIndex:(NSUInteger)index {
for (MWZoomingScrollView *page in _visiblePages)
if (PAGE_INDEX(page) == index) return YES;
return NO;
- (MWZoomingScrollView *)pageDisplayedAtIndex:(NSUInteger)index {
MWZoomingScrollView *thePage =
for (MWZoomingScrollView *page in _visiblePages) {
if (PAGE_INDEX(page) == index) {
return theP
- (MWZoomingScrollView *)pageDisplayingPhoto:(id&MWPhoto&)photo {
MWZoomingScrollView *thePage =
for (MWZoomingScrollView *page in _visiblePages) {
if (page.photo == photo) {
return theP
- (void)configurePage:(MWZoomingScrollView *)page forIndex:(NSUInteger)index {
page.frame = [self frameForPageAtIndex:index];
page.tag = PAGE_INDEX_TAG_OFFSET +
page.photo = [self photoAtIndex:index];
- (MWZoomingScrollView *)dequeueRecycledPage {
MWZoomingScrollView *page = [_recycledPages anyObject];
if (page) {
[[page retain] autorelease];
[_recycledPages removeObject:page];
// Handle page changes
- (void)didStartViewingPageAtIndex:(NSUInteger)index {
// Release images further away than +/-1
if (index & 0) {
// Release anything & index - 1
for (i = 0; i & index-1; i++) {
id photo = [_photos objectAtIndex:i];
if (photo != [NSNull null]) {
[photo unloadUnderlyingImage];
[_photos replaceObjectAtIndex:i withObject:[NSNull null]];
MWLog(@&Released underlying image at index %i&, i);
if (index & [self numberOfPhotos] - 1) {
// Release anything & index + 1
for (i = index + 2; i & _photos. i++) {
id photo = [_photos objectAtIndex:i];
if (photo != [NSNull null]) {
[photo unloadUnderlyingImage];
[_photos replaceObjectAtIndex:i withObject:[NSNull null]];
MWLog(@&Released underlying image at index %i&, i);
// Load adjacent images if needed and the photo is already
// loaded. Also called after photo has been loaded in background
id &MWPhoto& currentPhoto = [self photoAtIndex:index];
if ([currentPhoto underlyingImage]) {
// photo loaded so load ajacent now
[self loadAdjacentPhotosIfNecessary:currentPhoto];
#pragma mark - Frame Calculations
- (CGRect)frameForPagingScrollView {
CGRect frame = self.view.// [[UIScreen mainScreen] bounds];
frame.origin.x -= PADDING;
frame.size.width += (2 * PADDING);
- (CGRect)frameForPageAtIndex:(NSUInteger)index {
// We have to use our paging scroll view's bounds, not frame, to calculate the page placement. When the device is in
// landscape orientation, the frame will still be in portrait because the pagingScrollView is the root view controller's
// view, so its frame is in window coordinate space, which is never rotated. Its bounds, however, will be in landscape
// because it has a rotation transform applied.
CGRect bounds = _pagingScrollView.
CGRect pageFrame =
pageFrame.size.width -= (2 * PADDING);
pageFrame.origin.x = (bounds.size.width * index) + PADDING;
return pageF
- (CGSize)contentSizeForPagingScrollView {
// We have to use the paging scroll view's bounds to calculate the contentSize, for the same reason outlined above.
CGRect bounds = _pagingScrollView.
return CGSizeMake(bounds.size.width * [self numberOfPhotos], bounds.size.height);
- (CGPoint)contentOffsetForPageAtIndex:(NSUInteger)index {
CGFloat pageWidth = _pagingScrollView.bounds.size.
CGFloat newOffset = index * pageW
return CGPointMake(newOffset, 0);
- (CGRect)frameForToolbarAtOrientation:(UIInterfaceOrientation)orientation {
CGFloat height = 44;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
UIInterfaceOrientationIsLandscape(orientation)) height = 32;
return CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height);
- (CGRect)frameForCaptionView:(MWCaptionView *)captionView atIndex:(NSUInteger)index {
CGRect pageFrame = [self frameForPageAtIndex:index];
captionView.frame = CGRectMake(0, 0, pageFrame.size.width, 44); // set initial frame
CGSize captionSize = [captionView sizeThatFits:CGSizeMake(pageFrame.size.width, 0)];
CGRect captionFrame = CGRectMake(pageFrame.origin.x, pageFrame.size.height - captionSize.height - (_toolbar.superview?_toolbar.frame.size.height:0), pageFrame.size.width, captionSize.height);
return captionF
#pragma mark - UIScrollView Delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (!_viewIsActive || _performingLayout || _rotating)
// Tile pages
[self tilePages];
// Calculate current page
CGRect visibleBounds = _pagingScrollView.
int index = (int)(floorf(CGRectGetMidX(visibleBounds) / CGRectGetWidth(visibleBounds)));
if (index & 0) index = 0;
if (index & [self numberOfPhotos] - 1) index = [self numberOfPhotos] - 1;
NSUInteger previousCurrentPage = _currentPageI
_currentPageIndex =
if (_currentPageIndex != previousCurrentPage) {
[self didStartViewingPageAtIndex:index];
MWPhoto *curPhoto = [_photos objectAtIndex:_currentPageIndex];
if ([curPhoto underlyingImage] != entranceImg.image)
[entranceImg setHidden:NO];
} else [entranceImg setHidden:YES];
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
// Hide controls when dragging begins
[self setControlsHidden:YES animated:YES permanent:NO];
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// Update nav when page changes
[self updateNavigation];
#pragma mark - Navigation
- (void)updateNavigation {
if ([self numberOfPhotos] & 1) {
self.title = [NSString stringWithFormat:@&%i %@ %i&, _currentPageIndex+1, NSLocalizedString(@&of&, @&Used in the context: 'Showing 1 of 3 items'&), [self numberOfPhotos]];
self.title =
// Buttons
_previousButton.enabled = (_currentPageIndex & 0);
_nextButton.enabled = (_currentPageIndex & [self numberOfPhotos]-1);
- (void)jumpToPageAtIndex:(NSUInteger)index {
// Change page
if (index & [self numberOfPhotos]) {
CGRect pageFrame = [self frameForPageAtIndex:index];
_pagingScrollView.contentOffset = CGPointMake(pageFrame.origin.x - PADDING, 0);
[self updateNavigation];
// Update timer to give more time
[self hideControlsAfterDelay];
- (void)gotoPreviousPage { [self jumpToPageAtIndex:_currentPageIndex-1]; }
- (void)gotoNextPage { [self jumpToPageAtIndex:_currentPageIndex+1]; }
#pragma mark - Control Hiding / Showing
// If permanent then we don't set timers to hide again
- (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated permanent:(BOOL)permanent {
// Cancel any timers
[self cancelControlHiding];
// Status bar and nav bar positioning
if (self.wantsFullScreenLayout) {
// Get status bar height if visible
CGFloat statusBarHeight = 0;
if (![UIApplication sharedApplication].statusBarHidden) {
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
statusBarHeight = MIN(statusBarFrame.size.height, statusBarFrame.size.width);
// Status Bar
if ([UIApplication instancesRespondToSelector:@selector(setStatusBarHidden:withAnimation:)]) {
[[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:animated?UIStatusBarAnimationFade:UIStatusBarAnimationNone];
[[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:UIStatusBarAnimationFade];
// Get status bar height if visible
if (![UIApplication sharedApplication].statusBarHidden) {
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
statusBarHeight = MIN(statusBarFrame.size.height, statusBarFrame.size.width);
// Set navigation bar frame
CGRect navBarFrame = self.navigationController.navigationBar.
navBarFrame.origin.y = statusBarH
self.navigationController.navigationBar.frame = navBarF
// Captions
NSMutableSet *captionViews = [[[NSMutableSet alloc] initWithCapacity:_visiblePages.count] autorelease];
for (MWZoomingScrollView *page in _visiblePages) {
if (page.captionView) [captionViews addObject:page.captionView];
// Animate
if (animated) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
CGFloat alpha = hidden ? 0 : 1;
[self.navigationController.navigationBar setAlpha:alpha];
[_toolbar setAlpha:alpha];
for (UIView *v in captionViews) v.alpha =
if (animated) [UIView commitAnimations];
// Control hiding timer
// Will cancel existing timer but only begin hiding if
// they are visible
if (!permanent) [self hideControlsAfterDelay];
- (void)cancelControlHiding {
// If a timer exists then cancel and release
if (_controlVisibilityTimer) {
[_controlVisibilityTimer invalidate];
[_controlVisibilityTimer release];
_controlVisibilityTimer =
// Enable/disable control visiblity timer
- (void)hideControlsAfterDelay {
if (![self areControlsHidden]) {
[self cancelControlHiding];
_controlVisibilityTimer = [[NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(hideControls) userInfo:nil repeats:NO] retain];
- (BOOL)areControlsHidden { return (_toolbar.alpha == 0); /* [UIApplication sharedApplication].isStatusBarH */ }
- (void)hideControls { [self setControlsHidden:YES animated:YES permanent:NO]; }
- (void)toggleControls { [self setControlsHidden:![self areControlsHidden] animated:YES permanent:NO]; }
#pragma mark - Properties
- (void)setInitialPageIndex:(NSUInteger)index {
// Validate
if (index &= [self numberOfPhotos]) index = [self numberOfPhotos]-1;
_currentPageIndex =
if ([self isViewLoaded]) {
[self jumpToPageAtIndex:index];
if (!_viewIsActive) [self tilePages]; // Force tiling if view is not visible
#pragma mark - Misc
- (void)doneButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
- (void)actionButtonPressed:(id)sender {
if (_actionsSheet) {
// Dismiss
[_actionsSheet dismissWithClickedButtonIndex:_actionsSheet.cancelButtonIndex animated:YES];
id &MWPhoto& photo = [self photoAtIndex:_currentPageIndex];
if ([self numberOfPhotos] & 0 && [photo underlyingImage]) {
// Keep controls hidden
[self setControlsHidden:NO animated:YES permanent:YES];
if ([MFMailComposeViewController canSendMail]) {
self.actionsSheet = [[[UIActionSheet alloc] initWithTitle:nil delegate:self
cancelButtonTitle:NSLocalizedString(@&Cancel&, nil) destructiveButtonTitle:nil
otherButtonTitles:NSLocalizedString(@&Save&, nil), NSLocalizedString(@&Copy&, nil), NSLocalizedString(@&Email&, nil), nil] autorelease];
self.actionsSheet = [[[UIActionSheet alloc] initWithTitle:nil delegate:self
cancelButtonTitle:NSLocalizedString(@&Cancel&, nil) destructiveButtonTitle:nil
otherButtonTitles:NSLocalizedString(@&Save&, nil), NSLocalizedString(@&Copy&, nil), nil] autorelease];
_actionsSheet.actionSheetStyle = UIActionSheetStyleBlackT
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[_actionsSheet showFromBarButtonItem:sender animated:YES];
[_actionsSheet showInView:self.view];
#pragma mark - Action Sheet Delegate
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (actionSheet == _actionsSheet) {
// Actions
self.actionsSheet =
if (buttonIndex != actionSheet.cancelButtonIndex) {
if (buttonIndex == actionSheet.firstOtherButtonIndex) {
[self savePhoto];
} else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) {
[self copyPhoto];
} else if (buttonIndex == actionSheet.firstOtherButtonIndex + 2) {
[self emailPhoto];
[self hideControlsAfterDelay]; // Continue as normal...
#pragma mark - MBProgressHUD
- (MBProgressHUD *)progressHUD {
if (!_progressHUD) {
_progressHUD = [[MBProgressHUD alloc] initWithView:self.view];
_progressHUD.minSize = CGSizeMake(120, 120);
_progressHUD.minShowTime = 1;
// The sample image is based on the
// work by:
// licence: http://creativecommons.org/licenses/by/2.5/ca/
self.progressHUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@&MWPhotoBrowser.bundle/images/Checkmark.png&]] autorelease];
[self.view addSubview:_progressHUD];
return _progressHUD;
- (void)showProgressHUDWithMessage:(NSString *)message {
self.progressHUD.labelText =
self.progressHUD.mode = MBProgressHUDModeI
[self.progressHUD show:YES];
self.navigationController.navigationBar.userInteractionEnabled = NO;
- (void)hideProgressHUD:(BOOL)animated {
[self.progressHUD hide:animated];
self.navigationController.navigationBar.userInteractionEnabled = YES;
- (void)showProgressHUDCompleteMessage:(NSString *)message {
if (message) {
if (self.progressHUD.isHidden) [self.progressHUD show:YES];
self.progressHUD.labelText =
self.progressHUD.mode = MBProgressHUDModeCustomV
[self.progressHUD hide:YES afterDelay:1.5];
[self.progressHUD hide:YES];
self.navigationController.navigationBar.userInteractionEnabled = YES;
#pragma mark - Actions
- (void)savePhoto {
id &MWPhoto& photo = [self photoAtIndex:_currentPageIndex];
if ([photo underlyingImage]) {
[self showProgressHUDWithMessage:[NSString stringWithFormat:@&%@\u2026& , NSLocalizedString(@&Saving&, @&Displayed with ellipsis as 'Saving...' when an item is in the process of being saved&)]];
[self performSelector:@selector(actuallySavePhoto:) withObject:photo afterDelay:0];
- (void)actuallySavePhoto:(id&MWPhoto&)photo {
if ([photo underlyingImage]) {
UIImageWriteToSavedPhotosAlbum([photo underlyingImage], self,
@selector(image:didFinishSavingWithError:contextInfo:), nil);
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
[self showProgressHUDCompleteMessage: error ? NSLocalizedString(@&Failed&, @&Informing the user a process has failed&) : NSLocalizedString(@&Saved&, @&Informing the user an item has been saved&)];
[self hideControlsAfterDelay]; // Continue as normal...
- (void)copyPhoto {
id &MWPhoto& photo = [self photoAtIndex:_currentPageIndex];
if ([photo underlyingImage]) {
[self showProgressHUDWithMessage:[NSString stringWithFormat:@&%@\u2026& , NSLocalizedString(@&Copying&, @&Displayed with ellipsis as 'Copying...' when an item is in the process of being copied&)]];
[self performSelector:@selector(actuallyCopyPhoto:) withObject:photo afterDelay:0];
- (void)actuallyCopyPhoto:(id&MWPhoto&)photo {
if ([photo underlyingImage]) {
[[UIPasteboard generalPasteboard] setData:UIImagePNGRepresentation([photo underlyingImage])
forPasteboardType:@&public.png&];
[self showProgressHUDCompleteMessage:NSLocalizedString(@&Copied&, @&Informing the user an item has finished copying&)];
[self hideControlsAfterDelay]; // Continue as normal...
- (void)emailPhoto {
id &MWPhoto& photo = [self photoAtIndex:_currentPageIndex];
if ([photo underlyingImage]) {
[self showProgressHUDWithMessage:[NSString stringWithFormat:@&%@\u2026& , NSLocalizedString(@&Preparing&, @&Displayed with ellipsis as 'Preparing...' when an item is in the process of being prepared&)]];
[self performSelector:@selector(actuallyEmailPhoto:) withObject:photo afterDelay:0];
- (void)actuallyEmailPhoto:(id&MWPhoto&)photo {
if ([photo underlyingImage]) {
MFMailComposeViewController *emailer = [[MFMailComposeViewController alloc] init];
emailer.mailComposeDelegate =
[emailer setSubject:NSLocalizedString(@&Photo&, nil)];
[emailer addAttachmentData:UIImagePNGRepresentation([photo underlyingImage]) mimeType:@&png& fileName:@&Photo.png&];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
emailer.modalPresentationStyle = UIModalPresentationPageS
[self presentViewController:emailer animated:YES completion:nil];
[emailer release];
[self hideProgressHUD:NO];
#pragma mark Mail Compose Delegate
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
if (result == MFMailComposeResultFailed) {
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@&Email&, nil)
message:NSLocalizedString(@&Email failed to send. Please try again.&, nil)
delegate:nil cancelButtonTitle:NSLocalizedString(@&Dismiss&, nil) otherButtonTitles:nil] autorelease];
[alert show];
[self dismissViewControllerAnimated:YES completion:nil];
- (UIScrollView *)getPagingScrollView
return _pagingScrollV
Copyright(C)
OKBASE.NET All Rights Reserved 好库网 版权所有}

我要回帖

更多关于 mwphotobrowser 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信