Skip to content

Commit

Permalink
Add iPhone X support
Browse files Browse the repository at this point in the history
Safe areas are calculated for toolbar, done button and photo frame.
This accounts for orientation and fall back for pre-iOS 11 devices.
  • Loading branch information
oliveroneill committed Dec 4, 2017
1 parent 2123703 commit c280289
Show file tree
Hide file tree
Showing 7 changed files with 436 additions and 9 deletions.
46 changes: 38 additions & 8 deletions Classes/IDMPhotoBrowser.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import <QuartzCore/QuartzCore.h>
#import "IDMPhotoBrowser.h"
#import "IDMZoomingScrollView.h"
#import "IDMUtils.h"

#import "pop/POP.h"

Expand Down Expand Up @@ -62,6 +63,7 @@ @interface IDMPhotoBrowser () {
BOOL _viewIsActive; // active as in it's in the view heirarchy
BOOL _autoHide;
NSInteger _initalPageIndex;
CGFloat _statusBarHeight;

BOOL _isdraggingPhoto;

Expand Down Expand Up @@ -190,8 +192,11 @@ - (id)init {

_isdraggingPhoto = NO;

_statusBarHeight = 20.f;
_doneButtonRightInset = 20.f;
_doneButtonTopInset = 30.f;
// relative to status bar and safeAreaInsets
_doneButtonTopInset = 10.f;

_doneButtonSize = CGSizeMake(55.f, 26.f);

if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
Expand Down Expand Up @@ -478,8 +483,19 @@ - (CGRect)animationFrameForImage:(UIImage *)image presenting:(BOOL)presenting sc

CGSize imageSize = image.size;

CGFloat maxWidth = CGRectGetWidth(_applicationWindow.bounds);
CGFloat maxHeight = CGRectGetHeight(_applicationWindow.bounds);
CGRect bounds = _applicationWindow.bounds;
// adjust bounds as the photo browser does
if (@available(iOS 11.0, *)) {
// use the windows safe area inset
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIEdgeInsets insets = UIEdgeInsetsMake(_statusBarHeight, 0, 0, 0);
if (window != NULL) {
insets = window.safeAreaInsets;
}
bounds = [self adjustForSafeArea:bounds adjustForStatusBar:NO forInsets:insets];
}
CGFloat maxWidth = CGRectGetWidth(bounds);
CGFloat maxHeight = CGRectGetHeight(bounds);

CGRect animationFrame = CGRectZero;

Expand All @@ -497,7 +513,6 @@ - (CGRect)animationFrameForImage:(UIImage *)image presenting:(BOOL)presenting sc
if (!presenting) {
animationFrame.origin.y += scrollView.frame.origin.y;
}

return animationFrame;
}

Expand Down Expand Up @@ -1078,6 +1093,7 @@ - (CGRect)frameForPagingScrollView {
CGRect frame = self.view.bounds;
frame.origin.x -= PADDING;
frame.size.width += (2 * PADDING);
frame = [self adjustForSafeArea:frame adjustForStatusBar:false];
return frame;
}

Expand Down Expand Up @@ -1116,16 +1132,18 @@ - (CGRect)frameForToolbarAtOrientation:(UIInterfaceOrientation)orientation {
if ([self isLandscape:orientation])
height = 32;

return CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height);
CGRect rtn = CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height);
rtn = [self adjustForSafeArea:rtn adjustForStatusBar:true];
return rtn;
}

- (CGRect)frameForDoneButtonAtOrientation:(UIInterfaceOrientation)orientation {
CGRect screenBound = self.view.bounds;
CGFloat screenWidth = screenBound.size.width;

// if ([self isLandscape:orientation]) screenWidth = screenBound.size.height;

return CGRectMake(screenWidth - self.doneButtonRightInset - self.doneButtonSize.width, self.doneButtonTopInset, self.doneButtonSize.width, self.doneButtonSize.height);
CGRect rtn = CGRectMake(screenWidth - self.doneButtonRightInset - self.doneButtonSize.width, self.doneButtonTopInset, self.doneButtonSize.width, self.doneButtonSize.height);
rtn = [self adjustForSafeArea:rtn adjustForStatusBar:true];
return rtn;
}

- (CGRect)frameForCaptionView:(IDMCaptionView *)captionView atIndex:(NSUInteger)index {
Expand All @@ -1137,6 +1155,18 @@ - (CGRect)frameForCaptionView:(IDMCaptionView *)captionView atIndex:(NSUInteger)
return captionFrame;
}

- (CGRect)adjustForSafeArea:(CGRect)rect adjustForStatusBar:(BOOL)adjust {
if (@available(iOS 11.0, *)) {
return [self adjustForSafeArea:rect adjustForStatusBar:adjust forInsets:self.view.safeAreaInsets];
}
UIEdgeInsets insets = UIEdgeInsetsMake(_statusBarHeight, 0, 0, 0);
return [self adjustForSafeArea:rect adjustForStatusBar:adjust forInsets:insets];
}

- (CGRect)adjustForSafeArea:(CGRect)rect adjustForStatusBar:(BOOL)adjust forInsets:(UIEdgeInsets) insets {
return [IDMUtils adjustRect:rect forSafeAreaInsets:insets forBounds:self.view.bounds adjustForStatusBar:adjust statusBarHeight:_statusBarHeight];
}

#pragma mark - UIScrollView Delegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
Expand Down
12 changes: 12 additions & 0 deletions Classes/IDMUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// IDMUtils.h
// PhotoBrowserDemo
//
// Created by Oliver ONeill on 2/12/17.
//

#import <Foundation/Foundation.h>

@interface IDMUtils : NSObject
+ (CGRect)adjustRect:(CGRect)rect forSafeAreaInsets:(UIEdgeInsets)insets forBounds:(CGRect)bounds adjustForStatusBar:(BOOL)adjust statusBarHeight:(int)statusBarHeight;
@end
52 changes: 52 additions & 0 deletions Classes/IDMUtils.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// IDMUtils.m
// PhotoBrowserDemo
//
// Created by Oliver ONeill on 2/12/17.
//

#import "IDMUtils.h"

@implementation IDMUtils
/**
* Adjust a rect to be moved into a safe area specified by `insets`.
*
* NOTE: this does not cover all cases. Given a rect it will reposition it if it
* falls into an unsafe area according to `insets` and `bounds`. When
* `adjustForStatusBar` is true, the rect y position will be based from the edge
* of the safe area, otherwise it will be based from zero. This allows views to
* sit behind the status bar. Status bar height is also used
* to keep positioning consistent when toggling the status bar on and off
*/
+ (CGRect)adjustRect:(CGRect)rect forSafeAreaInsets:(UIEdgeInsets)insets forBounds:(CGRect)bounds adjustForStatusBar:(BOOL)adjust statusBarHeight:(int)statusBarHeight {
BOOL isLeft = rect.origin.x <= insets.left;
// If the safe area is not specified via insets we should fall back to the
// status bar height
CGFloat insetTop = insets.top > 0 ? insets.top : statusBarHeight;
// Don't adjust for y positioning when adjustForStatusBar is false
BOOL isAtTop = (rect.origin.y <= insetTop);
BOOL isRight = rect.origin.x + rect.size.width >= bounds.size.width - insets.right;
BOOL isAtBottom = rect.origin.y + rect.size.height >= bounds.size.height - insets.bottom;
if ((isLeft) && (isRight)) {
rect.origin.x += insets.left;
rect.size.width -= insets.right + insets.left;
} else if (isLeft) {
rect.origin.x += insets.left;
} else if (isRight) {
rect.origin.x -= insets.right;
}
// if we're adjusting for status bar then we should move the view out of
// the inset
if ((adjust) && (isAtTop) && (isAtBottom)) {
rect.origin.y += insetTop;
rect.size.height -= insets.bottom + insetTop;
} else if ((adjust) && (isAtTop)) {
rect.origin.y += insetTop;
} else if ((isAtTop) && (isAtBottom)) {
rect.size.height -= insets.bottom;
} else if (isAtBottom) {
rect.origin.y -= insets.bottom;
}
return rect;
}
@end
Loading

0 comments on commit c280289

Please sign in to comment.