Skip to content
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

Creating a blurred background effect #239

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Binary file added .DS_Store
Binary file not shown.
10 changes: 10 additions & 0 deletions Example/Example.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
6 changes: 6 additions & 0 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import UIKit
import AVKit

extension UIImageView: DisplaceableView {}

Expand Down Expand Up @@ -44,6 +45,11 @@ class ViewController: UIViewController {

galleryItem = GalleryItem.video(fetchPreviewImageBlock: { $0(UIImage(named: "2")!) }, videoURL: URL (string: "http://video.dailymail.co.uk/video/mol/test/2016/09/21/5739239377694275356/1024x576_MP4_5739239377694275356.mp4")!)

// galleryItem = GalleryItem.rawVideo(fetchPreviewImageBlock: { $0(UIImage(named: "2")!) }, fetchRawVideoBlock: { w in
// w(AVAsset(url:URL(string: "http://video.dailymail.co.uk/video/mol/test/2016/09/21/5739239377694275356/1024x576_MP4_5739239377694275356.mp4")!))
// })


case 4:

let myFetchImageBlock: FetchImageBlock = { $0(imageView.image!) }
Expand Down
2 changes: 1 addition & 1 deletion ImageViewer.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "ImageViewer"
s.version = "6.0.0"
s.version = "6.2.3"
s.summary = "An image viewer à la Twitter"
s.description = <<-EOS
ImageViewer is a library that enables a user to visualize an image in fullscreen. Besides the typical pinch and double tap to zoom, we also provide a vertical swipe to dismiss. Finally, we try to mimic the displacement of the image from its current container into fullscreen, this feature being its main selling point. We also offer an amazing Gallery, so you can swipe between images.
Expand Down
26 changes: 26 additions & 0 deletions ImageViewer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
C7897CEF1C1350B7006447FB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C7897CED1C1350B7006447FB /* LaunchScreen.storyboard */; };
C7897CF61C1356C6006447FB /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DABE631C12276800F5BD7B /* CGSize.swift */; };
C7DABE641C12276800F5BD7B /* CGSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DABE631C12276800F5BD7B /* CGSize.swift */; };
D043A10B24374E630069591A /* VideoRawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D043A10A24374E630069591A /* VideoRawViewController.swift */; };
D043A10C243750650069591A /* VideoRawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D043A10A24374E630069591A /* VideoRawViewController.swift */; };
EB057A151D510264007565F1 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB057A141D510264007565F1 /* AVPlayer.swift */; };
EB057A161D510264007565F1 /* AVPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB057A141D510264007565F1 /* AVPlayer.swift */; };
EB17B3781D4A51D200EED1DA /* UIBezierPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB17B3771D4A51D200EED1DA /* UIBezierPath.swift */; };
Expand Down Expand Up @@ -111,6 +113,8 @@
C7897CF01C1350B7006447FB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C7DABE481C12245B00F5BD7B /* ImageViewer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ImageViewer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C7DABE631C12276800F5BD7B /* CGSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGSize.swift; sourceTree = "<group>"; };
D043A10A24374E630069591A /* VideoRawViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRawViewController.swift; sourceTree = "<group>"; };
D095DC2624D89B7F006F0173 /* Example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Example.entitlements; sourceTree = "<group>"; };
EB057A141D510264007565F1 /* AVPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AVPlayer.swift; sourceTree = "<group>"; };
EB17B3771D4A51D200EED1DA /* UIBezierPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIBezierPath.swift; sourceTree = "<group>"; };
EB17B37D1D4A5A2500EED1DA /* CAShapeLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CAShapeLayer.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -185,6 +189,7 @@
C7897CE31C1350B7006447FB /* Example */ = {
isa = PBXGroup;
children = (
D095DC2624D89B7F006F0173 /* Example.entitlements */,
C7897CE41C1350B7006447FB /* AppDelegate.swift */,
C7897CE61C1350B7006447FB /* ViewController.swift */,
EB5253F31C8DCE9800EAA4A4 /* CounterView.swift */,
Expand Down Expand Up @@ -353,6 +358,7 @@
EB6F46541D4660AC00984035 /* VideoView.swift */,
EB60EE551D58EB4800CC5BA8 /* VideoScrubber.swift */,
EB60EE581D590E8B00CC5BA8 /* Slider.swift */,
D043A10A24374E630069591A /* VideoRawViewController.swift */,
);
name = Video;
sourceTree = "<group>";
Expand Down Expand Up @@ -460,7 +466,9 @@
TargetAttributes = {
C7897CE11C1350B7006447FB = {
CreatedOnToolsVersion = 7.1.1;
DevelopmentTeam = V862M46692;
LastSwiftMigration = 1100;
ProvisioningStyle = Automatic;
};
C7DABE471C12245B00F5BD7B = {
CreatedOnToolsVersion = 7.1.1;
Expand Down Expand Up @@ -556,6 +564,7 @@
13BDF0721E573D10009C458F /* UIColor.swift in Sources */,
4CD1C49C1C16FF64008D5F84 /* CGPoint.swift in Sources */,
EBA76F711D4F855C0094931F /* ItemBaseController.swift in Sources */,
D043A10C243750650069591A /* VideoRawViewController.swift in Sources */,
EB4DEBC01C84A6FD00D5F897 /* UIView.swift in Sources */,
EBAF4C631D3937AE0039CA93 /* ImageViewController.swift in Sources */,
EB40C3771C9C5C48004EA215 /* GalleryItemsDataSource.swift in Sources */,
Expand Down Expand Up @@ -598,6 +607,7 @@
EBA0A9541C89C653005B8DD3 /* GalleryConfiguration.swift in Sources */,
EB17B3791D4A51D200EED1DA /* UIBezierPath.swift in Sources */,
EB1DB6EA1D3E595D00DC9064 /* UIApplication.swift in Sources */,
D043A10B24374E630069591A /* VideoRawViewController.swift in Sources */,
EBBFCB971D26CBA2007E7244 /* BlurView.swift in Sources */,
EB8BEC7B1D3D1CB500DCE3EC /* ItemControllerDelegate.swift in Sources */,
EB60EE5A1D590E8B00CC5BA8 /* Slider.swift in Sources */,
Expand Down Expand Up @@ -646,10 +656,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = V862M46692;
INFOPLIST_FILE = Example/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = mailonline.Example;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SUPPORTS_MACCATALYST = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
};
Expand All @@ -659,10 +677,18 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = V862M46692;
INFOPLIST_FILE = Example/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = mailonline.Example;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
SUPPORTS_MACCATALYST = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 5.0;
};
Expand Down
10 changes: 7 additions & 3 deletions ImageViewer/Source/Extensions/UIView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ extension UIView {

extension DisplaceableView {

func frameInCoordinatesOfScreen() -> CGRect {

return UIView().convert(self.bounds, to: UIScreen.main.coordinateSpace)
func frameInCoordinatesOfScreen() -> CGRect
{
if #available(iOS 12.0, *) {
return UIView().convert(self.bounds, to: UIApplication.shared.keyWindow!.coordinateSpace)
} else {
return UIView().convert(self.bounds, to: UIScreen.main.coordinateSpace)
}
}
}
4 changes: 4 additions & 0 deletions ImageViewer/Source/GalleryItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@
//

import UIKit
import AVKit

public typealias ImageCompletion = (UIImage?) -> Void
public typealias VideoCompletion = (AVAsset?) -> Void
public typealias FetchImageBlock = (@escaping ImageCompletion) -> Void
public typealias FetchVideoBlock = (@escaping VideoCompletion) -> Void
public typealias ItemViewControllerBlock = (_ index: Int, _ itemCount: Int, _ fetchImageBlock: FetchImageBlock, _ configuration: GalleryConfiguration, _ isInitialController: Bool) -> UIViewController

public enum GalleryItem {

case image(fetchImageBlock: FetchImageBlock)
case video(fetchPreviewImageBlock: FetchImageBlock, videoURL: URL)
case rawVideo(fetchPreviewImageBlock: FetchImageBlock, fetchRawVideoBlock: FetchVideoBlock)
case custom(fetchImageBlock: FetchImageBlock, itemViewControllerBlock: ItemViewControllerBlock)
}
10 changes: 10 additions & 0 deletions ImageViewer/Source/GalleryPagingDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ final class GalleryPagingDataSource: NSObject, UIPageViewControllerDataSource {
itemController.displacedViewsDataSource = displacedViewsDataSource

return vc

case .rawVideo(let fetchImageBlock, let fetchVideoBlock):

let videoController = VideoRawViewController(index: itemIndex, itemCount: itemsDataSource.itemCount(), fetchImageBlock: fetchImageBlock, fetchVideoBlock:fetchVideoBlock, scrubber: scrubber, configuration: configuration, isInitialController: isInitial)

videoController.delegate = itemControllerDelegate
videoController.displacedViewsDataSource = displacedViewsDataSource

return videoController

}
}
}
35 changes: 28 additions & 7 deletions ImageViewer/Source/GalleryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,10 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {


fileprivate func configureOverlayView() {
let _bounds = UIApplication.shared.keyWindow!.bounds
overlayView.bounds.size = _bounds.insetBy(dx: -_bounds.width / 2, dy: -_bounds.height / 2).size
overlayView.center = CGPoint(x: (_bounds.width / 2), y: (_bounds.height / 2))

overlayView.bounds.size = UIScreen.main.bounds.insetBy(dx: -UIScreen.main.bounds.width / 2, dy: -UIScreen.main.bounds.height / 2).size
overlayView.center = CGPoint(x: (UIScreen.main.bounds.width / 2), y: (UIScreen.main.bounds.height / 2))

self.view.addSubview(overlayView)
self.view.sendSubviewToBack(overlayView)
Expand Down Expand Up @@ -315,8 +316,8 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {
self.view.transform = transform
self.view.bounds = bounds
}

overlayView.frame = view.bounds.insetBy(dx: -UIScreen.main.bounds.width * 2, dy: -UIScreen.main.bounds.height * 2)
let _bounds = UIApplication.shared.keyWindow!.bounds
overlayView.frame = view.bounds.insetBy(dx: -_bounds.width * 2, dy: -_bounds.height * 2)

layoutButton(closeButton, layout: closeLayout)
layoutButton(thumbnailsButton, layout: thumbnailsLayout)
Expand Down Expand Up @@ -420,7 +421,13 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {

scrubber.bounds = CGRect(origin: CGPoint.zero, size: CGSize(width: self.view.bounds.width, height: 40))
scrubber.center = self.view.boundsCenter
scrubber.frame.origin.y = (footerView?.frame.origin.y ?? self.view.bounds.maxY) - scrubber.bounds.height

if #available(iOS 11.0, *) {
scrubber.frame.origin.y = (self.view.safeAreaLayoutGuide.layoutFrame.maxY) - scrubber.bounds.height
} else {
// Fallback on earlier versions
scrubber.frame.origin.y = (footerView?.frame.origin.y ?? self.view.bounds.maxY) - scrubber.bounds.height
}
}

@objc fileprivate func deleteItem() {
Expand Down Expand Up @@ -613,7 +620,7 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {
self?.thumbnailsButton?.alpha = targetAlpha
self?.deleteButton?.alpha = targetAlpha

if let _ = self?.viewControllers?.first as? VideoViewController {
if let _ = self?.viewControllers?.first as? ItemBaseController<VideoView> {

UIView.animate(withDuration: 0.3, animations: { [weak self] in

Expand All @@ -626,14 +633,17 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {
public func itemControllerWillAppear(_ controller: ItemController) {

if let videoController = controller as? VideoViewController {
scrubber.player = videoController.player
}

if let videoController = controller as? VideoRawViewController {
scrubber.player = videoController.player
}
}

public func itemControllerWillDisappear(_ controller: ItemController) {

if let _ = controller as? VideoViewController {
if let _ = controller as? ItemBaseController<VideoView> {

scrubber.player = nil

Expand Down Expand Up @@ -661,6 +671,17 @@ open class GalleryViewController: UIPageViewController, ItemControllerDelegate {
})
}
}

if let videoController = controller as? VideoRawViewController {
scrubber.player = videoController.player
if scrubber.alpha == 0 && decorationViewsHidden == false {

UIView.animate(withDuration: 0.3, animations: { [weak self] in

self?.scrubber.alpha = 1
})
}
}
}

open func itemControllerDidSingleTap(_ controller: ItemController) {
Expand Down
18 changes: 17 additions & 1 deletion ImageViewer/Source/ItemBaseController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe
//UI
public var itemView = T()
let scrollView = UIScrollView()
let backgroundView = UIImageView()
let activityIndicatorView = UIActivityIndicatorView(style: .white)

//DELEGATE / DATASOURCE
Expand Down Expand Up @@ -108,6 +109,7 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe

self.itemView.isHidden = isInitialController

configureBackgroundView()
configureScrollView()
configureGestureRecognizers()

Expand All @@ -124,6 +126,17 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe

// MARK: - Configuration

fileprivate func configureBackgroundView(){
backgroundView.contentMode = .scaleToFill
let _frame = UIApplication.shared.keyWindow!.frame
backgroundView.frame = _frame
let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = backgroundView.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
backgroundView.addSubview(blurEffectView)
}

fileprivate func configureScrollView() {

scrollView.showsHorizontalScrollIndicator = false
Expand Down Expand Up @@ -177,7 +190,7 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe
}

fileprivate func createViewHierarchy() {

self.view.addSubview(backgroundView)
self.view.addSubview(scrollView)
scrollView.addSubview(itemView)

Expand Down Expand Up @@ -206,6 +219,7 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe

var itemView = self?.itemView
itemView?.image = image
self?.backgroundView.image = image
itemView?.isAccessibilityElement = image.isAccessibilityElement
itemView?.accessibilityLabel = image.accessibilityLabel
itemView?.accessibilityTraits = image.accessibilityTraits
Expand Down Expand Up @@ -240,6 +254,8 @@ open class ItemBaseController<T: UIView>: UIViewController, ItemController, UIGe

scrollView.frame = self.view.bounds
activityIndicatorView.center = view.boundsCenter
let _frame = UIApplication.shared.keyWindow!.frame
backgroundView.frame = _frame

if let size = itemView.image?.size , size != CGSize.zero {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class ThumbnailsViewController: UICollectionViewController, UICollectionViewDele
}
}

case .video(let fetchImageBlock, _):
case .video(let fetchImageBlock, _),.rawVideo(fetchPreviewImageBlock: let fetchImageBlock, _):

fetchImageBlock() { image in

Expand Down
Loading