Skip to content

Feature/video #304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Classes/IDMPhoto.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ typedef void (^IDMProgressUpdateBlock)(CGFloat progress);
// Properties
@property (nonatomic, strong) NSString *caption;
@property (nonatomic, strong) NSURL *photoURL;
@property (nonatomic, strong) NSURL *videoURL;
@property (nonatomic, strong) IDMProgressUpdateBlock progressUpdateBlock;
@property (nonatomic, strong) UIImage *placeholderImage;

Expand All @@ -36,6 +37,7 @@ typedef void (^IDMProgressUpdateBlock)(CGFloat progress);

// Init
- (id)initWithImage:(UIImage *)image;
- (id)initWithVideo:(NSURL *)videoURL;
- (id)initWithFilePath:(NSString *)path;
- (id)initWithURL:(NSURL *)url;

Expand Down
8 changes: 8 additions & 0 deletions Classes/IDMPhoto.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ @implementation IDMPhoto
// Properties
@synthesize underlyingImage = _underlyingImage,
photoURL = _photoURL,
videoURL = _videoURL,
caption = _caption;

#pragma mark Class Methods
Expand Down Expand Up @@ -104,6 +105,13 @@ - (id)initWithImage:(UIImage *)image {
return self;
}

- (id)initWithVideo:(NSURL *)videoURL {
if ((self = [super init])) {
self.videoURL = videoURL;
}
return self;
}

- (id)initWithFilePath:(NSString *)path {
if ((self = [super init])) {
_photoPath = [path copy];
Expand Down
22 changes: 21 additions & 1 deletion Classes/IDMPhotoBrowser.m
Original file line number Diff line number Diff line change
Expand Up @@ -714,11 +714,15 @@ - (void)viewWillAppear:(BOOL)animated {
// Update
[self reloadData];


if ([_delegate respondsToSelector:@selector(willAppearPhotoBrowser:)]) {
[_delegate willAppearPhotoBrowser:self];
}

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerDidFinishPlaying:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:NULL];

// Super
[super viewWillAppear:animated];

Expand All @@ -734,6 +738,15 @@ - (void)viewDidAppear:(BOOL)animated {
_viewIsActive = YES;
}

- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:AVPlayerItemDidPlayToEndTimeNotification
object:NULL];

// Super
[super viewWillDisappear:animated];
}

// Release any retained subviews of the main view.
- (void)viewDidUnload {
_currentPageIndex = 0;
Expand All @@ -748,6 +761,13 @@ - (void)viewDidUnload {
[super viewDidUnload];
}

#pragma mark - Video Loop

- (void)playerDidFinishPlaying:(NSNotification *)notification {
[[self pageDisplayedAtIndex:_currentPageIndex].videoPlayerLayer.player seekToTime:kCMTimeZero];
[[self pageDisplayedAtIndex:_currentPageIndex].videoPlayerLayer.player play];
}

#pragma mark - Status Bar

- (UIStatusBarStyle)preferredStatusBarStyle {
Expand Down
4 changes: 3 additions & 1 deletion Classes/IDMPhotoProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
// methods returns nil.
- (UIImage *)underlyingImage;

- (NSURL *)videoURL;

// Called when the browser has determined the underlying images is not
// already loaded into memory but needs it.
// You must load the image asyncronously (and decompress it for better performance).
Expand Down Expand Up @@ -61,4 +63,4 @@
// Return nil if there is no placeholder
- (UIImage *)placeholderImage;

@end
@end
4 changes: 4 additions & 0 deletions Classes/IDMZoomingScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//

#import <Foundation/Foundation.h>
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
#import "IDMPhotoProtocol.h"
#import "IDMTapDetectingImageView.h"
#import "IDMTapDetectingView.h"
Expand All @@ -29,6 +31,8 @@
}

@property (nonatomic, strong) IDMTapDetectingImageView *photoImageView;
@property (nonatomic, strong) IDMTapDetectingView *videoPlayerView;
@property (nonatomic, strong) AVPlayerLayer *videoPlayerLayer;
@property (nonatomic, strong) IDMCaptionView *captionView;
@property (nonatomic, strong) id<IDMPhoto> photo;
@property (nonatomic) CGFloat maximumDoubleTapZoomScale;
Expand Down
62 changes: 58 additions & 4 deletions Classes/IDMZoomingScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ - (void)handleDoubleTap:(CGPoint)touchPoint;

@implementation IDMZoomingScrollView

@synthesize photoImageView = _photoImageView, photoBrowser = _photoBrowser, photo = _photo, captionView = _captionView;
@synthesize photoImageView = _photoImageView, videoPlayerView = _videoPlayerView, videoPlayerLayer = _videoPlayerLayer, photoBrowser = _photoBrowser, photo = _photo, captionView = _captionView;

- (id)initWithPhotoBrowser:(IDMPhotoBrowser *)browser {
if ((self = [super init])) {
Expand All @@ -41,7 +41,20 @@ - (id)initWithPhotoBrowser:(IDMPhotoBrowser *)browser {
_tapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_tapView.backgroundColor = [UIColor clearColor];
[self addSubview:_tapView];


// Video
_videoPlayerView = [[IDMTapDetectingView alloc] initWithFrame:self.bounds];
_videoPlayerView.tapDelegate = self;
_videoPlayerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_videoPlayerView.backgroundColor = [UIColor clearColor];
[self addSubview:_videoPlayerView];

_videoPlayerLayer = [[AVPlayerLayer alloc] init];
_videoPlayerLayer.backgroundColor = [UIColor clearColor].CGColor;
[_videoPlayerLayer setFrame:_videoPlayerView.bounds];
[_videoPlayerLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
[_videoPlayerView.layer addSublayer:_videoPlayerLayer];

// Image view
_photoImageView = [[IDMTapDetectingImageView alloc] initWithFrame:CGRectZero];
_photoImageView.tapDelegate = self;
Expand All @@ -57,6 +70,7 @@ - (id)initWithPhotoBrowser:(IDMPhotoBrowser *)browser {
if (@available(iOS 11.0, *)) {
UIDragInteraction *drag = [[UIDragInteraction alloc] initWithDelegate: self];
[_photoImageView addInteraction:drag];
[_videoPlayerView addInteraction:drag];
}

CGRect screenBound = [[UIScreen mainScreen] bounds];
Expand Down Expand Up @@ -99,6 +113,11 @@ - (void)setPhoto:(id<IDMPhoto>)photo {
}

- (void)prepareForReuse {
[_progressView setProgress:0 animated:NO];
[_progressView setIndeterminate:NO];
[_videoPlayerLayer.player removeObserver:self forKeyPath:@"status" context:nil];
[_videoPlayerLayer.player pause];
_videoPlayerLayer.player = NULL;
self.photo = nil;
[_captionView removeFromSuperview];
self.captionView = nil;
Expand All @@ -125,6 +144,9 @@ - (void)displayImage {
// Get image from browser as it handles ordering of fetching
UIImage *img = [self.photoBrowser imageForPhoto:_photo];
if (img) {
// Hide video
_videoPlayerView.hidden = YES;

// Hide ProgressView
//_progressView.alpha = 0.0f;
[_progressView removeFromSuperview];
Expand All @@ -143,17 +165,46 @@ - (void)displayImage {

// Set zoom to minimum zoom
[self setMaxMinZoomScalesForCurrentBounds];
} else if (_photo.videoURL != NULL) {
// Hide ProgressView
//_progressView.alpha = 0.0f;
[_progressView setProgress:0.3 animated:YES];
[_progressView setIndeterminateDuration:0.7f];
[_progressView setIndeterminate:YES];

_photoImageView.hidden = YES;
_videoPlayerView.hidden = NO;

[_videoPlayerLayer.player pause];
_videoPlayerLayer.player = NULL;
AVPlayer *player = [AVPlayer playerWithURL:_photo.videoURL];
[_videoPlayerLayer setPlayer:player];

[player seekToTime:kCMTimeZero];
[player play];

[player addObserver:self forKeyPath:@"status" options:0 context:nil];
} else {
// Hide image view
_photoImageView.hidden = YES;

_progressView.alpha = 1.0f;
}

[self setNeedsLayout];
}
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == _videoPlayerLayer.player && [keyPath isEqualToString:@"status"]) {
if (_videoPlayerLayer.player.status == AVPlayerStatusReadyToPlay) {
[_progressView removeFromSuperview];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}

- (void)setProgress:(CGFloat)progress forPhoto:(IDMPhoto*)photo {
IDMPhoto *p = (IDMPhoto*)self.photo;

Expand Down Expand Up @@ -241,7 +292,10 @@ - (void)setMaxMinZoomScalesForCurrentBounds {
- (void)layoutSubviews {
// Update tap view frame
_tapView.frame = self.bounds;


_videoPlayerView.frame = self.bounds;
_videoPlayerLayer.frame = _videoPlayerView.bounds;

// Super
[super layoutSubviews];

Expand Down
38 changes: 4 additions & 34 deletions Demo/PhotoBrowserDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@
7D2B79BF1FD25B7600F2094F /* PhotoBrowserDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PhotoBrowserDemoTests.m; sourceTree = "<group>"; };
7D2B79C11FD25B7600F2094F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7D2B79C71FD25BF300F2094F /* IDMUtilsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IDMUtilsTest.m; sourceTree = "<group>"; };
7D7D66691E09D6D400410A67 /* IDMBrowserDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDMBrowserDelegate.h; sourceTree = "<group>"; };
7D7D666A1E09D6DA00410A67 /* IDMPhotoDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDMPhotoDataSource.h; sourceTree = "<group>"; };
D00FA320EEACA8C835D9D626 /* Pods-PhotoBrowserDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PhotoBrowserDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PhotoBrowserDemo/Pods-PhotoBrowserDemo.debug.xcconfig"; sourceTree = "<group>"; };
D11464B61802FFC4005B7BC3 /* IDMPBConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IDMPBConstants.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -327,8 +326,6 @@
4C6F978914AF734800F8389A /* Sources */,
4C6F978A14AF734800F8389A /* Frameworks */,
4C6F978B14AF734800F8389A /* Resources */,
64D1E44DFBE2976FB9C75718 /* [CP] Embed Pods Frameworks */,
F88445D630091F1AA9A2F89A /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -438,49 +435,22 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
64D1E44DFBE2976FB9C75718 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PhotoBrowserDemo/Pods-PhotoBrowserDemo-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9FEC6B6CD1E66BC894CF44FA /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-PhotoBrowserDemo-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
F88445D630091F1AA9A2F89A /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PhotoBrowserDemo/Pods-PhotoBrowserDemo-resources.sh\"\n";
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
Expand Down
47 changes: 33 additions & 14 deletions Demo/PhotoBrowserDemo/MenuViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ extension MenuViewController {
case 0:
return 1
case 1:
return 3
return 4
case 2:
return 0
default:
Expand Down Expand Up @@ -161,8 +161,10 @@ extension MenuViewController {
cell?.textLabel?.text = "Local photos"
case 1:
cell?.textLabel?.text = "Photos from Flickr"
case 2:
cell?.textLabel?.text = "Photos from Flickr - Custom"
case 2:
cell?.textLabel?.text = "Photos from Flickr - Custom"
case 3:
cell?.textLabel?.text = "Video"
default:
break
}
Expand Down Expand Up @@ -191,7 +193,7 @@ extension MenuViewController {
}
else if indexPath.section == 1 { // Multiple photos
if indexPath.row == 0 { // Local Photos

let path_photo1l = [Bundle.main.path(forResource: "photo1l", ofType: "jpg")]
photo = IDMPhoto.photos(withFilePaths:path_photo1l).first as! IDMPhoto
photo.caption = "Grotto of the Madonna"
Expand All @@ -211,23 +213,40 @@ extension MenuViewController {
photo = IDMPhoto.photos(withFilePaths:path_photo4l).first as! IDMPhoto
photo.caption = "Campervan";
photos.append(photo)
} else if indexPath.row == 1 || indexPath.row == 2 { // Photos from Flickr or Flickr - Custom
let photosWithURLArray = [NSURL.init(string: "http://farm4.static.flickr.com/3567/3523321514_371d9ac42f_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3629/3339128908_7aecabc34b_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3364/3338617424_7ff836d55f_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3590/3329114220_5fbc5bc92b_b.jpg")]
let photosWithURL: [IDMPhoto] = IDMPhoto.photos(withURLs: photosWithURLArray) as! [IDMPhoto]

photos = photosWithURL
}
} else if indexPath.row == 1 || indexPath.row == 2 { // Photos from Flickr or Flickr - Custom
let photosWithURLArray = [NSURL.init(string: "http://farm4.static.flickr.com/3567/3523321514_371d9ac42f_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3629/3339128908_7aecabc34b_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3364/3338617424_7ff836d55f_b.jpg"),
NSURL.init(string: "http://farm4.static.flickr.com/3590/3329114220_5fbc5bc92b_b.jpg")]
let photosWithURL: [IDMPhoto] = IDMPhoto.photos(withURLs: photosWithURLArray) as! [IDMPhoto]

photos = photosWithURL
} else if indexPath.row == 3 { // Videos
let video1 = IDMPhoto(video: URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")!)!
video1.caption = "Big Buck Bunny — by THE PEACH OPEN MOVIE PROJECT"

let photo1 = IDMPhoto(url: URL(string: "http://farm4.static.flickr.com/3590/3329114220_5fbc5bc92b_b.jpg")!)!
photo1.caption = "A standard picture separating two videos"

let video2 = IDMPhoto(video: URL(string: "https://staging.coverr.co/s3/mp4/Playful.mp4")!)!
video2.caption = "A cover coming straight from coverr.co for an example"

let videos: [IDMPhoto] = [
video1,
photo1,
video2
]

photos = videos
}
}

// Create and setup browser
let browser = IDMPhotoBrowser.init(photos: photos)
browser?.delegate = self

if indexPath.section == 1 { // Multiple photos
if indexPath.row == 1 { // Photos from Flickr
if indexPath.row == 1 || indexPath.row == 3 { // Photos from Flickr
browser?.displayCounterLabel = true
browser?.displayActionButton = false
} else if indexPath.row == 2 { // Photos from Flickr - Custom
Expand Down
1 change: 0 additions & 1 deletion Demo/PhotoBrowserDemo/PhotoBrowserDemo-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
// Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "Menu.h"
#import "IDMPhotoBrowser.h"
Loading