Compare commits
14 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e87ec9eb72 | |
|
|
2db02eecc0 | |
|
|
d40c5d2c2e | |
|
|
5714a95908 | |
|
|
8d2c1f3b38 | |
|
|
464114e40d | |
|
|
c3f8fa7e8a | |
|
|
3b275293b5 | |
|
|
6a591bcd5d | |
|
|
26378bae91 | |
|
|
709f024135 | |
|
|
49131da2e0 | |
|
|
1704f37363 | |
|
|
554dac6756 |
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -1,5 +1,20 @@
|
|||
# Change Log
|
||||
|
||||
## 3.1.2
|
||||
|
||||
Released on 16-9-2016
|
||||
|
||||
#### Fixed
|
||||
- Scrolling performance slowed #145
|
||||
|
||||
## 3.1.1
|
||||
|
||||
Released on 15-9-2016
|
||||
|
||||
#### Fixed
|
||||
- Example crash in xcode8 fixed
|
||||
- Provides various UI configuration options via SKPhotoBrowserOptions. #144
|
||||
|
||||
## 3.1.0
|
||||
|
||||
Released on 9-2016
|
||||
|
|
@ -7,7 +22,7 @@ Released on 9-2016
|
|||
#### Fixed
|
||||
- Issue with multiple actionButtonTitles #137
|
||||
- fix swiftlint warnings #140
|
||||
- Update for Xcode GM. #141
|
||||
- Update for Xcode 8 GM (swift 2.3). #141
|
||||
|
||||
## 3.0.2
|
||||
|
||||
|
|
@ -16,7 +31,7 @@ Released on 9-2016
|
|||
#### Fixed
|
||||
- Issue with multiple actionButtonTitles #137
|
||||
- Impossible to zoom when resolution is 1024x768 #134
|
||||
- unexpectedly found nil while unwrapping an Optional value #133
|
||||
- Crash bug at zooming scrool view #133
|
||||
|
||||
## 3.0.1
|
||||
|
||||
|
|
|
|||
49
README.md
49
README.md
|
|
@ -1,6 +1,7 @@
|
|||
SKPhotoBrowser
|
||||
========================
|
||||
|
||||

|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoadocs.org/docsets/SKPhotoBrowser)
|
||||
|
||||
|
|
@ -106,14 +107,39 @@ func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath i
|
|||
You can customize Toolbar via SKPhotoBrowserOptions.
|
||||
|
||||
```swift
|
||||
SKPhotoBrowserOptions.displayToolbar = false // all tool bar will be hidden
|
||||
SKPhotoBrowserOptions.displayCounterLabel = false // counter label will be hidden
|
||||
SKPhotoBrowserOptions.displayBackAndForwardButton = false // back / forward button will be hidden
|
||||
SKPhotoBrowserOptions.displayAction = false // action button will be hidden
|
||||
SKPhotoBrowserOptions.displayDeleteButton = true // delete button will be shown
|
||||
SKPhotoBrowserOptions.displayToolbar = false // all tool bar will be hidden
|
||||
SKPhotoBrowserOptions.displayCounterLabel = false // counter label will be hidden
|
||||
SKPhotoBrowserOptions.displayBackAndForwardButton = false // back / forward button will be hidden
|
||||
SKPhotoBrowserOptions.displayAction = false // action button will be hidden
|
||||
SKPhotoBrowserOptions.displayDeleteButton = true // delete button will be shown
|
||||
SKPhotoBrowserOptions.displayHorizontalScrollIndicator = false // horizontal scroll bar will be hidden
|
||||
SKPhotoBrowserOptions.displayVerticalScrollIndicator = false // vertical scroll bar will be hidden
|
||||
let browser = SKPhotoBrowser(originImage: originImage, photos: images, animatedFromView: cell)
|
||||
```
|
||||
|
||||
#### Colors
|
||||
You can customize text, icon and background colors via SKPhotoBrowserOptions
|
||||
```swift
|
||||
SKPhotoBrowserOptions.backgroundColor = UIColor.whiteColor() // browser view will be white
|
||||
SKPhotoBrowserOptions.textAndIconColor = UIColor.blackColor() // text and icons will be black
|
||||
SKPhotoBrowserOptions.toolbarTextShadowColor = UIColor.clearColor() // shadow of toolbar text will be removed
|
||||
SKPhotoBrowserOptions.toolbarFont = UIFont(name: "Futura", size: 16.0) // font of toolbar will be 'Futura'
|
||||
SKPhotoBrowserOptions.captionFont = UIFont(name: "Helvetica", size: 18.0) // font of toolbar will be 'Helvetica'
|
||||
```
|
||||
|
||||
#### Images
|
||||
You can customize the padding of displayed images via SKPhotoBrowserOptions
|
||||
```swift
|
||||
SKPhotoBrowserOptions.imagePaddingX = 50 // image padding left and right will be 25
|
||||
SKPhotoBrowserOptions.imagePaddingY = 50 // image padding top and bottom will be 25
|
||||
```
|
||||
|
||||
#### Statusbar
|
||||
You can customize the visibility of the Statusbar in browser view via SKPhotoBrowserOptions
|
||||
```swift
|
||||
SKPhotoBrowserOptions.displayStatusbar = false // status bar will be hidden
|
||||
```
|
||||
|
||||
#### Custom Cache From Web URL
|
||||
You can use SKCacheable protocol if others are adaptable. (SKImageCacheable or SKRequestResponseCacheable)
|
||||
|
||||
|
|
@ -130,8 +156,8 @@ SKCache.sharedCache.imageCache = CustomImageCache()
|
|||
#### CustomButton Image
|
||||
Close, Delete buttons are able to change image and frame.
|
||||
``` swift
|
||||
browser.browser.updateCloseButton(UIImage())
|
||||
browser.browser.updateUpdateButton(UIImage())
|
||||
browser.updateCloseButton(UIImage())
|
||||
browser.updateUpdateButton(UIImage())
|
||||
```
|
||||
|
||||
#### Delete Photo
|
||||
|
|
@ -149,8 +175,7 @@ images.append(photo)
|
|||
#### SwipeGesture
|
||||
vertical swipe can enable/disable:
|
||||
``` swift
|
||||
let browser = SKPhotoBrowser(originImage: originImage, photos: images, animatedFromView: cell)
|
||||
browser.disableVerticalSwipe = true
|
||||
SKPhotoBrowserOptions.disableVerticalSwipe = true
|
||||
```
|
||||
|
||||
#### Delegate
|
||||
|
|
@ -183,10 +208,12 @@ func didDismissAtPageIndex(index: Int) {
|
|||
|
||||
```
|
||||
|
||||
#### Minor Option
|
||||
- blackArea handling which is appearing outside of photo
|
||||
#### Options
|
||||
You can access via `SKPhotoBrowserOptions`, which can use for browser control.
|
||||
- single tap handling, dismiss/noaction
|
||||
- blackArea handling which is appearing outside of photo
|
||||
- bounce animation when appearing/dismissing
|
||||
- text color, font, or more
|
||||
``` swift
|
||||
SKPhotoBrowserOptions.enableZoomBlackArea = true // default true
|
||||
SKPhotoBrowserOptions.enableSingleTapDismiss = true // default false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "SKPhotoBrowser"
|
||||
s.version = "3.1.0"
|
||||
s.version = "3.1.2"
|
||||
s.summary = "Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift2.0."
|
||||
s.homepage = "https://github.com/suzuki-0000/SKPhotoBrowser"
|
||||
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0A6BA1F31DAE0E2700778221 /* SKNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BA1F21DAE0E2700778221 /* SKNavigationBar.swift */; };
|
||||
0AE527521DABB87500619FAD /* SKNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE527511DABB87500619FAD /* SKNavigationBar.swift */; };
|
||||
210E53ED1C986D3A008DD5E3 /* UIView+Radius.swift in Sources */ = {isa = PBXBuildFile; fileRef = 210E53EC1C986D3A008DD5E3 /* UIView+Radius.swift */; };
|
||||
210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 210E53EE1C986D57008DD5E3 /* UIImage+Rotation.swift */; };
|
||||
26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C97AD41D0EB6870039F6CB /* SKCache.swift */; };
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0A6BA1F21DAE0E2700778221 /* SKNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKNavigationBar.swift; sourceTree = "<group>"; };
|
||||
0AE527511DABB87500619FAD /* SKNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKNavigationBar.swift; sourceTree = "<group>"; };
|
||||
210E53EC1C986D3A008DD5E3 /* UIView+Radius.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIView+Radius.swift"; path = "extensions/UIView+Radius.swift"; sourceTree = "<group>"; };
|
||||
210E53EE1C986D57008DD5E3 /* UIImage+Rotation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIImage+Rotation.swift"; path = "extensions/UIImage+Rotation.swift"; sourceTree = "<group>"; };
|
||||
26C97AD41D0EB6870039F6CB /* SKCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKCache.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -137,8 +137,8 @@
|
|||
8909B53F1BC791510060A053 /* SKPhoto.swift */,
|
||||
8909B5411BC791510060A053 /* SKPhotoBrowser.swift */,
|
||||
89C24A811D657AD1005F09A9 /* SKPhotoBrowserOptions.swift */,
|
||||
0A6BA1F21DAE0E2700778221 /* SKNavigationBar.swift */,
|
||||
890A6F1F1D5D9E53003B01F0 /* SKToolbar.swift */,
|
||||
0AE527511DABB87500619FAD /* SKNavigationBar.swift */,
|
||||
8909B5331BC791280060A053 /* SKPhotoBrowser.h */,
|
||||
8917B1AF1D5A13DE000CE1C4 /* SKPhotoBrowserDelegate.swift */,
|
||||
89D0BA481D59966B002A811B /* SKMesurement.swift */,
|
||||
|
|
@ -218,7 +218,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 0700;
|
||||
ORGANIZATIONNAME = suzuki_keishi;
|
||||
TargetAttributes = {
|
||||
8909B52F1BC791280060A053 = {
|
||||
|
|
@ -303,7 +303,7 @@
|
|||
8917B1B41D5A14B0000CE1C4 /* SKButtons.swift in Sources */,
|
||||
89C24A821D657AD1005F09A9 /* SKPhotoBrowserOptions.swift in Sources */,
|
||||
26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */,
|
||||
0A6BA1F31DAE0E2700778221 /* SKNavigationBar.swift in Sources */,
|
||||
0AE527521DABB87500619FAD /* SKNavigationBar.swift in Sources */,
|
||||
210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */,
|
||||
8909B5431BC791510060A053 /* SKCaptionView.swift in Sources */,
|
||||
8909B5491BC791510060A053 /* SKPhotoBrowser.swift in Sources */,
|
||||
|
|
@ -344,10 +344,8 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -394,10 +392,8 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -417,7 +413,6 @@
|
|||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
@ -429,7 +424,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
|
@ -442,7 +436,7 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -450,7 +444,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
|
@ -462,7 +455,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.keishi.suzuki.SKPhotoBrowser;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "0700"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
|
|
|||
|
|
@ -10,13 +10,12 @@ import UIKit
|
|||
|
||||
|
||||
@objc public protocol SKPhotoBrowserAnimatorDelegate {
|
||||
func willPresent(_ browser: SKPhotoBrowser)
|
||||
func willDismiss(_ browser: SKPhotoBrowser, sender: UIView?)
|
||||
func willPresent(browser: SKPhotoBrowser)
|
||||
func willDismiss(browser: SKPhotoBrowser)
|
||||
}
|
||||
|
||||
class SKAnimator: NSObject, SKPhotoBrowserAnimatorDelegate {
|
||||
var resizableImageView: UIImageView?
|
||||
var parentViewController: UIViewController?
|
||||
|
||||
var senderOriginImage: UIImage!
|
||||
var senderViewOriginalFrame: CGRect = .zero
|
||||
|
|
@ -25,7 +24,7 @@ class SKAnimator: NSObject, SKPhotoBrowserAnimatorDelegate {
|
|||
var finalImageViewFrame: CGRect = .zero
|
||||
|
||||
var bounceAnimation: Bool = false
|
||||
var animationDuration: TimeInterval {
|
||||
var animationDuration: NSTimeInterval {
|
||||
if SKPhotoBrowserOptions.bounceAnimation {
|
||||
return 0.5
|
||||
}
|
||||
|
|
@ -38,8 +37,8 @@ class SKAnimator: NSObject, SKPhotoBrowserAnimatorDelegate {
|
|||
return 1
|
||||
}
|
||||
|
||||
func willPresent(_ browser: SKPhotoBrowser) {
|
||||
guard let appWindow = UIApplication.shared.delegate?.window else {
|
||||
func willPresent(browser: SKPhotoBrowser) {
|
||||
guard let appWindow = UIApplication.sharedApplication().delegate?.window else {
|
||||
return
|
||||
}
|
||||
guard let window = appWindow else {
|
||||
|
|
@ -71,20 +70,23 @@ class SKAnimator: NSObject, SKPhotoBrowserAnimatorDelegate {
|
|||
presentAnimation(browser)
|
||||
}
|
||||
|
||||
func willDismiss(_ browser: SKPhotoBrowser, sender: UIView?) {
|
||||
guard let sender = sender, let image = browser.photoAtIndex(browser.currentPageIndex).underlyingImage,
|
||||
let scrollView = browser.pageDisplayedAtIndex(browser.currentPageIndex) else {
|
||||
|
||||
self.resizableImageView?.removeFromSuperview()
|
||||
browser.dismissPhotoBrowser(animated: true)
|
||||
func willDismiss(browser: SKPhotoBrowser) {
|
||||
guard let sender = browser.delegate?.viewForPhoto?(browser, index: browser.currentPageIndex),
|
||||
image = browser.photoAtIndex(browser.currentPageIndex).underlyingImage,
|
||||
scrollView = browser.pageDisplayedAtIndex(browser.currentPageIndex) else {
|
||||
|
||||
senderViewForAnimation?.hidden = false
|
||||
browser.dismissPhotoBrowser(animated: false)
|
||||
return
|
||||
}
|
||||
|
||||
senderViewForAnimation = sender
|
||||
browser.view.isHidden = true
|
||||
|
||||
browser.view.hidden = true
|
||||
browser.backgroundView.hidden = false
|
||||
browser.backgroundView.alpha = 1
|
||||
|
||||
senderViewOriginalFrame = calcOriginFrame(sender)
|
||||
|
||||
|
||||
let photo = browser.photoAtIndex(browser.currentPageIndex)
|
||||
let contentOffset = scrollView.contentOffset
|
||||
let scrollFrame = scrollView.photoImageView.frame
|
||||
|
|
@ -95,35 +97,34 @@ class SKAnimator: NSObject, SKPhotoBrowserAnimatorDelegate {
|
|||
width: scrollFrame.width,
|
||||
height: scrollFrame.height)
|
||||
|
||||
// resizableImageView.image = scrollView.photo?.underlyingImage?.rotateImageByOrientation()
|
||||
resizableImageView!.image = image.rotateImageByOrientation()
|
||||
resizableImageView!.frame = frame
|
||||
resizableImageView!.alpha = 1.0
|
||||
resizableImageView!.clipsToBounds = true
|
||||
resizableImageView!.contentMode = photo.contentMode
|
||||
if let view = senderViewForAnimation, view.layer.cornerRadius != 0 {
|
||||
if let view = senderViewForAnimation where view.layer.cornerRadius != 0 {
|
||||
let duration = (animationDuration * Double(animationDamping))
|
||||
resizableImageView!.layer.masksToBounds = true
|
||||
resizableImageView!.addCornerRadiusAnimation(0, to: view.layer.cornerRadius, duration: duration)
|
||||
}
|
||||
|
||||
parentViewController?.view.insertSubview(resizableImageView!, at: 1)
|
||||
|
||||
dismissAnimation(browser)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SKAnimator {
|
||||
func calcOriginFrame(_ sender: UIView) -> CGRect {
|
||||
if let senderViewOriginalFrameTemp = sender.superview?.convert(sender.frame, to:nil) {
|
||||
func calcOriginFrame(sender: UIView) -> CGRect {
|
||||
if let senderViewOriginalFrameTemp = sender.superview?.convertRect(sender.frame, toView:nil) {
|
||||
return senderViewOriginalFrameTemp
|
||||
} else if let senderViewOriginalFrameTemp = sender.layer.superlayer?.convert(sender.frame, to: nil) {
|
||||
} else if let senderViewOriginalFrameTemp = sender.layer.superlayer?.convertRect(sender.frame, toLayer: nil) {
|
||||
return senderViewOriginalFrameTemp
|
||||
} else {
|
||||
return .zero
|
||||
}
|
||||
}
|
||||
|
||||
func calcFinalFrame(_ imageRatio: CGFloat) -> CGRect {
|
||||
func calcFinalFrame(imageRatio: CGFloat) -> CGRect {
|
||||
if SKMesurement.screenRatio < imageRatio {
|
||||
let width = SKMesurement.screenWidth
|
||||
let height = width / imageRatio
|
||||
|
|
@ -139,16 +140,16 @@ private extension SKAnimator {
|
|||
}
|
||||
|
||||
private extension SKAnimator {
|
||||
func presentAnimation(_ browser: SKPhotoBrowser, completion: ((Void) -> Void)? = nil) {
|
||||
browser.view.isHidden = true
|
||||
func presentAnimation(browser: SKPhotoBrowser, completion: (Void -> Void)? = nil) {
|
||||
browser.view.hidden = true
|
||||
browser.view.alpha = 0.0
|
||||
|
||||
UIView.animate(
|
||||
withDuration: animationDuration,
|
||||
UIView.animateWithDuration(
|
||||
animationDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping:animationDamping,
|
||||
initialSpringVelocity:0,
|
||||
options:UIViewAnimationOptions(),
|
||||
options:.CurveEaseInOut,
|
||||
animations: {
|
||||
browser.showButtons()
|
||||
browser.backgroundView.alpha = 1.0
|
||||
|
|
@ -156,21 +157,23 @@ private extension SKAnimator {
|
|||
self.resizableImageView?.frame = self.finalImageViewFrame
|
||||
},
|
||||
completion: { (Bool) -> Void in
|
||||
browser.view.isHidden = false
|
||||
UIApplication.sharedApplication().setStatusBarHidden(!SKPhotoBrowserOptions.displayStatusbar, withAnimation: .Fade)
|
||||
|
||||
browser.view.hidden = false
|
||||
browser.view.alpha = 1.0
|
||||
browser.backgroundView.isHidden = true
|
||||
browser.backgroundView.hidden = true
|
||||
|
||||
self.resizableImageView?.alpha = 0.0
|
||||
})
|
||||
}
|
||||
|
||||
func dismissAnimation(_ browser: SKPhotoBrowser, completion: ((Void) -> Void)? = nil) {
|
||||
UIView.animate(
|
||||
withDuration: animationDuration,
|
||||
func dismissAnimation(browser: SKPhotoBrowser, completion: (Void -> Void)? = nil) {
|
||||
UIView.animateWithDuration(
|
||||
animationDuration,
|
||||
delay:0,
|
||||
usingSpringWithDamping:animationDamping,
|
||||
initialSpringVelocity:0,
|
||||
options:UIViewAnimationOptions(),
|
||||
options:.CurveEaseInOut,
|
||||
animations: {
|
||||
browser.backgroundView.alpha = 0.0
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
import Foundation
|
||||
|
||||
// helpers which often used
|
||||
private let bundle = Bundle(for: SKPhotoBrowser.self)
|
||||
private let bundle = NSBundle(forClass: SKPhotoBrowser.self)
|
||||
|
||||
class SKButton: UIButton {
|
||||
var showFrame: CGRect!
|
||||
|
|
@ -17,7 +17,7 @@ class SKButton: UIButton {
|
|||
var insets: UIEdgeInsets {
|
||||
|
||||
|
||||
return UI_USER_INTERFACE_IDIOM() == .phone
|
||||
return UI_USER_INTERFACE_IDIOM() == .Phone
|
||||
? UIEdgeInsets(top: 15.25, left: 15.25, bottom: 15.25, right: 15.25) : UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
|
||||
}
|
||||
var size: CGSize = CGSize(width: 44, height: 44)
|
||||
|
|
@ -25,21 +25,22 @@ class SKButton: UIButton {
|
|||
|
||||
var buttonTopOffset: CGFloat { return 5 }
|
||||
|
||||
func setup(_ imageName: String) {
|
||||
backgroundColor = UIColor.clear
|
||||
func setup(imageName: String) {
|
||||
backgroundColor = .clearColor()
|
||||
tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
imageEdgeInsets = insets
|
||||
// clipsToBounds = true
|
||||
translatesAutoresizingMaskIntoConstraints = true
|
||||
autoresizingMask = [.flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin]
|
||||
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
|
||||
|
||||
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
|
||||
in: bundle, compatibleWith: nil) ?? UIImage()
|
||||
setImage(image, for: UIControlState())
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage()
|
||||
setImage(image, forState: .Normal)
|
||||
}
|
||||
|
||||
func updateFrame() { }
|
||||
|
||||
func setFrameSize(_ size: CGSize) {
|
||||
func setFrameSize(size: CGSize) {
|
||||
let newRect = CGRect(x: margin, y: buttonTopOffset, width: size.width, height: size.height)
|
||||
self.frame = newRect
|
||||
showFrame = newRect
|
||||
|
|
@ -80,7 +81,7 @@ class SKDeleteButton: SKButton {
|
|||
override func updateFrame() {
|
||||
}
|
||||
|
||||
override func setFrameSize(_ size: CGSize) {
|
||||
override func setFrameSize(size: CGSize) {
|
||||
let newRect = CGRect(x: SKMesurement.screenWidth - size.width, y: buttonTopOffset, width: size.width, height: size.height)
|
||||
self.frame = newRect
|
||||
showFrame = newRect
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
open class SKCache {
|
||||
open static let sharedCache = SKCache()
|
||||
open var imageCache: SKCacheable
|
||||
public class SKCache {
|
||||
public static let sharedCache = SKCache()
|
||||
public var imageCache: SKCacheable
|
||||
|
||||
init() {
|
||||
self.imageCache = SKDefaultImageCache()
|
||||
}
|
||||
|
||||
open func imageForKey(_ key: String) -> UIImage? {
|
||||
public func imageForKey(key: String) -> UIImage? {
|
||||
guard let cache = imageCache as? SKImageCacheable else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ open class SKCache {
|
|||
return cache.imageForKey(key)
|
||||
}
|
||||
|
||||
open func setImage(_ image: UIImage, forKey key: String) {
|
||||
public func setImage(image: UIImage, forKey key: String) {
|
||||
guard let cache = imageCache as? SKImageCacheable else {
|
||||
return
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ open class SKCache {
|
|||
cache.setImage(image, forKey: key)
|
||||
}
|
||||
|
||||
open func removeImageForKey(_ key: String) {
|
||||
public func removeImageForKey(key: String) {
|
||||
guard let cache = imageCache as? SKImageCacheable else {
|
||||
return
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ open class SKCache {
|
|||
cache.removeImageForKey(key)
|
||||
}
|
||||
|
||||
open func imageForRequest(_ request: URLRequest) -> UIImage? {
|
||||
public func imageForRequest(request: NSURLRequest) -> UIImage? {
|
||||
guard let cache = imageCache as? SKRequestResponseCacheable else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -51,31 +51,31 @@ open class SKCache {
|
|||
return nil
|
||||
}
|
||||
|
||||
open func setImageData(_ data: Data, response: URLResponse, request: URLRequest) {
|
||||
public func setImageData(data: NSData, response: NSURLResponse, request: NSURLRequest) {
|
||||
guard let cache = imageCache as? SKRequestResponseCacheable else {
|
||||
return
|
||||
}
|
||||
let cachedResponse = CachedURLResponse(response: response, data: data)
|
||||
let cachedResponse = NSCachedURLResponse(response: response, data: data)
|
||||
cache.storeCachedResponse(cachedResponse, forRequest: request)
|
||||
}
|
||||
}
|
||||
|
||||
class SKDefaultImageCache: SKImageCacheable {
|
||||
var cache: NSCache<AnyObject, AnyObject>
|
||||
var cache: NSCache
|
||||
|
||||
init() {
|
||||
cache = NSCache()
|
||||
}
|
||||
|
||||
func imageForKey(_ key: String) -> UIImage? {
|
||||
return cache.object(forKey: key as AnyObject) as? UIImage
|
||||
func imageForKey(key: String) -> UIImage? {
|
||||
return cache.objectForKey(key) as? UIImage
|
||||
}
|
||||
|
||||
func setImage(_ image: UIImage, forKey key: String) {
|
||||
cache.setObject(image, forKey: key as AnyObject)
|
||||
func setImage(image: UIImage, forKey key: String) {
|
||||
cache.setObject(image, forKey: key)
|
||||
}
|
||||
|
||||
func removeImageForKey(_ key: String) {
|
||||
cache.removeObject(forKey: key as AnyObject)
|
||||
func removeImageForKey(key: String) {
|
||||
cache.removeObjectForKey(key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import UIKit.UIImage
|
|||
|
||||
public protocol SKCacheable {}
|
||||
public protocol SKImageCacheable: SKCacheable {
|
||||
func imageForKey(_ key: String) -> UIImage?
|
||||
func setImage(_ image: UIImage, forKey key: String)
|
||||
func removeImageForKey(_ key: String)
|
||||
func imageForKey(key: String) -> UIImage?
|
||||
func setImage(image: UIImage, forKey key: String)
|
||||
func removeImageForKey(key: String)
|
||||
}
|
||||
|
||||
public protocol SKRequestResponseCacheable: SKCacheable {
|
||||
func cachedResponseForRequest(_ request: URLRequest) -> CachedURLResponse?
|
||||
func storeCachedResponse(_ cachedResponse: CachedURLResponse, forRequest request: URLRequest)
|
||||
func cachedResponseForRequest(request: NSURLRequest) -> NSCachedURLResponse?
|
||||
func storeCachedResponse(cachedResponse: NSCachedURLResponse, forRequest request: NSURLRequest)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,31 +7,11 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
fileprivate func < <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (l?, r?):
|
||||
return l < r
|
||||
case (nil, _?):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func > <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (l?, r?):
|
||||
return l > r
|
||||
default:
|
||||
return rhs < lhs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open class SKCaptionView: UIView {
|
||||
fileprivate var photo: SKPhotoProtocol?
|
||||
fileprivate var photoLabel: UILabel!
|
||||
fileprivate var photoLabelPadding: CGFloat = 10
|
||||
public class SKCaptionView: UIView {
|
||||
private var photo: SKPhotoProtocol?
|
||||
private var photoLabel: UILabel!
|
||||
private var photoLabelPadding: CGFloat = 10
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
|
|
@ -42,13 +22,13 @@ open class SKCaptionView: UIView {
|
|||
}
|
||||
|
||||
public convenience init(photo: SKPhotoProtocol) {
|
||||
let screenBound = UIScreen.main.bounds
|
||||
let screenBound = UIScreen.mainScreen().bounds
|
||||
self.init(frame: CGRect(x: 0, y: 0, width: screenBound.size.width, height: screenBound.size.height))
|
||||
self.photo = photo
|
||||
setup()
|
||||
}
|
||||
|
||||
open override func sizeThatFits(_ size: CGSize) -> CGSize {
|
||||
public override func sizeThatFits(size: CGSize) -> CGSize {
|
||||
guard let text = photoLabel.text else {
|
||||
return CGSize.zero
|
||||
}
|
||||
|
|
@ -61,7 +41,7 @@ open class SKCaptionView: UIView {
|
|||
let height: CGFloat = photoLabel.font.lineHeight * CGFloat(photoLabel.numberOfLines)
|
||||
|
||||
let attributedText = NSAttributedString(string: text, attributes: [NSFontAttributeName: font])
|
||||
let textSize = attributedText.boundingRect(with: CGSize(width: width, height: height), options: .usesLineFragmentOrigin, context: nil).size
|
||||
let textSize = attributedText.boundingRectWithSize(CGSize(width: width, height: height), options: .UsesLineFragmentOrigin, context: nil).size
|
||||
|
||||
return CGSize(width: textSize.width, height: textSize.height + photoLabelPadding * 2)
|
||||
}
|
||||
|
|
@ -69,8 +49,8 @@ open class SKCaptionView: UIView {
|
|||
|
||||
private extension SKCaptionView {
|
||||
func setup() {
|
||||
isOpaque = false
|
||||
autoresizingMask = [.flexibleWidth, .flexibleTopMargin, .flexibleRightMargin, .flexibleLeftMargin]
|
||||
opaque = false
|
||||
autoresizingMask = [.FlexibleWidth, .FlexibleTopMargin, .FlexibleRightMargin, .FlexibleLeftMargin]
|
||||
|
||||
// setup photoLabel
|
||||
setupPhotoLabel()
|
||||
|
|
@ -78,16 +58,16 @@ private extension SKCaptionView {
|
|||
|
||||
func setupPhotoLabel() {
|
||||
photoLabel = UILabel(frame: CGRect(x: photoLabelPadding, y: 0, width: bounds.size.width - (photoLabelPadding * 2), height: bounds.size.height))
|
||||
photoLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
photoLabel.isOpaque = false
|
||||
photoLabel.backgroundColor = UIColor.clear
|
||||
photoLabel.textColor = UIColor.white
|
||||
photoLabel.textAlignment = .center
|
||||
photoLabel.lineBreakMode = .byTruncatingTail
|
||||
photoLabel.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
||||
photoLabel.opaque = false
|
||||
photoLabel.backgroundColor = .clearColor()
|
||||
photoLabel.textColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
photoLabel.textAlignment = .Center
|
||||
photoLabel.lineBreakMode = .ByTruncatingTail
|
||||
photoLabel.numberOfLines = 3
|
||||
photoLabel.shadowColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
photoLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
|
||||
photoLabel.font = UIFont.systemFont(ofSize: 17.0)
|
||||
photoLabel.font = SKPhotoBrowserOptions.captionFont
|
||||
photoLabel.text = photo?.caption
|
||||
addSubview(photoLabel)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
import UIKit
|
||||
|
||||
@objc protocol SKDetectingImageViewDelegate {
|
||||
func handleImageViewSingleTap(_ touchPoint: CGPoint)
|
||||
func handleImageViewDoubleTap(_ touchPoint: CGPoint)
|
||||
func handleImageViewSingleTap(touchPoint: CGPoint)
|
||||
func handleImageViewDoubleTap(touchPoint: CGPoint)
|
||||
}
|
||||
|
||||
class SKDetectingImageView: UIImageView {
|
||||
|
|
@ -26,25 +26,25 @@ class SKDetectingImageView: UIImageView {
|
|||
setup()
|
||||
}
|
||||
|
||||
func handleDoubleTap(_ recognizer: UITapGestureRecognizer) {
|
||||
delegate?.handleImageViewDoubleTap(recognizer.location(in: self))
|
||||
func handleDoubleTap(recognizer: UITapGestureRecognizer) {
|
||||
delegate?.handleImageViewDoubleTap(recognizer.locationInView(self))
|
||||
}
|
||||
|
||||
func handleSingleTap(_ recognizer: UITapGestureRecognizer) {
|
||||
delegate?.handleImageViewSingleTap(recognizer.location(in: self))
|
||||
func handleSingleTap(recognizer: UITapGestureRecognizer) {
|
||||
delegate?.handleImageViewSingleTap(recognizer.locationInView(self))
|
||||
}
|
||||
}
|
||||
|
||||
private extension SKDetectingImageView {
|
||||
func setup() {
|
||||
isUserInteractionEnabled = true
|
||||
userInteractionEnabled = true
|
||||
|
||||
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
|
||||
doubleTap.numberOfTapsRequired = 2
|
||||
addGestureRecognizer(doubleTap)
|
||||
|
||||
let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap(_:)))
|
||||
singleTap.require(toFail: doubleTap)
|
||||
singleTap.requireGestureRecognizerToFail(doubleTap)
|
||||
addGestureRecognizer(singleTap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,17 +9,17 @@
|
|||
import UIKit
|
||||
|
||||
@objc protocol SKDetectingViewDelegate {
|
||||
func handleSingleTap(_ view: UIView, touch: UITouch)
|
||||
func handleDoubleTap(_ view: UIView, touch: UITouch)
|
||||
func handleSingleTap(view: UIView, touch: UITouch)
|
||||
func handleDoubleTap(view: UIView, touch: UITouch)
|
||||
}
|
||||
|
||||
class SKDetectingView: UIView {
|
||||
weak var delegate: SKDetectingViewDelegate?
|
||||
|
||||
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||
super.touchesEnded(touches, with: event)
|
||||
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
|
||||
super.touchesEnded(touches, withEvent: event)
|
||||
defer {
|
||||
_ = next
|
||||
nextResponder()
|
||||
}
|
||||
|
||||
guard let touch = touches.first else {
|
||||
|
|
@ -32,11 +32,11 @@ class SKDetectingView: UIView {
|
|||
}
|
||||
}
|
||||
|
||||
func handleSingleTap(_ touch: UITouch) {
|
||||
func handleSingleTap(touch: UITouch) {
|
||||
delegate?.handleSingleTap(self, touch: touch)
|
||||
}
|
||||
|
||||
func handleDoubleTap(_ touch: UITouch) {
|
||||
func handleDoubleTap(touch: UITouch) {
|
||||
delegate?.handleDoubleTap(self, touch: touch)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ class SKIndicatorView: UIActivityIndicatorView {
|
|||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
center = CGPoint(x: frame.width / 2, y: frame.height / 2)
|
||||
activityIndicatorViewStyle = .whiteLarge
|
||||
activityIndicatorViewStyle = SKPhotoBrowserOptions.backgroundColor.isEqual(UIColor.whiteColor()) ? .Gray : .WhiteLarge
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@
|
|||
import UIKit
|
||||
|
||||
// MARK: - SKLocalPhoto
|
||||
open class SKLocalPhoto: NSObject, SKPhotoProtocol {
|
||||
public class SKLocalPhoto: NSObject, SKPhotoProtocol {
|
||||
|
||||
open var underlyingImage: UIImage!
|
||||
open var photoURL: String!
|
||||
open var contentMode: UIViewContentMode = .scaleToFill
|
||||
open var shouldCachePhotoURLImage: Bool = false
|
||||
open var caption: String!
|
||||
open var index: Int = 0
|
||||
public var underlyingImage: UIImage!
|
||||
public var photoURL: String!
|
||||
public var contentMode: UIViewContentMode = .ScaleToFill
|
||||
public var shouldCachePhotoURLImage: Bool = false
|
||||
public var caption: String!
|
||||
public var index: Int = 0
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
|
@ -33,9 +33,9 @@ open class SKLocalPhoto: NSObject, SKPhotoProtocol {
|
|||
underlyingImage = holder
|
||||
}
|
||||
|
||||
open func checkCache() {}
|
||||
public func checkCache() {}
|
||||
|
||||
open func loadUnderlyingImageAndNotify() {
|
||||
public func loadUnderlyingImageAndNotify() {
|
||||
|
||||
if underlyingImage != nil && photoURL == nil {
|
||||
loadUnderlyingImageComplete()
|
||||
|
|
@ -43,8 +43,8 @@ open class SKLocalPhoto: NSObject, SKPhotoProtocol {
|
|||
|
||||
if photoURL != nil {
|
||||
// Fetch Image
|
||||
if FileManager.default.fileExists(atPath: photoURL) {
|
||||
if let data = FileManager.default.contents(atPath: photoURL) {
|
||||
if NSFileManager.defaultManager().fileExistsAtPath(photoURL) {
|
||||
if let data = NSFileManager.defaultManager().contentsAtPath(photoURL) {
|
||||
self.loadUnderlyingImageComplete()
|
||||
if let image = UIImage(data: data) {
|
||||
self.underlyingImage = image
|
||||
|
|
@ -55,16 +55,16 @@ open class SKLocalPhoto: NSObject, SKPhotoProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
open func loadUnderlyingImageComplete() {
|
||||
NotificationCenter.default.post(name: Notification.Name(rawValue: SKPHOTO_LOADING_DID_END_NOTIFICATION), object: self)
|
||||
public func loadUnderlyingImageComplete() {
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(SKPHOTO_LOADING_DID_END_NOTIFICATION, object: self)
|
||||
}
|
||||
|
||||
// MARK: - class func
|
||||
open class func photoWithImageURL(_ url: String) -> SKLocalPhoto {
|
||||
public class func photoWithImageURL(url: String) -> SKLocalPhoto {
|
||||
return SKLocalPhoto(url: url)
|
||||
}
|
||||
|
||||
open class func photoWithImageURL(_ url: String, holder: UIImage?) -> SKLocalPhoto {
|
||||
public class func photoWithImageURL(url: String, holder: UIImage?) -> SKLocalPhoto {
|
||||
return SKLocalPhoto(url: url, holder: holder)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ import Foundation
|
|||
import UIKit
|
||||
|
||||
struct SKMesurement {
|
||||
static let isPhone: Bool = UIDevice.current.userInterfaceIdiom == .phone
|
||||
static let isPad: Bool = UIDevice.current.userInterfaceIdiom == .pad
|
||||
static let isPhone: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Phone
|
||||
static let isPad: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Pad
|
||||
static var statusBarH: CGFloat {
|
||||
return UIApplication.shared.statusBarFrame.height
|
||||
return UIApplication.sharedApplication().statusBarFrame.height
|
||||
}
|
||||
static var screenHeight: CGFloat {
|
||||
return UIScreen.main.bounds.height
|
||||
return UIScreen.mainScreen().bounds.height
|
||||
}
|
||||
static var screenWidth: CGFloat {
|
||||
return UIScreen.main.bounds.width
|
||||
return UIScreen.mainScreen().bounds.width
|
||||
}
|
||||
static var screenScale: CGFloat {
|
||||
return UIScreen.main.scale
|
||||
return UIScreen.mainScreen().scale
|
||||
}
|
||||
static var screenRatio: CGFloat {
|
||||
return screenWidth / screenHeight
|
||||
|
|
|
|||
|
|
@ -2,119 +2,54 @@
|
|||
// SKNavigationBar.swift
|
||||
// SKPhotoBrowser
|
||||
//
|
||||
// Created by Григорий Уланов on 12.10.16.
|
||||
// Created by Григорий Уланов on 10.10.16.
|
||||
// Copyright © 2016 suzuki_keishi. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SKNavigationBar: UIView {
|
||||
|
||||
class SKNavigationBar: UINavigationBar {
|
||||
var showFrame: CGRect!
|
||||
var hideFrame: CGRect!
|
||||
|
||||
private static let toolBarHeight: CGFloat = 44.0
|
||||
private static let toolBarHeight: CGFloat = 64.0
|
||||
|
||||
fileprivate weak var browser: SKPhotoBrowser?
|
||||
|
||||
private var countLabel: UILabel?
|
||||
private var doneButton: UIButton?
|
||||
|
||||
var onDoneTap: (() -> Void)?
|
||||
var isStatusBarHidden: Bool = false {
|
||||
didSet {
|
||||
if let bounds = superview?.bounds {
|
||||
updateFrame(bounds.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isBigStatusBar: Bool {
|
||||
return statusBarHeight > 20 ? true : false
|
||||
}
|
||||
|
||||
private var statusBarHeight: CGFloat {
|
||||
return UIApplication.shared.statusBarFrame.height
|
||||
}
|
||||
private weak var browser: SKPhotoBrowser?
|
||||
|
||||
convenience init(browser: SKPhotoBrowser) {
|
||||
self.init(frame: CGRect.zero)
|
||||
|
||||
self.browser = browser
|
||||
|
||||
backgroundColor = UIColor.black.withAlphaComponent(0.65)
|
||||
translucent = false
|
||||
tintColor = UIColor.whiteColor()
|
||||
barTintColor = UIColor.blackColor()
|
||||
titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
|
||||
|
||||
countLabel = UILabel()
|
||||
countLabel?.font = UIFont.boldSystemFont(ofSize: 18)
|
||||
countLabel?.textColor = UIColor.white
|
||||
countLabel?.textAlignment = .center
|
||||
if let countLabel = countLabel {
|
||||
addSubview(countLabel)
|
||||
}
|
||||
|
||||
doneButton = UIButton()
|
||||
doneButton?.setTitle(SKPhotoBrowserOptions.navigationBarDoneTitle, for: .normal)
|
||||
doneButton?.setTitleColor(UIColor.white, for: .normal)
|
||||
doneButton?.addTarget(self, action: #selector(doneButtonAction), for: .touchUpInside)
|
||||
if let doneButton = doneButton {
|
||||
addSubview(doneButton)
|
||||
}
|
||||
let navigationItem = UINavigationItem()
|
||||
pushNavigationItem(navigationItem, animated: false)
|
||||
}
|
||||
|
||||
@objc private func doneButtonAction() {
|
||||
onDoneTap?()
|
||||
}
|
||||
|
||||
func updateNavigationBar(_ currentPageIndex: Int) {
|
||||
func updateNavigationBar(currentPageIndex: Int) {
|
||||
guard let browser = browser else { return }
|
||||
|
||||
if browser.numberOfPhotos > 1 {
|
||||
self.countLabel?.text = "\(currentPageIndex + 1) \(SKPhotoBrowserOptions.navigationBarCounterSepatator) \(browser.numberOfPhotos)"
|
||||
self.topItem?.title = "\(currentPageIndex + 1) \(SKPhotoBrowserOptions.navigationBarCounterSepatator) \(browser.numberOfPhotos)"
|
||||
} else {
|
||||
self.countLabel?.text = nil
|
||||
self.topItem?.title = nil
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
if !isStatusBarHidden {
|
||||
countLabel?.frame = CGRect(x: 0,
|
||||
y: isBigStatusBar ? 0 : statusBarHeight,
|
||||
width: bounds.width,
|
||||
height: isBigStatusBar ? bounds.height : bounds.height - statusBarHeight)
|
||||
doneButton?.frame = CGRect(x: 0,
|
||||
y: isBigStatusBar ? 0 : statusBarHeight,
|
||||
width: 85,
|
||||
height: isBigStatusBar ? bounds.height : bounds.height - statusBarHeight)
|
||||
} else {
|
||||
countLabel?.frame = bounds
|
||||
doneButton?.frame = CGRect(x: 0, y: 0, width: 85, height: bounds.height)
|
||||
}
|
||||
}
|
||||
|
||||
private func setNewFrame(rect: CGRect) {
|
||||
frame = rect
|
||||
func setNewFrame(rect: CGRect) {
|
||||
self.frame = rect
|
||||
showFrame = rect
|
||||
|
||||
hideFrame = CGRect(x: rect.origin.x, y: rect.origin.y - 20, width: rect.size.width, height: rect.size.height)
|
||||
layoutSubviews()
|
||||
}
|
||||
|
||||
func updateFrame(_ parentSize: CGSize) {
|
||||
var newRect: CGRect?
|
||||
|
||||
if !isStatusBarHidden {
|
||||
newRect = CGRect(x: 0,
|
||||
y: isBigStatusBar ? statusBarHeight/2 : 0,
|
||||
width: parentSize.width,
|
||||
height: isBigStatusBar ? SKNavigationBar.toolBarHeight : SKNavigationBar.toolBarHeight + statusBarHeight)
|
||||
} else {
|
||||
newRect = CGRect(x: 0, y: 0, width: parentSize.width, height: SKNavigationBar.toolBarHeight)
|
||||
}
|
||||
|
||||
if let newRect = newRect {
|
||||
setNewFrame(rect: newRect)
|
||||
}
|
||||
func updateFrame(parentSize: CGSize) {
|
||||
let newRect = CGRect(x: 0, y: 0, width: parentSize.width, height: SKNavigationBar.toolBarHeight)
|
||||
setNewFrame(newRect)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import Foundation
|
|||
class SKPagingScrollView: UIScrollView {
|
||||
let pageIndexTagOffset: Int = 1000
|
||||
let sideMargin: CGFloat = 10
|
||||
fileprivate var visiblePages = [SKZoomingScrollView]()
|
||||
fileprivate var recycledPages = [SKZoomingScrollView]()
|
||||
private var visiblePages = [SKZoomingScrollView]()
|
||||
private var recycledPages = [SKZoomingScrollView]()
|
||||
|
||||
fileprivate weak var browser: SKPhotoBrowser?
|
||||
private weak var browser: SKPhotoBrowser?
|
||||
var numberOfPhotos: Int {
|
||||
return browser?.photos.count ?? 0
|
||||
}
|
||||
|
|
@ -27,9 +27,9 @@ class SKPagingScrollView: UIScrollView {
|
|||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
isPagingEnabled = true
|
||||
showsHorizontalScrollIndicator = true
|
||||
showsVerticalScrollIndicator = true
|
||||
pagingEnabled = true
|
||||
showsHorizontalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator
|
||||
showsVerticalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator
|
||||
}
|
||||
|
||||
convenience init(frame: CGRect, browser: SKPhotoBrowser) {
|
||||
|
|
@ -45,8 +45,8 @@ class SKPagingScrollView: UIScrollView {
|
|||
recycledPages.removeAll()
|
||||
}
|
||||
|
||||
func loadAdjacentPhotosIfNecessary(_ photo: SKPhotoProtocol, currentPageIndex: Int) {
|
||||
guard let browser = browser, let page = pageDisplayingAtPhoto(photo) else {
|
||||
func loadAdjacentPhotosIfNecessary(photo: SKPhotoProtocol, currentPageIndex: Int) {
|
||||
guard let browser = browser, page = pageDisplayingAtPhoto(photo) else {
|
||||
return
|
||||
}
|
||||
let pageIndex = (page.tag - pageIndexTagOffset)
|
||||
|
|
@ -75,11 +75,11 @@ class SKPagingScrollView: UIScrollView {
|
|||
}
|
||||
}
|
||||
|
||||
func animate(_ frame: CGRect) {
|
||||
func animate(frame: CGRect) {
|
||||
setContentOffset(CGPoint(x: frame.origin.x - sideMargin, y: 0), animated: true)
|
||||
}
|
||||
|
||||
func updateFrame(_ bounds: CGRect, currentPageIndex: Int) {
|
||||
func updateFrame(bounds: CGRect, currentPageIndex: Int) {
|
||||
var frame = bounds
|
||||
frame.origin.x -= sideMargin
|
||||
frame.size.width += (2 * sideMargin)
|
||||
|
|
@ -105,7 +105,7 @@ class SKPagingScrollView: UIScrollView {
|
|||
contentSize = CGSize(width: bounds.size.width * CGFloat(numberOfPhotos), height: bounds.size.height)
|
||||
}
|
||||
|
||||
func updateContentOffset(_ index: Int) {
|
||||
func updateContentOffset(index: Int) {
|
||||
let pageWidth = bounds.size.width
|
||||
let newOffset = CGFloat(index) * pageWidth
|
||||
contentOffset = CGPoint(x: newOffset, y: 0)
|
||||
|
|
@ -126,7 +126,7 @@ class SKPagingScrollView: UIScrollView {
|
|||
}
|
||||
|
||||
let visibleSet: Set<SKZoomingScrollView> = Set(visiblePages)
|
||||
let visibleSetWithoutRecycled: Set<SKZoomingScrollView> = visibleSet.subtracting(recycledPages)
|
||||
let visibleSetWithoutRecycled: Set<SKZoomingScrollView> = visibleSet.subtract(recycledPages)
|
||||
visiblePages = Array(visibleSetWithoutRecycled)
|
||||
|
||||
while recycledPages.count > 2 {
|
||||
|
|
@ -157,7 +157,7 @@ class SKPagingScrollView: UIScrollView {
|
|||
}
|
||||
}
|
||||
|
||||
func frameForCaptionView(_ captionView: SKCaptionView, index: Int) -> CGRect {
|
||||
func frameForCaptionView(captionView: SKCaptionView, index: Int) -> CGRect {
|
||||
let pageFrame = frameForPageAtIndex(index)
|
||||
let captionSize = captionView.sizeThatFits(CGSize(width: pageFrame.size.width, height: 0))
|
||||
let navHeight = browser?.navigationController?.navigationBar.frame.size.height ?? 44
|
||||
|
|
@ -165,7 +165,7 @@ class SKPagingScrollView: UIScrollView {
|
|||
width: pageFrame.size.width, height: captionSize.height)
|
||||
}
|
||||
|
||||
func pageDisplayedAtIndex(_ index: Int) -> SKZoomingScrollView? {
|
||||
func pageDisplayedAtIndex(index: Int) -> SKZoomingScrollView? {
|
||||
for page in visiblePages {
|
||||
if page.tag - pageIndexTagOffset == index {
|
||||
return page
|
||||
|
|
@ -174,7 +174,7 @@ class SKPagingScrollView: UIScrollView {
|
|||
return nil
|
||||
}
|
||||
|
||||
func pageDisplayingAtPhoto(_ photo: SKPhotoProtocol) -> SKZoomingScrollView? {
|
||||
func pageDisplayingAtPhoto(photo: SKPhotoProtocol) -> SKZoomingScrollView? {
|
||||
for page in visiblePages {
|
||||
if page.photo === photo {
|
||||
return page
|
||||
|
|
@ -195,15 +195,15 @@ class SKPagingScrollView: UIScrollView {
|
|||
}
|
||||
|
||||
private extension SKPagingScrollView {
|
||||
func frameForPageAtIndex(_ index: Int) -> CGRect {
|
||||
func frameForPageAtIndex(index: Int) -> CGRect {
|
||||
var pageFrame = bounds
|
||||
pageFrame.size.width -= (2 * 10)
|
||||
pageFrame.origin.x = (bounds.size.width * CGFloat(index)) + sideMargin
|
||||
return pageFrame
|
||||
}
|
||||
|
||||
func createCaptionView(_ index: Int) -> SKCaptionView? {
|
||||
guard let photo = browser?.photoAtIndex(index), photo.caption != nil else {
|
||||
func createCaptionView(index: Int) -> SKCaptionView? {
|
||||
guard let photo = browser?.photoAtIndex(index) where photo.caption != nil else {
|
||||
return nil
|
||||
}
|
||||
return SKCaptionView(photo: photo)
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ import UIKit
|
|||
}
|
||||
|
||||
// MARK: - SKPhoto
|
||||
open class SKPhoto: NSObject, SKPhotoProtocol {
|
||||
public class SKPhoto: NSObject, SKPhotoProtocol {
|
||||
|
||||
open var underlyingImage: UIImage!
|
||||
open var photoURL: String!
|
||||
open var contentMode: UIViewContentMode = .scaleAspectFill
|
||||
open var shouldCachePhotoURLImage: Bool = false
|
||||
open var caption: String!
|
||||
open var index: Int = 0
|
||||
public var underlyingImage: UIImage!
|
||||
public var photoURL: String!
|
||||
public var contentMode: UIViewContentMode = .ScaleAspectFill
|
||||
public var shouldCachePhotoURLImage: Bool = false
|
||||
public var caption: String!
|
||||
public var index: Int = 0
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
|
@ -47,7 +47,7 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
underlyingImage = holder
|
||||
}
|
||||
|
||||
open func checkCache() {
|
||||
public func checkCache() {
|
||||
guard let photoURL = photoURL else {
|
||||
return
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
}
|
||||
|
||||
if SKCache.sharedCache.imageCache is SKRequestResponseCacheable {
|
||||
let request = URLRequest(url: URL(string: photoURL)!)
|
||||
let request = NSURLRequest(URL: NSURL(string: photoURL)!)
|
||||
if let img = SKCache.sharedCache.imageForRequest(request) {
|
||||
underlyingImage = img
|
||||
}
|
||||
|
|
@ -67,7 +67,7 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
open func loadUnderlyingImageAndNotify() {
|
||||
public func loadUnderlyingImageAndNotify() {
|
||||
|
||||
if underlyingImage != nil {
|
||||
loadUnderlyingImageComplete()
|
||||
|
|
@ -76,33 +76,27 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
|
||||
if photoURL != nil {
|
||||
// Fetch Image
|
||||
let session = URLSession(configuration: URLSessionConfiguration.default)
|
||||
if let nsURL = URL(string: photoURL) {
|
||||
var task: URLSessionDataTask!
|
||||
|
||||
var loadingRequest = URLRequest(url: nsURL)
|
||||
if let customHeaders = SKPhotoBrowserOptions.imageLoadingCustomHeaders {
|
||||
loadingRequest.allHTTPHeaderFields = customHeaders
|
||||
}
|
||||
|
||||
task = session.dataTask(with: loadingRequest, completionHandler: { [weak self] (data, response, error) in
|
||||
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
|
||||
if let nsURL = NSURL(string: photoURL) {
|
||||
var task: NSURLSessionDataTask!
|
||||
task = session.dataTaskWithURL(nsURL, completionHandler: { [weak self](response: NSData?, data: NSURLResponse?, error: NSError?) in
|
||||
if let _self = self {
|
||||
|
||||
if error != nil {
|
||||
DispatchQueue.main.async {
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
_self.loadUnderlyingImageComplete()
|
||||
}
|
||||
}
|
||||
|
||||
if let data = data, let response = response, let image = UIImage(data: data) {
|
||||
if let res = response, image = UIImage(data: res) {
|
||||
if _self.shouldCachePhotoURLImage {
|
||||
if SKCache.sharedCache.imageCache is SKRequestResponseCacheable {
|
||||
SKCache.sharedCache.setImageData(data, response: response, request: task.originalRequest!)
|
||||
SKCache.sharedCache.setImageData(response!, response: data!, request: task.originalRequest!)
|
||||
} else {
|
||||
SKCache.sharedCache.setImage(image, forKey: _self.photoURL)
|
||||
}
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
_self.underlyingImage = image
|
||||
_self.loadUnderlyingImageComplete()
|
||||
}
|
||||
|
|
@ -115,8 +109,8 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
open func loadUnderlyingImageComplete() {
|
||||
NotificationCenter.default.post(name: Notification.Name(rawValue: SKPHOTO_LOADING_DID_END_NOTIFICATION), object: self)
|
||||
public func loadUnderlyingImageComplete() {
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(SKPHOTO_LOADING_DID_END_NOTIFICATION, object: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -124,15 +118,15 @@ open class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
// MARK: - Static Function
|
||||
|
||||
extension SKPhoto {
|
||||
public static func photoWithImage(_ image: UIImage) -> SKPhoto {
|
||||
public static func photoWithImage(image: UIImage) -> SKPhoto {
|
||||
return SKPhoto(image: image)
|
||||
}
|
||||
|
||||
public static func photoWithImageURL(_ url: String) -> SKPhoto {
|
||||
public static func photoWithImageURL(url: String) -> SKPhoto {
|
||||
return SKPhoto(url: url)
|
||||
}
|
||||
|
||||
public static func photoWithImageURL(_ url: String, holder: UIImage?) -> SKPhoto {
|
||||
public static func photoWithImageURL(url: String, holder: UIImage?) -> SKPhoto {
|
||||
return SKPhoto(url: url, holder: holder)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,112 +11,108 @@ import UIKit
|
|||
public let SKPHOTO_LOADING_DID_END_NOTIFICATION = "photoLoadingDidEndNotification"
|
||||
|
||||
// MARK: - SKPhotoBrowser
|
||||
open class SKPhotoBrowser: UIViewController {
|
||||
public class SKPhotoBrowser: UIViewController {
|
||||
|
||||
let pageIndexTagOffset: Int = 1000
|
||||
|
||||
fileprivate var closeButton: SKCloseButton!
|
||||
fileprivate var deleteButton: SKDeleteButton!
|
||||
fileprivate var toolbar: SKToolbar!
|
||||
fileprivate var navigationBar: SKNavigationBar!
|
||||
private var closeButton: SKCloseButton!
|
||||
private var deleteButton: SKDeleteButton!
|
||||
private var toolbar: SKToolbar!
|
||||
|
||||
private var navigationBar: SKNavigationBar!
|
||||
|
||||
// actions
|
||||
fileprivate var activityViewController: UIActivityViewController!
|
||||
fileprivate var panGesture: UIPanGestureRecognizer!
|
||||
private var activityViewController: UIActivityViewController!
|
||||
private var panGesture: UIPanGestureRecognizer!
|
||||
|
||||
// tool for controls
|
||||
fileprivate var applicationWindow: UIWindow!
|
||||
fileprivate lazy var pagingScrollView: SKPagingScrollView = SKPagingScrollView(frame: self.view.frame, browser: self)
|
||||
private var applicationWindow: UIWindow!
|
||||
private lazy var pagingScrollView: SKPagingScrollView = SKPagingScrollView(frame: self.view.frame, browser: self)
|
||||
var backgroundView: UIView!
|
||||
|
||||
var initialPageIndex: Int = 0
|
||||
var currentPageIndex: Int = 0
|
||||
|
||||
// status bar
|
||||
private var isStatusBarHidden: Bool = false {
|
||||
didSet {
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
navigationBar.isStatusBarHidden = isStatusBarHidden
|
||||
}
|
||||
}
|
||||
|
||||
// for status check property
|
||||
fileprivate var isEndAnimationByToolBar: Bool = true
|
||||
fileprivate var isViewActive: Bool = false
|
||||
fileprivate var isPerformingLayout: Bool = false
|
||||
private var isEndAnimationByToolBar: Bool = true
|
||||
private var isViewActive: Bool = false
|
||||
private var isPerformingLayout: Bool = false
|
||||
|
||||
// pangesture property
|
||||
fileprivate var firstX: CGFloat = 0.0
|
||||
fileprivate var firstY: CGFloat = 0.0
|
||||
private var firstX: CGFloat = 0.0
|
||||
private var firstY: CGFloat = 0.0
|
||||
|
||||
// timer
|
||||
fileprivate var controlVisibilityTimer: Timer!
|
||||
private var controlVisibilityTimer: NSTimer!
|
||||
|
||||
// blocks
|
||||
public var willDismissPage: ((_ animated: Bool) -> Void)?
|
||||
public var willDismissPage: (() -> Void)?
|
||||
public var didPresentPage: (() -> Void)?
|
||||
|
||||
// delegate
|
||||
fileprivate let animator = SKAnimator()
|
||||
open weak var delegate: SKPhotoBrowserDelegate?
|
||||
private let animator = SKAnimator()
|
||||
public weak var delegate: SKPhotoBrowserDelegate?
|
||||
|
||||
// photos
|
||||
var photos: [SKPhotoProtocol] = [SKPhotoProtocol]()
|
||||
var numberOfPhotos: Int {
|
||||
return photos.count
|
||||
}
|
||||
|
||||
// statusbar initial state
|
||||
private var statusbarHidden: Bool = UIApplication.sharedApplication().statusBarHidden
|
||||
|
||||
// MARK - Initializer
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
setup()
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: Bundle!) {
|
||||
public override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
setup()
|
||||
}
|
||||
|
||||
public convenience init(photos: [SKPhotoProtocol]) {
|
||||
self.init(nibName: nil, bundle: nil)
|
||||
let pictures = photos.flatMap { $0 }
|
||||
for photo in pictures {
|
||||
let picutres = photos.flatMap { $0 }
|
||||
for photo in picutres {
|
||||
photo.checkCache()
|
||||
self.photos.append(photo)
|
||||
}
|
||||
}
|
||||
|
||||
public convenience init(originImage: UIImage, photos: [SKPhotoProtocol], animatedFromView: UIView, fromViewController: UIViewController) {
|
||||
public convenience init(originImage: UIImage, photos: [SKPhotoProtocol], animatedFromView: UIView) {
|
||||
self.init(nibName: nil, bundle: nil)
|
||||
animator.senderOriginImage = originImage
|
||||
animator.senderViewForAnimation = animatedFromView
|
||||
animator.parentViewController = fromViewController
|
||||
|
||||
let pictures = photos.flatMap { $0 }
|
||||
for photo in pictures {
|
||||
let picutres = photos.flatMap { $0 }
|
||||
for photo in picutres {
|
||||
photo.checkCache()
|
||||
self.photos.append(photo)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
func setup() {
|
||||
guard let window = UIApplication.shared.delegate?.window else {
|
||||
guard let window = UIApplication.sharedApplication().delegate?.window else {
|
||||
return
|
||||
}
|
||||
applicationWindow = window
|
||||
|
||||
modalPresentationCapturesStatusBarAppearance = true
|
||||
modalPresentationStyle = .overFullScreen
|
||||
modalTransitionStyle = .crossDissolve
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.handleSKPhotoLoadingDidEndNotification(_:)), name: NSNotification.Name(rawValue: SKPHOTO_LOADING_DID_END_NOTIFICATION), object: nil)
|
||||
modalPresentationStyle = .Custom
|
||||
modalTransitionStyle = .CrossDissolve
|
||||
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.handleSKPhotoLoadingDidEndNotification(_:)), name: SKPHOTO_LOADING_DID_END_NOTIFICATION, object: nil)
|
||||
}
|
||||
|
||||
// MARK: - override
|
||||
override open func viewDidLoad() {
|
||||
override public func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
configureAppearance()
|
||||
|
|
@ -126,13 +122,10 @@ open class SKPhotoBrowser: UIViewController {
|
|||
configureToolbar()
|
||||
|
||||
animator.willPresent(self)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(didChangeOrientation), name: .UIDeviceOrientationDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(didChangeStatusBarFrame), name: .UIApplicationDidChangeStatusBarFrame, object: nil)
|
||||
didPresentPage?()
|
||||
}
|
||||
|
||||
|
||||
override open func viewWillAppear(_ animated: Bool) {
|
||||
override public func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(true)
|
||||
reloadData()
|
||||
|
||||
|
|
@ -142,61 +135,37 @@ open class SKPhotoBrowser: UIViewController {
|
|||
i = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
func didChangeOrientation() {
|
||||
isStatusBarHidden = UIApplication.shared.statusBarOrientation != .portrait
|
||||
}
|
||||
|
||||
func didChangeStatusBarFrame() {
|
||||
viewWillLayoutSubviews()
|
||||
view.layoutSubviews()
|
||||
viewDidLayoutSubviews()
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
|
||||
|
||||
override public func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
isPerformingLayout = true
|
||||
|
||||
|
||||
closeButton.updateFrame()
|
||||
deleteButton.updateFrame()
|
||||
navigationBar.updateFrame(view.bounds.size)
|
||||
pagingScrollView.updateFrame(view.bounds, currentPageIndex: currentPageIndex)
|
||||
|
||||
|
||||
toolbar.frame = frameForToolbarAtOrientation()
|
||||
|
||||
|
||||
// where did start
|
||||
delegate?.didShowPhotoAtIndex?(currentPageIndex)
|
||||
|
||||
|
||||
isPerformingLayout = false
|
||||
|
||||
super.viewDidLayoutSubviews()
|
||||
}
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
override public func viewDidAppear(animated: Bool) {
|
||||
super.viewDidAppear(true)
|
||||
isViewActive = true
|
||||
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
didPresentPage?()
|
||||
}
|
||||
|
||||
open override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
}
|
||||
|
||||
open override var prefersStatusBarHidden: Bool {
|
||||
return isStatusBarHidden
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Notification
|
||||
open func handleSKPhotoLoadingDidEndNotification(_ notification: Notification) {
|
||||
public func handleSKPhotoLoadingDidEndNotification(notification: NSNotification) {
|
||||
guard let photo = notification.object as? SKPhotoProtocol else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), let photo = page.photo else {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), photo = page.photo else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -209,18 +178,17 @@ open class SKPhotoBrowser: UIViewController {
|
|||
})
|
||||
}
|
||||
|
||||
open func loadAdjacentPhotosIfNecessary(_ photo: SKPhotoProtocol) {
|
||||
public func loadAdjacentPhotosIfNecessary(photo: SKPhotoProtocol) {
|
||||
pagingScrollView.loadAdjacentPhotosIfNecessary(photo, currentPageIndex: currentPageIndex)
|
||||
}
|
||||
|
||||
// MARK: - initialize / setup
|
||||
open func reloadData() {
|
||||
backgroundView.backgroundColor = view.backgroundColor
|
||||
public func reloadData() {
|
||||
performLayout()
|
||||
view.setNeedsLayout()
|
||||
}
|
||||
|
||||
open func performLayout() {
|
||||
public func performLayout() {
|
||||
isPerformingLayout = true
|
||||
|
||||
toolbar.updateToolbar(currentPageIndex)
|
||||
|
|
@ -238,51 +206,52 @@ open class SKPhotoBrowser: UIViewController {
|
|||
isPerformingLayout = false
|
||||
}
|
||||
|
||||
open func prepareForClosePhotoBrowser() {
|
||||
public func prepareForClosePhotoBrowser() {
|
||||
UIApplication.sharedApplication().setStatusBarHidden(statusbarHidden, withAnimation: .None)
|
||||
cancelControlHiding()
|
||||
applicationWindow.removeGestureRecognizer(panGesture)
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: self)
|
||||
NSObject.cancelPreviousPerformRequestsWithTarget(self)
|
||||
}
|
||||
|
||||
open func dismissPhotoBrowser(animated: Bool, completion: ((Void) -> Void)? = nil) {
|
||||
public func dismissPhotoBrowser(animated animated: Bool, completion: (Void -> Void)? = nil) {
|
||||
prepareForClosePhotoBrowser()
|
||||
|
||||
if !animated {
|
||||
modalTransitionStyle = .crossDissolve
|
||||
modalTransitionStyle = .CrossDissolve
|
||||
}
|
||||
|
||||
dismiss(animated: !animated) {
|
||||
dismissViewControllerAnimated(!animated) {
|
||||
completion?()
|
||||
self.delegate?.didDismissAtPageIndex?(self.currentPageIndex)
|
||||
}
|
||||
}
|
||||
|
||||
open func determineAndClose(sender: UIView?) {
|
||||
public func determineAndClose() {
|
||||
delegate?.willDismissAtPageIndex?(currentPageIndex)
|
||||
animator.willDismiss(self, sender: sender)
|
||||
willDismissPage?(sender != nil)
|
||||
animator.willDismiss(self)
|
||||
willDismissPage?()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public Function For Customizing Buttons
|
||||
|
||||
public extension SKPhotoBrowser {
|
||||
func updateCloseButton(_ image: UIImage, size: CGSize? = nil) {
|
||||
func updateCloseButton(image: UIImage, size: CGSize? = nil) {
|
||||
if closeButton == nil {
|
||||
configureCloseButton()
|
||||
}
|
||||
closeButton.setImage(image, for: UIControlState())
|
||||
closeButton.setImage(image, forState: .Normal)
|
||||
|
||||
if let size = size {
|
||||
closeButton.setFrameSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
func updateDeleteButton(_ image: UIImage, size: CGSize? = nil) {
|
||||
func updateDeleteButton(image: UIImage, size: CGSize? = nil) {
|
||||
if deleteButton == nil {
|
||||
configureDeleteButton()
|
||||
}
|
||||
deleteButton.setImage(image, for: UIControlState())
|
||||
deleteButton.setImage(image, forState: .Normal)
|
||||
|
||||
if let size = size {
|
||||
deleteButton.setFrameSize(size)
|
||||
|
|
@ -293,7 +262,7 @@ public extension SKPhotoBrowser {
|
|||
// MARK: - Public Function For Browser Control
|
||||
|
||||
public extension SKPhotoBrowser {
|
||||
func initializePageIndex(_ index: Int) {
|
||||
func initializePageIndex(index: Int) {
|
||||
var i = index
|
||||
if index >= numberOfPhotos {
|
||||
i = numberOfPhotos - 1
|
||||
|
|
@ -302,7 +271,7 @@ public extension SKPhotoBrowser {
|
|||
initialPageIndex = i
|
||||
currentPageIndex = i
|
||||
|
||||
if isViewLoaded {
|
||||
if isViewLoaded() {
|
||||
jumpToPageAtIndex(index)
|
||||
if !isViewActive {
|
||||
pagingScrollView.tilePages()
|
||||
|
|
@ -310,7 +279,7 @@ public extension SKPhotoBrowser {
|
|||
}
|
||||
}
|
||||
|
||||
func jumpToPageAtIndex(_ index: Int) {
|
||||
func jumpToPageAtIndex(index: Int) {
|
||||
if index < numberOfPhotos {
|
||||
if !isEndAnimationByToolBar {
|
||||
return
|
||||
|
|
@ -325,7 +294,7 @@ public extension SKPhotoBrowser {
|
|||
hideControlsAfterDelay()
|
||||
}
|
||||
|
||||
func photoAtIndex(_ index: Int) -> SKPhotoProtocol {
|
||||
func photoAtIndex(index: Int) -> SKPhotoProtocol {
|
||||
return photos[index]
|
||||
}
|
||||
|
||||
|
|
@ -348,14 +317,14 @@ public extension SKPhotoBrowser {
|
|||
// reset
|
||||
cancelControlHiding()
|
||||
// start
|
||||
controlVisibilityTimer = Timer.scheduledTimer(timeInterval: 4.0, target: self, selector: #selector(SKPhotoBrowser.hideControls(_:)), userInfo: nil, repeats: false)
|
||||
controlVisibilityTimer = NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector: #selector(SKPhotoBrowser.hideControls(_:)), userInfo: nil, repeats: false)
|
||||
}
|
||||
|
||||
func hideControls() {
|
||||
setControlsHidden(true, animated: true, permanent: false)
|
||||
}
|
||||
|
||||
func hideControls(_ timer: Timer) {
|
||||
func hideControls(timer: NSTimer) {
|
||||
hideControls()
|
||||
}
|
||||
|
||||
|
|
@ -367,7 +336,7 @@ public extension SKPhotoBrowser {
|
|||
return toolbar.alpha == 0.0
|
||||
}
|
||||
|
||||
func popupShare(includeCaption: Bool = true) {
|
||||
func popupShare(includeCaption includeCaption: Bool = true) {
|
||||
let photo = photos[currentPageIndex]
|
||||
guard let underlyingImage = photo.underlyingImage else {
|
||||
return
|
||||
|
|
@ -376,10 +345,9 @@ public extension SKPhotoBrowser {
|
|||
var activityItems: [AnyObject] = [underlyingImage]
|
||||
if photo.caption != nil && includeCaption {
|
||||
if let shareExtraCaption = SKPhotoBrowserOptions.shareExtraCaption {
|
||||
let caption = photo.caption + shareExtraCaption
|
||||
activityItems.append(caption as AnyObject)
|
||||
activityItems.append(photo.caption + shareExtraCaption)
|
||||
} else {
|
||||
activityItems.append(photo.caption as AnyObject)
|
||||
activityItems.append(photo.caption)
|
||||
}
|
||||
}
|
||||
activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
|
|
@ -388,13 +356,13 @@ public extension SKPhotoBrowser {
|
|||
self.hideControlsAfterDelay()
|
||||
self.activityViewController = nil
|
||||
}
|
||||
if UI_USER_INTERFACE_IDIOM() == .phone {
|
||||
present(activityViewController, animated: true, completion: nil)
|
||||
if UI_USER_INTERFACE_IDIOM() == .Phone {
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
} else {
|
||||
activityViewController.modalPresentationStyle = .popover
|
||||
activityViewController.modalPresentationStyle = .Popover
|
||||
let popover: UIPopoverPresentationController! = activityViewController.popoverPresentationController
|
||||
popover.barButtonItem = toolbar.toolActionButton
|
||||
present(activityViewController, animated: true, completion: nil)
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -414,13 +382,13 @@ internal extension SKPhotoBrowser {
|
|||
}
|
||||
}
|
||||
|
||||
func pageDisplayedAtIndex(_ index: Int) -> SKZoomingScrollView? {
|
||||
func pageDisplayedAtIndex(index: Int) -> SKZoomingScrollView? {
|
||||
return pagingScrollView.pageDisplayedAtIndex(index)
|
||||
}
|
||||
|
||||
func getImageFromView(_ sender: UIView) -> UIImage {
|
||||
func getImageFromView(sender: UIView) -> UIImage {
|
||||
UIGraphicsBeginImageContextWithOptions(sender.frame.size, true, 0.0)
|
||||
sender.layer.render(in: UIGraphicsGetCurrentContext()!)
|
||||
sender.layer.renderInContext(UIGraphicsGetCurrentContext()!)
|
||||
let result = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return result!
|
||||
|
|
@ -431,16 +399,24 @@ internal extension SKPhotoBrowser {
|
|||
|
||||
internal extension SKPhotoBrowser {
|
||||
func frameForToolbarAtOrientation() -> CGRect {
|
||||
let height: CGFloat = 44
|
||||
let currentOrientation = UIApplication.sharedApplication().statusBarOrientation
|
||||
var height: CGFloat = navigationController?.navigationBar.frame.size.height ?? 44
|
||||
if UIInterfaceOrientationIsLandscape(currentOrientation) {
|
||||
height = 32
|
||||
}
|
||||
return CGRect(x: 0, y: view.bounds.size.height - height, width: view.bounds.size.width, height: height)
|
||||
}
|
||||
|
||||
func frameForToolbarHideAtOrientation() -> CGRect {
|
||||
let height: CGFloat = 44
|
||||
let currentOrientation = UIApplication.sharedApplication().statusBarOrientation
|
||||
var height: CGFloat = navigationController?.navigationBar.frame.size.height ?? 44
|
||||
if UIInterfaceOrientationIsLandscape(currentOrientation) {
|
||||
height = 32
|
||||
}
|
||||
return CGRect(x: 0, y: view.bounds.size.height + height, width: view.bounds.size.width, height: height)
|
||||
}
|
||||
|
||||
func frameForPageAtIndex(_ index: Int) -> CGRect {
|
||||
func frameForPageAtIndex(index: Int) -> CGRect {
|
||||
let bounds = pagingScrollView.bounds
|
||||
var pageFrame = bounds
|
||||
pageFrame.size.width -= (2 * 10)
|
||||
|
|
@ -452,19 +428,19 @@ internal extension SKPhotoBrowser {
|
|||
// MARK: - Internal Function For Button Pressed, UIGesture Control
|
||||
|
||||
internal extension SKPhotoBrowser {
|
||||
func panGestureRecognized(_ sender: UIPanGestureRecognizer) {
|
||||
func panGestureRecognized(sender: UIPanGestureRecognizer) {
|
||||
guard let zoomingScrollView: SKZoomingScrollView = pagingScrollView.pageDisplayedAtIndex(currentPageIndex) else {
|
||||
return
|
||||
}
|
||||
|
||||
backgroundView.isHidden = true
|
||||
backgroundView.hidden = true
|
||||
|
||||
let viewHeight: CGFloat = zoomingScrollView.frame.size.height
|
||||
let viewHalfHeight: CGFloat = viewHeight/2
|
||||
var translatedPoint: CGPoint = sender.translation(in: self.view)
|
||||
var translatedPoint: CGPoint = sender.translationInView(self.view)
|
||||
|
||||
// gesture began
|
||||
if sender.state == .began {
|
||||
if sender.state == .Began {
|
||||
firstX = zoomingScrollView.center.x
|
||||
firstY = zoomingScrollView.center.y
|
||||
|
||||
|
|
@ -480,29 +456,22 @@ internal extension SKPhotoBrowser {
|
|||
? zoomingScrollView.center.y - viewHalfHeight
|
||||
: -(zoomingScrollView.center.y - viewHalfHeight)) / viewHalfHeight
|
||||
|
||||
view.alpha = CGFloat.maximum(0.6, offset)
|
||||
view.alpha = max(0.7, offset)
|
||||
|
||||
// gesture end
|
||||
if sender.state == .ended || sender.state == .cancelled || sender.state == .failed {
|
||||
if sender.state == .Ended {
|
||||
|
||||
if zoomingScrollView.center.y > viewHalfHeight + minOffset
|
||||
|| zoomingScrollView.center.y < viewHalfHeight - minOffset {
|
||||
|
||||
if let sender = self.delegate?.viewForPhoto?(self, index: self.currentPageIndex) {
|
||||
determineAndClose(sender: sender)
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
self.view.alpha = 0
|
||||
}, completion: { _ in
|
||||
self.determineAndClose(sender: nil)
|
||||
})
|
||||
}
|
||||
|
||||
backgroundView.backgroundColor = view.backgroundColor
|
||||
determineAndClose()
|
||||
|
||||
} else {
|
||||
// Continue Showing View
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
|
||||
let velocityY: CGFloat = CGFloat(0.35) * sender.velocity(in: self.view).y
|
||||
let velocityY: CGFloat = CGFloat(0.35) * sender.velocityInView(self.view).y
|
||||
let finalX: CGFloat = firstX
|
||||
let finalY: CGFloat = viewHalfHeight
|
||||
|
||||
|
|
@ -510,8 +479,8 @@ internal extension SKPhotoBrowser {
|
|||
|
||||
UIView.beginAnimations(nil, context: nil)
|
||||
UIView.setAnimationDuration(animationDuration)
|
||||
UIView.setAnimationCurve(UIViewAnimationCurve.easeIn)
|
||||
view.backgroundColor = UIColor.black
|
||||
UIView.setAnimationCurve(UIViewAnimationCurve.EaseIn)
|
||||
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
view.alpha = 1
|
||||
zoomingScrollView.center = CGPoint(x: finalX, y: finalY)
|
||||
UIView.commitAnimations()
|
||||
|
|
@ -519,17 +488,17 @@ internal extension SKPhotoBrowser {
|
|||
}
|
||||
}
|
||||
|
||||
func deleteButtonPressed(_ sender: UIButton) {
|
||||
func deleteButtonPressed(sender: UIButton) {
|
||||
delegate?.removePhoto?(self, index: currentPageIndex) { [weak self] in
|
||||
self?.deleteImage()
|
||||
}
|
||||
}
|
||||
|
||||
func closeButtonPressed(_ sender: UIButton) {
|
||||
determineAndClose(sender: nil)
|
||||
func closeButtonPressed(sender: UIButton) {
|
||||
determineAndClose()
|
||||
}
|
||||
|
||||
func actionButtonPressed(ignoreAndShare: Bool) {
|
||||
func actionButtonPressed(ignoreAndShare ignoreAndShare: Bool) {
|
||||
delegate?.willShowActionSheet?(currentPageIndex)
|
||||
|
||||
guard numberOfPhotos > 0 else {
|
||||
|
|
@ -537,26 +506,26 @@ internal extension SKPhotoBrowser {
|
|||
}
|
||||
|
||||
if let titles = SKPhotoBrowserOptions.actionButtonTitles {
|
||||
let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
actionSheetController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
|
||||
let actionSheetController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
|
||||
actionSheetController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: { (action) -> Void in
|
||||
}))
|
||||
for idx in titles.indices {
|
||||
actionSheetController.addAction(UIAlertAction(title: titles[idx], style: .default, handler: { (action) -> Void in
|
||||
actionSheetController.addAction(UIAlertAction(title: titles[idx], style: .Default, handler: { (action) -> Void in
|
||||
self.delegate?.didDismissActionSheetWithButtonIndex?(idx, photoIndex: self.currentPageIndex)
|
||||
}))
|
||||
}
|
||||
|
||||
if UI_USER_INTERFACE_IDIOM() == .phone {
|
||||
present(actionSheetController, animated: true, completion: nil)
|
||||
if UI_USER_INTERFACE_IDIOM() == .Phone {
|
||||
presentViewController(actionSheetController, animated: true, completion: nil)
|
||||
} else {
|
||||
actionSheetController.modalPresentationStyle = .popover
|
||||
actionSheetController.modalPresentationStyle = .Popover
|
||||
|
||||
if let popoverController = actionSheetController.popoverPresentationController {
|
||||
popoverController.sourceView = self.view
|
||||
popoverController.barButtonItem = toolbar.toolActionButton
|
||||
}
|
||||
|
||||
present(actionSheetController, animated: true, completion: { () -> Void in
|
||||
presentViewController(actionSheetController, animated: true, completion: { () -> Void in
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -569,12 +538,12 @@ internal extension SKPhotoBrowser {
|
|||
// MARK: - Private Function
|
||||
private extension SKPhotoBrowser {
|
||||
func configureAppearance() {
|
||||
view.backgroundColor = UIColor.black
|
||||
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
view.clipsToBounds = true
|
||||
view.isOpaque = false
|
||||
view.opaque = false
|
||||
|
||||
backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: SKMesurement.screenWidth, height: SKMesurement.screenHeight))
|
||||
backgroundView.backgroundColor = UIColor.black
|
||||
backgroundView.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
backgroundView.alpha = 0.0
|
||||
applicationWindow.addSubview(backgroundView)
|
||||
|
||||
|
|
@ -583,6 +552,7 @@ private extension SKPhotoBrowser {
|
|||
|
||||
panGesture = UIPanGestureRecognizer(target: self, action: #selector(SKPhotoBrowser.panGestureRecognized(_:)))
|
||||
panGesture.minimumNumberOfTouches = 1
|
||||
panGesture.maximumNumberOfTouches = 1
|
||||
if !SKPhotoBrowserOptions.disableVerticalSwipe {
|
||||
view.addGestureRecognizer(panGesture)
|
||||
}
|
||||
|
|
@ -590,26 +560,22 @@ private extension SKPhotoBrowser {
|
|||
|
||||
func configureCloseButton() {
|
||||
closeButton = SKCloseButton(frame: .zero)
|
||||
closeButton.addTarget(self, action: #selector(closeButtonPressed(_:)), for: .touchUpInside)
|
||||
closeButton.isHidden = !SKPhotoBrowserOptions.displayCloseButton
|
||||
closeButton.addTarget(self, action: #selector(closeButtonPressed(_:)), forControlEvents: .TouchUpInside)
|
||||
closeButton.hidden = !SKPhotoBrowserOptions.displayCloseButton
|
||||
view.addSubview(closeButton)
|
||||
}
|
||||
|
||||
func configureDeleteButton() {
|
||||
deleteButton = SKDeleteButton(frame: .zero)
|
||||
deleteButton.addTarget(self, action: #selector(deleteButtonPressed(_:)), for: .touchUpInside)
|
||||
deleteButton.isHidden = !SKPhotoBrowserOptions.displayDeleteButton
|
||||
deleteButton.addTarget(self, action: #selector(deleteButtonPressed(_:)), forControlEvents: .TouchUpInside)
|
||||
deleteButton.hidden = !SKPhotoBrowserOptions.displayDeleteButton
|
||||
view.addSubview(deleteButton)
|
||||
}
|
||||
|
||||
func configureNavigationBar() {
|
||||
navigationBar = SKNavigationBar(browser: self)
|
||||
navigationBar.updateFrame(view.bounds.size)
|
||||
navigationBar.isHidden = !SKPhotoBrowserOptions.displayNavigationBar
|
||||
navigationBar.onDoneTap = { [weak self] in
|
||||
self?.willDismissPage?(false)
|
||||
self?.dismissPhotoBrowser(animated: false)
|
||||
}
|
||||
navigationBar.hidden = !SKPhotoBrowserOptions.displayNavigationBar
|
||||
view.addSubview(navigationBar)
|
||||
}
|
||||
|
||||
|
|
@ -618,12 +584,12 @@ private extension SKPhotoBrowser {
|
|||
view.addSubview(toolbar)
|
||||
}
|
||||
|
||||
func setControlsHidden(_ hidden: Bool, animated: Bool, permanent: Bool) {
|
||||
func setControlsHidden(hidden: Bool, animated: Bool, permanent: Bool) {
|
||||
cancelControlHiding()
|
||||
|
||||
let captionViews = pagingScrollView.getCaptionViews()
|
||||
|
||||
UIView.animate(withDuration: 0.35,
|
||||
UIView.animateWithDuration(0.35,
|
||||
animations: { () -> Void in
|
||||
let alpha: CGFloat = hidden ? 0.0 : 1.0
|
||||
self.toolbar.alpha = alpha
|
||||
|
|
@ -648,11 +614,10 @@ private extension SKPhotoBrowser {
|
|||
if !permanent {
|
||||
hideControlsAfterDelay()
|
||||
}
|
||||
|
||||
setNeedsStatusBarAppearanceUpdate()
|
||||
}
|
||||
|
||||
func deleteImage() {
|
||||
private func deleteImage() {
|
||||
defer {
|
||||
reloadData()
|
||||
}
|
||||
|
|
@ -660,7 +625,7 @@ private extension SKPhotoBrowser {
|
|||
if photos.count > 1 {
|
||||
pagingScrollView.deleteImage()
|
||||
|
||||
photos.remove(at: currentPageIndex)
|
||||
photos.removeAtIndex(currentPageIndex)
|
||||
if currentPageIndex != 0 {
|
||||
gotoPreviousPage()
|
||||
}
|
||||
|
|
@ -676,7 +641,7 @@ private extension SKPhotoBrowser {
|
|||
// MARK: - UIScrollView Delegate
|
||||
|
||||
extension SKPhotoBrowser: UIScrollViewDelegate {
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
public func scrollViewDidScroll(scrollView: UIScrollView) {
|
||||
guard isViewActive else {
|
||||
return
|
||||
}
|
||||
|
|
@ -699,14 +664,14 @@ extension SKPhotoBrowser: UIScrollViewDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
||||
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
|
||||
hideControlsAfterDelay()
|
||||
|
||||
let currentIndex = pagingScrollView.contentOffset.x / pagingScrollView.frame.size.width
|
||||
delegate?.didScrollToIndex?(Int(currentIndex))
|
||||
}
|
||||
|
||||
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
|
||||
public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
|
||||
isEndAnimationByToolBar = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,28 +15,28 @@ import Foundation
|
|||
|
||||
- Parameter index: the index of the new photo
|
||||
*/
|
||||
@objc optional func didShowPhotoAtIndex(_ index: Int)
|
||||
optional func didShowPhotoAtIndex(index: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate the browser will start to dismiss
|
||||
|
||||
- Parameter index: the index of the current photo
|
||||
*/
|
||||
@objc optional func willDismissAtPageIndex(_ index: Int)
|
||||
optional func willDismissAtPageIndex(index: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate that the browser will start showing the `UIActionSheet`
|
||||
|
||||
- Parameter photoIndex: the index of the current photo
|
||||
*/
|
||||
@objc optional func willShowActionSheet(_ photoIndex: Int)
|
||||
optional func willShowActionSheet(photoIndex: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate that the browser has been dismissed
|
||||
|
||||
- Parameter index: the index of the current photo
|
||||
*/
|
||||
@objc optional func didDismissAtPageIndex(_ index: Int)
|
||||
optional func didDismissAtPageIndex(index: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate that the browser did dismiss the UIActionSheet
|
||||
|
|
@ -44,14 +44,14 @@ import Foundation
|
|||
- Parameter buttonIndex: the index of the pressed button
|
||||
- Parameter photoIndex: the index of the current photo
|
||||
*/
|
||||
@objc optional func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int)
|
||||
optional func didDismissActionSheetWithButtonIndex(buttonIndex: Int, photoIndex: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate that the browser did scroll to index
|
||||
|
||||
- Parameter index: the index of the photo where the user had scroll
|
||||
*/
|
||||
@objc optional func didScrollToIndex(_ index: Int)
|
||||
optional func didScrollToIndex(index: Int)
|
||||
|
||||
/**
|
||||
Tells the delegate the user removed a photo, when implementing this call, be sure to call reload to finish the deletion process
|
||||
|
|
@ -60,7 +60,7 @@ import Foundation
|
|||
- Parameter index: the index of the removed photo
|
||||
- Parameter reload: function that needs to be called after finishing syncing up
|
||||
*/
|
||||
@objc optional func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void))
|
||||
optional func removePhoto(browser: SKPhotoBrowser, index: Int, reload: (() -> Void))
|
||||
|
||||
/**
|
||||
Asks the delegate for the view for a certain photo. Needed to detemine the animation when presenting/closing the browser.
|
||||
|
|
@ -70,6 +70,7 @@ import Foundation
|
|||
|
||||
- Returns: the view to animate to
|
||||
*/
|
||||
@objc optional func viewForPhoto(_ browser: SKPhotoBrowser, index: Int) -> UIView?
|
||||
optional func viewForPhoto(browser: SKPhotoBrowser, index: Int) -> UIView?
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@
|
|||
// Copyright © 2016年 suzuki_keishi. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
public struct SKPhotoBrowserOptions {
|
||||
public static var displayStatusbar: Bool = false
|
||||
|
||||
public static var displayAction: Bool = true
|
||||
public static var shareExtraCaption: String? = nil
|
||||
public static var actionButtonTitles: [String]?
|
||||
|
|
@ -18,16 +20,27 @@ public struct SKPhotoBrowserOptions {
|
|||
public static var displayBackAndForwardButton: Bool = true
|
||||
public static var disableVerticalSwipe: Bool = false
|
||||
|
||||
public static var displayCloseButton = false
|
||||
public static var displayNavigationBar = true
|
||||
public static var displayDeleteButton = false
|
||||
|
||||
public static var navigationBarCounterSepatator = "из"
|
||||
public static var navigationBarDoneTitle = "Готово"
|
||||
public static var displayCloseButton: Bool = true
|
||||
public static var displayNavigationBar: Bool = true
|
||||
public static var displayDeleteButton: Bool = false
|
||||
|
||||
public static var bounceAnimation = false
|
||||
public static var enableZoomBlackArea = true
|
||||
public static var enableSingleTapDismiss = false
|
||||
public static var displayHorizontalScrollIndicator: Bool = true
|
||||
public static var displayVerticalScrollIndicator: Bool = true
|
||||
|
||||
public static var bounceAnimation: Bool = false
|
||||
public static var enableZoomBlackArea: Bool = true
|
||||
public static var enableSingleTapDismiss: Bool = false
|
||||
|
||||
public static var backgroundColor = UIColor.blackColor()
|
||||
public static var textAndIconColor = UIColor.whiteColor()
|
||||
public static var toolbarTextShadowColor = UIColor.darkTextColor()
|
||||
|
||||
public static var imageLoadingCustomHeaders: [String : String]?
|
||||
public static var navigationBarCounterSepatator: String = "из"
|
||||
|
||||
public static var toolbarFont = UIFont(name: "Helvetica", size: 16.0)
|
||||
public static var captionFont = UIFont.systemFontOfSize(17.0)
|
||||
|
||||
// FIXED: Scrolling performance slowed #145
|
||||
// public static var imagePaddingX: CGFloat = 0
|
||||
// public static var imagePaddingY: CGFloat = 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
import Foundation
|
||||
|
||||
// helpers which often used
|
||||
private let bundle = Bundle(for: SKPhotoBrowser.self)
|
||||
private let bundle = NSBundle(forClass: SKPhotoBrowser.self)
|
||||
|
||||
class SKToolbar: UIToolbar {
|
||||
var toolCounterLabel: UILabel!
|
||||
|
|
@ -18,7 +18,7 @@ class SKToolbar: UIToolbar {
|
|||
var toolNextButton: UIBarButtonItem!
|
||||
var toolActionButton: UIBarButtonItem!
|
||||
|
||||
fileprivate weak var browser: SKPhotoBrowser?
|
||||
private weak var browser: SKPhotoBrowser?
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
|
|
@ -40,7 +40,7 @@ class SKToolbar: UIToolbar {
|
|||
setupToolbar()
|
||||
}
|
||||
|
||||
func updateToolbar(_ currentPageIndex: Int) {
|
||||
func updateToolbar(currentPageIndex: Int) {
|
||||
guard let browser = browser else { return }
|
||||
|
||||
if browser.numberOfPhotos > 1 {
|
||||
|
|
@ -49,28 +49,28 @@ class SKToolbar: UIToolbar {
|
|||
toolCounterLabel.text = nil
|
||||
}
|
||||
|
||||
toolPreviousButton.isEnabled = (currentPageIndex > 0)
|
||||
toolNextButton.isEnabled = (currentPageIndex < browser.numberOfPhotos - 1)
|
||||
toolPreviousButton.enabled = (currentPageIndex > 0)
|
||||
toolNextButton.enabled = (currentPageIndex < browser.numberOfPhotos - 1)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SKToolbar {
|
||||
func setupApperance() {
|
||||
backgroundColor = UIColor.black.withAlphaComponent(0.65)
|
||||
backgroundColor = .clearColor()
|
||||
clipsToBounds = true
|
||||
isTranslucent = true
|
||||
setBackgroundImage(UIImage(), forToolbarPosition: .any, barMetrics: .default)
|
||||
translucent = true
|
||||
setBackgroundImage(UIImage(), forToolbarPosition: .Any, barMetrics: .Default)
|
||||
|
||||
// toolbar
|
||||
if !SKPhotoBrowserOptions.displayToolbar {
|
||||
isHidden = true
|
||||
hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
func setupToolbar() {
|
||||
guard let browser = browser else { return }
|
||||
|
||||
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
|
||||
let flexSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: self, action: nil)
|
||||
var items = [UIBarButtonItem]()
|
||||
items.append(flexSpace)
|
||||
if browser.numberOfPhotos > 1 && SKPhotoBrowserOptions.displayBackAndForwardButton {
|
||||
|
|
@ -95,30 +95,30 @@ private extension SKToolbar {
|
|||
|
||||
func setupPreviousButton() {
|
||||
let previousBtn = SKPreviousButton(frame: frame)
|
||||
previousBtn.addTarget(browser, action: #selector(SKPhotoBrowser.gotoPreviousPage), for: .touchUpInside)
|
||||
previousBtn.addTarget(browser, action: #selector(SKPhotoBrowser.gotoPreviousPage), forControlEvents: .TouchUpInside)
|
||||
toolPreviousButton = UIBarButtonItem(customView: previousBtn)
|
||||
}
|
||||
|
||||
func setupNextButton() {
|
||||
let nextBtn = SKNextButton(frame: frame)
|
||||
nextBtn.addTarget(browser, action: #selector(SKPhotoBrowser.gotoNextPage), for: .touchUpInside)
|
||||
nextBtn.addTarget(browser, action: #selector(SKPhotoBrowser.gotoNextPage), forControlEvents: .TouchUpInside)
|
||||
toolNextButton = UIBarButtonItem(customView: nextBtn)
|
||||
}
|
||||
|
||||
func setupCounterLabel() {
|
||||
toolCounterLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 95, height: 40))
|
||||
toolCounterLabel.textAlignment = .center
|
||||
toolCounterLabel.backgroundColor = UIColor.clear
|
||||
toolCounterLabel.font = UIFont(name: "Helvetica", size: 16.0)
|
||||
toolCounterLabel.textColor = UIColor.white
|
||||
toolCounterLabel.shadowColor = UIColor.black
|
||||
toolCounterLabel.textAlignment = .Center
|
||||
toolCounterLabel.backgroundColor = .clearColor()
|
||||
toolCounterLabel.font = SKPhotoBrowserOptions.toolbarFont
|
||||
toolCounterLabel.textColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
toolCounterLabel.shadowColor = SKPhotoBrowserOptions.toolbarTextShadowColor
|
||||
toolCounterLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
|
||||
toolCounterButton = UIBarButtonItem(customView: toolCounterLabel)
|
||||
}
|
||||
|
||||
func setupActionButton() {
|
||||
toolActionButton = UIBarButtonItem(barButtonSystemItem: .action, target: browser, action: #selector(SKPhotoBrowser.actionButtonPressed))
|
||||
toolActionButton.tintColor = UIColor.white
|
||||
toolActionButton = UIBarButtonItem(barButtonSystemItem: .Action, target: browser, action: #selector(SKPhotoBrowser.actionButtonPressed))
|
||||
toolActionButton.tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,16 +126,17 @@ private extension SKToolbar {
|
|||
class SKToolbarButton: UIButton {
|
||||
let insets: UIEdgeInsets = UIEdgeInsets(top: 13.25, left: 17.25, bottom: 13.25, right: 17.25)
|
||||
|
||||
func setup(_ imageName: String) {
|
||||
backgroundColor = UIColor.clear
|
||||
func setup(imageName: String) {
|
||||
backgroundColor = .clearColor()
|
||||
tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
imageEdgeInsets = insets
|
||||
translatesAutoresizingMaskIntoConstraints = true
|
||||
autoresizingMask = [.flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin]
|
||||
contentMode = .center
|
||||
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
|
||||
contentMode = .Center
|
||||
|
||||
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
|
||||
in: bundle, compatibleWith: nil) ?? UIImage()
|
||||
setImage(image, for: UIControlState())
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage()
|
||||
setImage(image, forState: .Normal)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,4 +162,4 @@ class SKNextButton: SKToolbarButton {
|
|||
super.init(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
|
||||
setup(imageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
open class SKZoomingScrollView: UIScrollView {
|
||||
public class SKZoomingScrollView: UIScrollView {
|
||||
var captionView: SKCaptionView!
|
||||
var photo: SKPhotoProtocol! {
|
||||
didSet {
|
||||
|
|
@ -19,10 +19,10 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate(set) var photoImageView: SKDetectingImageView!
|
||||
fileprivate weak var photoBrowser: SKPhotoBrowser?
|
||||
fileprivate var tapView: SKDetectingView!
|
||||
fileprivate var indicatorView: SKIndicatorView!
|
||||
private(set) var photoImageView: SKDetectingImageView!
|
||||
private weak var photoBrowser: SKPhotoBrowser?
|
||||
private var tapView: SKDetectingView!
|
||||
private var indicatorView: SKIndicatorView!
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
|
|
@ -48,15 +48,15 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
// tap
|
||||
tapView = SKDetectingView(frame: bounds)
|
||||
tapView.delegate = self
|
||||
tapView.backgroundColor = UIColor.clear
|
||||
tapView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
tapView.backgroundColor = .clearColor()
|
||||
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
|
||||
addSubview(tapView)
|
||||
|
||||
// image
|
||||
photoImageView = SKDetectingImageView(frame: frame)
|
||||
photoImageView.delegate = self
|
||||
photoImageView.contentMode = .bottom
|
||||
photoImageView.backgroundColor = UIColor.clear
|
||||
photoImageView.contentMode = .Bottom
|
||||
photoImageView.backgroundColor = .clearColor()
|
||||
addSubview(photoImageView)
|
||||
|
||||
// indicator
|
||||
|
|
@ -64,17 +64,17 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
addSubview(indicatorView)
|
||||
|
||||
// self
|
||||
backgroundColor = UIColor.clear
|
||||
backgroundColor = .clearColor()
|
||||
delegate = self
|
||||
showsHorizontalScrollIndicator = false
|
||||
showsVerticalScrollIndicator = false
|
||||
decelerationRate = UIScrollViewDecelerationRateFast
|
||||
autoresizingMask = [.flexibleWidth, .flexibleTopMargin, .flexibleBottomMargin, .flexibleRightMargin, .flexibleLeftMargin]
|
||||
autoresizingMask = [.FlexibleWidth, .FlexibleTopMargin, .FlexibleBottomMargin, .FlexibleRightMargin, .FlexibleLeftMargin]
|
||||
}
|
||||
|
||||
// MARK: - override
|
||||
|
||||
open override func layoutSubviews() {
|
||||
public override func layoutSubviews() {
|
||||
tapView.frame = bounds
|
||||
indicatorView.frame = bounds
|
||||
|
||||
|
|
@ -97,12 +97,12 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
}
|
||||
|
||||
// Center
|
||||
if !photoImageView.frame.equalTo(frameToCenter) {
|
||||
if !CGRectEqualToRect(photoImageView.frame, frameToCenter) {
|
||||
photoImageView.frame = frameToCenter
|
||||
}
|
||||
}
|
||||
|
||||
open func setMaxMinZoomScalesForCurrentBounds() {
|
||||
public func setMaxMinZoomScalesForCurrentBounds() {
|
||||
maximumZoomScale = 1
|
||||
minimumZoomScale = 1
|
||||
zoomScale = 1
|
||||
|
|
@ -114,18 +114,18 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
let boundsSize = bounds.size
|
||||
let imageSize = photoImageView.frame.size
|
||||
|
||||
let xScale = CGFloat(Int(boundsSize.width / imageSize.width * 100)) / 100
|
||||
let yScale = CGFloat(Int(boundsSize.height / imageSize.height * 100)) / 100
|
||||
let xScale = boundsSize.width / imageSize.width
|
||||
let yScale = boundsSize.height / imageSize.height
|
||||
let minScale: CGFloat = min(xScale, yScale)
|
||||
var maxScale: CGFloat = 1.0
|
||||
|
||||
let scale = max(UIScreen.main.scale, 2.0)
|
||||
let deviceScreenWidth = UIScreen.main.bounds.width * scale // width in pixels. scale needs to remove if to use the old algorithm
|
||||
let deviceScreenHeight = UIScreen.main.bounds.height * scale // height in pixels. scale needs to remove if to use the old algorithm
|
||||
let scale = max(UIScreen.mainScreen().scale, 2.0)
|
||||
let deviceScreenWidth = UIScreen.mainScreen().bounds.width * scale // width in pixels. scale needs to remove if to use the old algorithm
|
||||
let deviceScreenHeight = UIScreen.mainScreen().bounds.height * scale // height in pixels. scale needs to remove if to use the old algorithm
|
||||
|
||||
if photoImageView.frame.width < deviceScreenWidth {
|
||||
// I think that we should to get coefficient between device screen width and image width and assign it to maxScale. I made two mode that we will get the same result for different device orientations.
|
||||
if UIApplication.shared.statusBarOrientation.isPortrait {
|
||||
if UIApplication.sharedApplication().statusBarOrientation.isPortrait {
|
||||
maxScale = deviceScreenHeight / photoImageView.frame.width
|
||||
} else {
|
||||
maxScale = deviceScreenWidth / photoImageView.frame.width
|
||||
|
|
@ -156,7 +156,7 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
setNeedsLayout()
|
||||
}
|
||||
|
||||
open func prepareForReuse() {
|
||||
public func prepareForReuse() {
|
||||
photo = nil
|
||||
if captionView != nil {
|
||||
captionView.removeFromSuperview()
|
||||
|
|
@ -165,7 +165,7 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
}
|
||||
|
||||
// MARK: - image
|
||||
open func displayImage(complete flag: Bool) {
|
||||
public func displayImage(complete flag: Bool) {
|
||||
// reset scale
|
||||
maximumZoomScale = 1
|
||||
minimumZoomScale = 1
|
||||
|
|
@ -182,10 +182,25 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
}
|
||||
|
||||
if let image = photo.underlyingImage {
|
||||
|
||||
// FIXED: Scrolling performance slowed #145
|
||||
|
||||
// create padding
|
||||
// let width: CGFloat = image.size.width + SKPhotoBrowserOptions.imagePaddingX
|
||||
// let height: CGFloat = image.size.height + SKPhotoBrowserOptions.imagePaddingY;
|
||||
// UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), false, 0.0);
|
||||
// let context: CGContextRef = UIGraphicsGetCurrentContext()!;
|
||||
// UIGraphicsPushContext(context);
|
||||
// let origin: CGPoint = CGPointMake((width - image.size.width) / 2, (height - image.size.height) / 2);
|
||||
// image.drawAtPoint(origin)
|
||||
// UIGraphicsPopContext();
|
||||
// let imageWithPadding = UIGraphicsGetImageFromCurrentImageContext();
|
||||
// UIGraphicsEndImageContext();
|
||||
|
||||
// image
|
||||
photoImageView.image = image
|
||||
photoImageView.contentMode = photo.contentMode
|
||||
photoImageView.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
|
||||
var photoImageViewFrame = CGRect.zero
|
||||
photoImageViewFrame.origin = CGPoint.zero
|
||||
|
|
@ -200,14 +215,14 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
setNeedsLayout()
|
||||
}
|
||||
|
||||
open func displayImageFailure() {
|
||||
public func displayImageFailure() {
|
||||
indicatorView.stopAnimating()
|
||||
}
|
||||
|
||||
// MARK: - handle tap
|
||||
open func handleDoubleTap(_ touchPoint: CGPoint) {
|
||||
public func handleDoubleTap(touchPoint: CGPoint) {
|
||||
if let photoBrowser = photoBrowser {
|
||||
NSObject.cancelPreviousPerformRequests(withTarget: photoBrowser)
|
||||
NSObject.cancelPreviousPerformRequestsWithTarget(photoBrowser)
|
||||
}
|
||||
|
||||
if zoomScale > minimumZoomScale {
|
||||
|
|
@ -222,7 +237,7 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
}
|
||||
*/
|
||||
let zoomRect = zoomRectForScrollViewWith(maximumZoomScale, touchPoint: touchPoint)
|
||||
zoom(to: zoomRect, animated: true)
|
||||
zoomToRect(zoomRect, animated: true)
|
||||
}
|
||||
|
||||
// delay control
|
||||
|
|
@ -233,15 +248,15 @@ open class SKZoomingScrollView: UIScrollView {
|
|||
// MARK: - UIScrollViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: UIScrollViewDelegate {
|
||||
public func viewForZooming(in scrollView: UIScrollView) -> UIView? {
|
||||
public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
|
||||
return photoImageView
|
||||
}
|
||||
|
||||
public func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
|
||||
public func scrollViewWillBeginZooming(scrollView: UIScrollView, withView view: UIView?) {
|
||||
photoBrowser?.cancelControlHiding()
|
||||
}
|
||||
|
||||
public func scrollViewDidZoom(_ scrollView: UIScrollView) {
|
||||
public func scrollViewDidZoom(scrollView: UIScrollView) {
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
|
@ -250,7 +265,7 @@ extension SKZoomingScrollView: UIScrollViewDelegate {
|
|||
// MARK: - SKDetectingImageViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: SKDetectingViewDelegate {
|
||||
func handleSingleTap(_ view: UIView, touch: UITouch) {
|
||||
func handleSingleTap(view: UIView, touch: UITouch) {
|
||||
guard let browser = photoBrowser else {
|
||||
return
|
||||
}
|
||||
|
|
@ -259,13 +274,13 @@ extension SKZoomingScrollView: SKDetectingViewDelegate {
|
|||
}
|
||||
|
||||
if browser.areControlsHidden() == false && SKPhotoBrowserOptions.enableSingleTapDismiss == true {
|
||||
browser.determineAndClose(sender: nil)
|
||||
browser.determineAndClose()
|
||||
} else {
|
||||
browser.toggleControls()
|
||||
}
|
||||
}
|
||||
|
||||
func handleDoubleTap(_ view: UIView, touch: UITouch) {
|
||||
func handleDoubleTap(view: UIView, touch: UITouch) {
|
||||
if SKPhotoBrowserOptions.enableZoomBlackArea == true {
|
||||
let needPoint = getViewFramePercent(view, touch: touch)
|
||||
handleDoubleTap(needPoint)
|
||||
|
|
@ -277,26 +292,26 @@ extension SKZoomingScrollView: SKDetectingViewDelegate {
|
|||
// MARK: - SKDetectingImageViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: SKDetectingImageViewDelegate {
|
||||
func handleImageViewSingleTap(_ touchPoint: CGPoint) {
|
||||
func handleImageViewSingleTap(touchPoint: CGPoint) {
|
||||
guard let browser = photoBrowser else {
|
||||
return
|
||||
}
|
||||
if SKPhotoBrowserOptions.enableSingleTapDismiss {
|
||||
browser.determineAndClose(sender: nil)
|
||||
browser.determineAndClose()
|
||||
} else {
|
||||
browser.toggleControls()
|
||||
}
|
||||
}
|
||||
|
||||
func handleImageViewDoubleTap(_ touchPoint: CGPoint) {
|
||||
func handleImageViewDoubleTap(touchPoint: CGPoint) {
|
||||
handleDoubleTap(touchPoint)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SKZoomingScrollView {
|
||||
func getViewFramePercent(_ view: UIView, touch: UITouch) -> CGPoint {
|
||||
func getViewFramePercent(view: UIView, touch: UITouch) -> CGPoint {
|
||||
let oneWidthViewPercent = view.bounds.width / 100
|
||||
let viewTouchPoint = touch.location(in: view)
|
||||
let viewTouchPoint = touch.locationInView(view)
|
||||
let viewWidthTouch = viewTouchPoint.x
|
||||
let viewPercentTouch = viewWidthTouch / oneWidthViewPercent
|
||||
|
||||
|
|
@ -315,11 +330,11 @@ private extension SKZoomingScrollView {
|
|||
return allPoint
|
||||
}
|
||||
|
||||
func zoomRectForScrollViewWith(_ scale: CGFloat, touchPoint: CGPoint) -> CGRect {
|
||||
func zoomRectForScrollViewWith(scale: CGFloat, touchPoint: CGPoint) -> CGRect {
|
||||
let w = frame.size.width / scale
|
||||
let h = frame.size.height / scale
|
||||
let x = touchPoint.x - (h / max(UIScreen.main.scale, 2.0))
|
||||
let y = touchPoint.y - (w / max(UIScreen.main.scale, 2.0))
|
||||
let x = touchPoint.x - (h / max(UIScreen.mainScreen().scale, 2.0))
|
||||
let y = touchPoint.y - (w / max(UIScreen.mainScreen().scale, 2.0))
|
||||
|
||||
return CGRect(x: x, y: y, width: w, height: h)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import UIKit
|
|||
extension UIImage {
|
||||
func rotateImageByOrientation() -> UIImage {
|
||||
// No-op if the orientation is already correct
|
||||
guard self.imageOrientation != .up else {
|
||||
guard self.imageOrientation != .Up else {
|
||||
return self
|
||||
}
|
||||
|
||||
|
|
@ -19,58 +19,58 @@ extension UIImage {
|
|||
|
||||
// Now we draw the underlying CGImage into a new context, applying the transform
|
||||
// calculated above.
|
||||
let ctx = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height),
|
||||
bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0,
|
||||
space: self.cgImage!.colorSpace!,
|
||||
bitmapInfo: self.cgImage!.bitmapInfo.rawValue)
|
||||
ctx!.concatenate(transform)
|
||||
let ctx = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height),
|
||||
CGImageGetBitsPerComponent(self.CGImage!), 0,
|
||||
CGImageGetColorSpace(self.CGImage!)!,
|
||||
CGImageGetBitmapInfo(self.CGImage!).rawValue)
|
||||
CGContextConcatCTM(ctx!, transform)
|
||||
|
||||
switch self.imageOrientation {
|
||||
case .left, .leftMirrored, .right, .rightMirrored:
|
||||
ctx!.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
|
||||
case .Left, .LeftMirrored, .Right, .RightMirrored:
|
||||
CGContextDrawImage(ctx!, CGRect(x: 0, y: 0, width: size.height, height: size.width), self.CGImage!)
|
||||
|
||||
default:
|
||||
ctx!.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
|
||||
CGContextDrawImage(ctx!, CGRect(x: 0, y: 0, width: size.width, height: size.height), self.CGImage!)
|
||||
}
|
||||
|
||||
// And now we just create a new UIImage from the drawing context
|
||||
if let cgImage = ctx!.makeImage() {
|
||||
return UIImage(cgImage: cgImage)
|
||||
if let cgImage = CGBitmapContextCreateImage(ctx!) {
|
||||
return UIImage(CGImage: cgImage)
|
||||
} else {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func calculateAffineTransform() -> CGAffineTransform {
|
||||
private func calculateAffineTransform() -> CGAffineTransform {
|
||||
// We need to calculate the proper transformation to make the image upright.
|
||||
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
|
||||
var transform = CGAffineTransform.identity
|
||||
var transform = CGAffineTransformIdentity
|
||||
|
||||
switch self.imageOrientation {
|
||||
case .down, .downMirrored:
|
||||
transform = transform.translatedBy(x: self.size.width, y: self.size.height)
|
||||
transform = transform.rotated(by: CGFloat(M_PI))
|
||||
case .Down, .DownMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
|
||||
transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
|
||||
|
||||
case .left, .leftMirrored:
|
||||
transform = transform.translatedBy(x: self.size.width, y: 0)
|
||||
transform = transform.rotated(by: CGFloat(M_PI_2))
|
||||
case .Left, .LeftMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
|
||||
|
||||
case .right, .rightMirrored:
|
||||
transform = transform.translatedBy(x: 0, y: self.size.height)
|
||||
transform = transform.rotated(by: CGFloat(-M_PI_2))
|
||||
case .Right, .RightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, 0, self.size.height)
|
||||
transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
switch self.imageOrientation {
|
||||
case .upMirrored, .downMirrored:
|
||||
transform = transform.translatedBy(x: self.size.width, y: 0)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
case .UpMirrored, .DownMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
case .leftMirrored, .rightMirrored:
|
||||
transform = transform.translatedBy(x: self.size.height, y: 0)
|
||||
transform = transform.scaledBy(x: -1, y: 1)
|
||||
case .LeftMirrored, .RightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.height, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
default:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
func addCornerRadiusAnimation(_ from: CGFloat, to: CGFloat, duration: CFTimeInterval) {
|
||||
func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval) {
|
||||
let animation = CABasicAnimation(keyPath: "cornerRadius")
|
||||
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
|
||||
animation.fromValue = from
|
||||
animation.toValue = to
|
||||
animation.duration = duration
|
||||
self.layer.add(animation, forKey: "cornerRadius")
|
||||
self.layer.addAnimation(animation, forKey: "cornerRadius")
|
||||
self.layer.cornerRadius = to
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
platform :ios, '9.0'
|
||||
platform :ios, '8.0'
|
||||
use_frameworks!
|
||||
|
||||
target "SKPhotoBrowserExample" do
|
||||
pod 'SDWebImage', '~>3.8'
|
||||
end
|
||||
pod 'SDWebImage', '~>3.8'
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,4 @@ DEPENDENCIES:
|
|||
SPEC CHECKSUMS:
|
||||
SDWebImage: 35f9627a3e44b4f292a8a8ce6a531fa488239b91
|
||||
|
||||
PODFILE CHECKSUM: a32274f1ce260fbc242dfd48f2b1af8a84a5bc0e
|
||||
|
||||
COCOAPODS: 1.1.0.beta.2
|
||||
COCOAPODS: 0.39.0
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
212705891C92C69C00466223 /* FromCameraRollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 212705881C92C69C00466223 /* FromCameraRollViewController.swift */; };
|
||||
88ABF7F872EE84010BCE3BD6 /* Pods_SKPhotoBrowserExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB686E31A24C3FFC5B05ECF8 /* Pods_SKPhotoBrowserExample.framework */; };
|
||||
8909B55B1BC792150060A053 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8909B55A1BC792150060A053 /* AppDelegate.swift */; };
|
||||
8909B55D1BC792150060A053 /* FromLocalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8909B55C1BC792150060A053 /* FromLocalViewController.swift */; };
|
||||
8909B5601BC792150060A053 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8909B55E1BC792150060A053 /* Main.storyboard */; };
|
||||
|
|
@ -29,6 +28,7 @@
|
|||
89FC5DBB1D54A04900F1BE52 /* FromWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC5DBA1D54A04900F1BE52 /* FromWebViewController.swift */; };
|
||||
A6A7B7801C9578E30025AC07 /* SKPhotoBrowser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8909B5711BC792570060A053 /* SKPhotoBrowser.framework */; };
|
||||
A6A7B7811C9578E30025AC07 /* SKPhotoBrowser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8909B5711BC792570060A053 /* SKPhotoBrowser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
DDFD24AF2FBA5A60984D378D /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C2188E912BB106233AA4AB2 /* Pods.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -71,8 +71,6 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
212705881C92C69C00466223 /* FromCameraRollViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FromCameraRollViewController.swift; sourceTree = "<group>"; };
|
||||
241888FD69B198BD34C3C0BB /* Pods-SKPhotoBrowserExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SKPhotoBrowserExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SKPhotoBrowserExample/Pods-SKPhotoBrowserExample.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4646E40B4CEC62B4734AB729 /* Pods-SKPhotoBrowserExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SKPhotoBrowserExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SKPhotoBrowserExample/Pods-SKPhotoBrowserExample.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7C2188E912BB106233AA4AB2 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8909B5571BC792150060A053 /* SKPhotoBrowserExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SKPhotoBrowserExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8909B55A1BC792150060A053 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -95,7 +93,8 @@
|
|||
8909B57F1BC792DC0060A053 /* image8.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image8.jpg; sourceTree = "<group>"; };
|
||||
8909B5801BC792DC0060A053 /* image9.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image9.jpg; sourceTree = "<group>"; };
|
||||
89FC5DBA1D54A04900F1BE52 /* FromWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FromWebViewController.swift; sourceTree = "<group>"; };
|
||||
BB686E31A24C3FFC5B05ECF8 /* Pods_SKPhotoBrowserExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SKPhotoBrowserExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B3E081D4F2C8623852C459F5 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
DD077DBD0C164C96BCC7494F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -104,30 +103,21 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A6A7B7801C9578E30025AC07 /* SKPhotoBrowser.framework in Frameworks */,
|
||||
88ABF7F872EE84010BCE3BD6 /* Pods_SKPhotoBrowserExample.framework in Frameworks */,
|
||||
DDFD24AF2FBA5A60984D378D /* Pods.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
4462E0EB8EBBBA6309EEEEB9 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4646E40B4CEC62B4734AB729 /* Pods-SKPhotoBrowserExample.debug.xcconfig */,
|
||||
241888FD69B198BD34C3C0BB /* Pods-SKPhotoBrowserExample.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8909B54E1BC792150060A053 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8909B56C1BC792570060A053 /* SKPhotoBrowser.xcodeproj */,
|
||||
8909B5591BC792150060A053 /* SKPhotoBrowserExample */,
|
||||
8909B5581BC792150060A053 /* Products */,
|
||||
D1D8ECD45B290372235B8168 /* Pods */,
|
||||
C646D2C27A5B9CCC003A9BD1 /* Frameworks */,
|
||||
4462E0EB8EBBBA6309EEEEB9 /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -219,11 +209,19 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
7C2188E912BB106233AA4AB2 /* Pods.framework */,
|
||||
BB686E31A24C3FFC5B05ECF8 /* Pods_SKPhotoBrowserExample.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D1D8ECD45B290372235B8168 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B3E081D4F2C8623852C459F5 /* Pods.debug.xcconfig */,
|
||||
DD077DBD0C164C96BCC7494F /* Pods.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
|
@ -231,13 +229,13 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8909B5691BC792150060A053 /* Build configuration list for PBXNativeTarget "SKPhotoBrowserExample" */;
|
||||
buildPhases = (
|
||||
E821EE59F7DDA23D9BBBB509 /* [CP] Check Pods Manifest.lock */,
|
||||
F19A62C34B2F0CFF753F30C3 /* Check Pods Manifest.lock */,
|
||||
8909B5531BC792150060A053 /* Sources */,
|
||||
8909B5541BC792150060A053 /* Frameworks */,
|
||||
8909B5551BC792150060A053 /* Resources */,
|
||||
A6A7B7841C9578E30025AC07 /* Embed Frameworks */,
|
||||
B9953EC3B1AD6BDFDD63D74C /* [CP] Embed Pods Frameworks */,
|
||||
554ADE9B9A609F47590589FC /* [CP] Copy Pods Resources */,
|
||||
575DBD5855AB711E5773767A /* Embed Pods Frameworks */,
|
||||
2ECF43C4E99CDE3D98AE6842 /* Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
|
@ -255,7 +253,7 @@
|
|||
8909B54F1BC792150060A053 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 0700;
|
||||
ORGANIZATIONNAME = suzuki_keishi;
|
||||
TargetAttributes = {
|
||||
8909B5561BC792150060A053 = {
|
||||
|
|
@ -331,49 +329,49 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
554ADE9B9A609F47590589FC /* [CP] Copy Pods Resources */ = {
|
||||
2ECF43C4E99CDE3D98AE6842 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SKPhotoBrowserExample/Pods-SKPhotoBrowserExample-resources.sh\"\n";
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
B9953EC3B1AD6BDFDD63D74C /* [CP] Embed Pods Frameworks */ = {
|
||||
575DBD5855AB711E5773767A /* Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
name = "Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SKPhotoBrowserExample/Pods-SKPhotoBrowserExample-frameworks.sh\"\n";
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E821EE59F7DDA23D9BBBB509 /* [CP] Check Pods Manifest.lock */ = {
|
||||
F19A62C34B2F0CFF753F30C3 /* Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
name = "Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../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";
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
|
@ -433,10 +431,8 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -480,10 +476,8 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -502,7 +496,6 @@
|
|||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
|
|
@ -510,31 +503,31 @@
|
|||
};
|
||||
8909B56A1BC792150060A053 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 4646E40B4CEC62B4734AB729 /* Pods-SKPhotoBrowserExample.debug.xcconfig */;
|
||||
baseConfigurationReference = B3E081D4F2C8623852C459F5 /* Pods.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = SKPhotoBrowserExample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.keishi.suzuki.aSKPhotoBrowserExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8909B56B1BC792150060A053 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 241888FD69B198BD34C3C0BB /* Pods-SKPhotoBrowserExample.release.xcconfig */;
|
||||
baseConfigurationReference = DD077DBD0C164C96BCC7494F /* Pods.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = SKPhotoBrowserExample/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.keishi.suzuki.aSKPhotoBrowserExample;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
func applicationWillResignActive(application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
func applicationDidEnterBackground(application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
func applicationWillEnterForeground(application: UIApplication) {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
func applicationDidBecomeActive(application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
func applicationWillTerminate(application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,22 +14,22 @@ class FromCameraRollViewController: UIViewController, SKPhotoBrowserDelegate, UI
|
|||
|
||||
@IBOutlet weak var collectionView: UICollectionView!
|
||||
|
||||
fileprivate let imageManager = PHCachingImageManager.default()
|
||||
private let imageManager = PHCachingImageManager.defaultManager()
|
||||
|
||||
fileprivate var assets: [PHAsset] = []
|
||||
private var assets: [PHAsset] = []
|
||||
|
||||
fileprivate lazy var requestOptions: PHImageRequestOptions = {
|
||||
private lazy var requestOptions: PHImageRequestOptions = {
|
||||
let options = PHImageRequestOptions()
|
||||
options.deliveryMode = .opportunistic
|
||||
options.resizeMode = .fast
|
||||
options.deliveryMode = .Opportunistic
|
||||
options.resizeMode = .Fast
|
||||
|
||||
return options
|
||||
}()
|
||||
|
||||
fileprivate lazy var bigRequestOptions: PHImageRequestOptions = {
|
||||
private lazy var bigRequestOptions: PHImageRequestOptions = {
|
||||
let options = PHImageRequestOptions()
|
||||
options.deliveryMode = .highQualityFormat
|
||||
options.resizeMode = .fast
|
||||
options.deliveryMode = .HighQualityFormat
|
||||
options.resizeMode = .Fast
|
||||
|
||||
return options
|
||||
}()
|
||||
|
|
@ -58,21 +58,21 @@ class FromCameraRollViewController: UIViewController, SKPhotoBrowserDelegate, UI
|
|||
|
||||
// MARK: UICollectionViewDataSource
|
||||
|
||||
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
|
||||
// #warning Incomplete implementation, return the number of sections
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
// #warning Incomplete implementation, return the number of items
|
||||
return assets.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "exampleCollectionViewCell", for: indexPath)
|
||||
let asset = assets[(indexPath as NSIndexPath).row]
|
||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("exampleCollectionViewCell", forIndexPath: indexPath)
|
||||
let asset = assets[indexPath.row]
|
||||
|
||||
if let cell = cell as? AssetExampleCollectionViewCell {
|
||||
if let id = cell.requestId {
|
||||
|
|
@ -91,16 +91,16 @@ class FromCameraRollViewController: UIViewController, SKPhotoBrowserDelegate, UI
|
|||
return cell
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? ExampleCollectionViewCell else {
|
||||
guard let cell = collectionView.cellForItemAtIndexPath(indexPath) as? ExampleCollectionViewCell else {
|
||||
return
|
||||
}
|
||||
guard let originImage = cell.exampleImageView.image else {
|
||||
return
|
||||
}
|
||||
|
||||
func open(_ images: [UIImage]) {
|
||||
func open(images: [UIImage]) {
|
||||
|
||||
let photoImages: [SKPhotoProtocol] = images.map({ return SKPhoto.photoWithImage($0) })
|
||||
let browser = SKPhotoBrowser(originImage: cell.exampleImageView.image!, photos: photoImages, animatedFromView: cell)
|
||||
|
|
@ -110,17 +110,17 @@ class FromCameraRollViewController: UIViewController, SKPhotoBrowserDelegate, UI
|
|||
// browser.bounceAnimation = true
|
||||
// browser.displayDeleteButton = true
|
||||
// browser.displayAction = false
|
||||
self.present(browser, animated: true, completion: {})
|
||||
self.presentViewController(browser, animated: true, completion: {})
|
||||
}
|
||||
|
||||
var fetchedImages: [UIImage] = Array<UIImage>(repeating: UIImage(), count: assets.count)
|
||||
var fetchedImages: [UIImage] = Array<UIImage>(count: assets.count, repeatedValue: UIImage())
|
||||
var fetched = 0
|
||||
|
||||
assets.forEach { (asset) -> () in
|
||||
|
||||
_ = requestImageForAsset(asset, options:bigRequestOptions, completion: { [weak self] (image, requestId) -> () in
|
||||
requestImageForAsset(asset, options:bigRequestOptions, completion: { [weak self] (image, requestId) -> () in
|
||||
|
||||
if let image = image, let index = self?.assets.index(of: asset) {
|
||||
if let image = image, index = self?.assets.indexOf(asset) {
|
||||
fetchedImages[index] = image
|
||||
}
|
||||
fetched += 1
|
||||
|
|
@ -132,55 +132,55 @@ class FromCameraRollViewController: UIViewController, SKPhotoBrowserDelegate, UI
|
|||
}
|
||||
}
|
||||
|
||||
fileprivate func fetchAssets() {
|
||||
private func fetchAssets() {
|
||||
|
||||
let options = PHFetchOptions()
|
||||
let limit = 8
|
||||
|
||||
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
|
||||
options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
|
||||
options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
|
||||
|
||||
options.fetchLimit = limit
|
||||
|
||||
let result = PHAsset.fetchAssets(with: options)
|
||||
let result = PHAsset.fetchAssetsWithOptions(options)
|
||||
let amount = min(result.count, limit)
|
||||
self.assets = result.objects(at: IndexSet(integersIn: NSRange(location: 0, length: amount).toRange() ?? 0..<0))
|
||||
self.assets = result.objectsAtIndexes(NSIndexSet(indexesInRange: NSRange(location: 0, length: amount))) as? [PHAsset] ?? []
|
||||
}
|
||||
|
||||
fileprivate func requestImageForAsset(_ asset: PHAsset, options: PHImageRequestOptions, completion: @escaping (_ image: UIImage?, _ requestId: PHImageRequestID?) -> ()) -> PHImageRequestID {
|
||||
private func requestImageForAsset(asset: PHAsset, options: PHImageRequestOptions, completion: (image: UIImage?, requestId: PHImageRequestID?) -> ()) -> PHImageRequestID {
|
||||
|
||||
let scale = UIScreen.main.scale
|
||||
let scale = UIScreen.mainScreen().scale
|
||||
let targetSize: CGSize
|
||||
|
||||
if options.deliveryMode == .highQualityFormat {
|
||||
if options.deliveryMode == .HighQualityFormat {
|
||||
targetSize = CGSize(width: 600 * scale, height: 600 * scale)
|
||||
} else {
|
||||
targetSize = CGSize(width: 182 * scale, height: 182 * scale)
|
||||
}
|
||||
|
||||
requestOptions.isSynchronous = false
|
||||
requestOptions.synchronous = false
|
||||
|
||||
// Workaround because PHImageManager.requestImageForAsset doesn't work for burst images
|
||||
if asset.representsBurst {
|
||||
return imageManager.requestImageData(for: asset, options: options) { data, _, _, dict in
|
||||
return imageManager.requestImageDataForAsset(asset, options: options) { data, _, _, dict in
|
||||
let image = data.flatMap { UIImage(data: $0) }
|
||||
let requestId = dict?[PHImageResultRequestIDKey] as? NSNumber
|
||||
completion(image, requestId?.int32Value)
|
||||
completion(image: image, requestId: requestId?.intValue)
|
||||
}
|
||||
} else {
|
||||
return imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: options) { image, dict in
|
||||
return imageManager.requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options) { image, dict in
|
||||
let requestId = dict?[PHImageResultRequestIDKey] as? NSNumber
|
||||
completion(image, requestId?.int32Value)
|
||||
completion(image: image, requestId: requestId?.intValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
override func prefersStatusBarHidden() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
override func preferredStatusBarStyle() -> UIStatusBarStyle {
|
||||
return .LightContent
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,28 +25,28 @@ class FromLocalViewController: UIViewController, UICollectionViewDataSource, UIC
|
|||
super.didReceiveMemoryWarning()
|
||||
}
|
||||
|
||||
override var prefersStatusBarHidden: Bool {
|
||||
override func prefersStatusBarHidden() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return .lightContent
|
||||
override func preferredStatusBarStyle() -> UIStatusBarStyle {
|
||||
return .LightContent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - UICollectionViewDataSource
|
||||
extension FromLocalViewController {
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return images.count
|
||||
}
|
||||
|
||||
@objc(collectionView:cellForItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "exampleCollectionViewCell", for: indexPath) as? ExampleCollectionViewCell else {
|
||||
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
guard let cell = collectionView.dequeueReusableCellWithReuseIdentifier("exampleCollectionViewCell", forIndexPath: indexPath) as? ExampleCollectionViewCell else {
|
||||
return UICollectionViewCell()
|
||||
}
|
||||
|
||||
cell.exampleImageView.image = UIImage(named: "image\((indexPath as NSIndexPath).row % 10).jpg")
|
||||
cell.exampleImageView.image = UIImage(named: "image\(indexPath.row % 10).jpg")
|
||||
// cell.exampleImageView.contentMode = .ScaleAspectFill
|
||||
return cell
|
||||
}
|
||||
|
|
@ -55,8 +55,8 @@ extension FromLocalViewController {
|
|||
// MARK: - UICollectionViewDelegate
|
||||
|
||||
extension FromLocalViewController {
|
||||
@objc(collectionView:didSelectItemAtIndexPath:) func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let cell = collectionView.cellForItem(at: indexPath) as? ExampleCollectionViewCell else {
|
||||
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
|
||||
guard let cell = collectionView.cellForItemAtIndexPath(indexPath) as? ExampleCollectionViewCell else {
|
||||
return
|
||||
}
|
||||
guard let originImage = cell.exampleImageView.image else {
|
||||
|
|
@ -70,14 +70,14 @@ extension FromLocalViewController {
|
|||
browser.delegate = self
|
||||
// browser.updateCloseButton(UIImage(named: "image1.jpg")!)
|
||||
|
||||
present(browser, animated: true, completion: {})
|
||||
presentViewController(browser, animated: true, completion: {})
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
|
||||
if UIDevice.current.userInterfaceIdiom == .pad {
|
||||
return CGSize(width: UIScreen.main.bounds.size.width / 2 - 5, height: 300)
|
||||
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
|
||||
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
|
||||
return CGSize(width: UIScreen.mainScreen().bounds.size.width / 2 - 5, height: 300)
|
||||
} else {
|
||||
return CGSize(width: UIScreen.main.bounds.size.width / 2 - 5, height: 200)
|
||||
return CGSize(width: UIScreen.mainScreen().bounds.size.width / 2 - 5, height: 200)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,45 +86,45 @@ extension FromLocalViewController {
|
|||
// MARK: - SKPhotoBrowserDelegate
|
||||
|
||||
extension FromLocalViewController {
|
||||
func didShowPhotoAtIndex(_ index: Int) {
|
||||
collectionView.visibleCells.forEach({$0.isHidden = false})
|
||||
collectionView.cellForItem(at: IndexPath(item: index, section: 0))?.isHidden = true
|
||||
func didShowPhotoAtIndex(index: Int) {
|
||||
collectionView.visibleCells().forEach({$0.hidden = false})
|
||||
collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: index, inSection: 0))?.hidden = true
|
||||
}
|
||||
|
||||
func willDismissAtPageIndex(_ index: Int) {
|
||||
collectionView.visibleCells.forEach({$0.isHidden = false})
|
||||
collectionView.cellForItem(at: IndexPath(item: index, section: 0))?.isHidden = true
|
||||
func willDismissAtPageIndex(index: Int) {
|
||||
collectionView.visibleCells().forEach({$0.hidden = false})
|
||||
collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: index, inSection: 0))?.hidden = true
|
||||
}
|
||||
|
||||
func willShowActionSheet(_ photoIndex: Int) {
|
||||
func willShowActionSheet(photoIndex: Int) {
|
||||
// do some handle if you need
|
||||
}
|
||||
|
||||
func didDismissAtPageIndex(_ index: Int) {
|
||||
collectionView.cellForItem(at: IndexPath(item: index, section: 0))?.isHidden = false
|
||||
func didDismissAtPageIndex(index: Int) {
|
||||
collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: index, inSection: 0))?.hidden = false
|
||||
}
|
||||
|
||||
func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int) {
|
||||
func didDismissActionSheetWithButtonIndex(buttonIndex: Int, photoIndex: Int) {
|
||||
// handle dismissing custom actions
|
||||
}
|
||||
|
||||
func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
|
||||
func removePhoto(browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
|
||||
reload()
|
||||
}
|
||||
|
||||
func viewForPhoto(_ browser: SKPhotoBrowser, index: Int) -> UIView? {
|
||||
return collectionView.cellForItem(at: IndexPath(item: index, section: 0))
|
||||
func viewForPhoto(browser: SKPhotoBrowser, index: Int) -> UIView? {
|
||||
return collectionView.cellForItemAtIndexPath(NSIndexPath(forItem: index, inSection: 0))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - private
|
||||
|
||||
private extension FromLocalViewController {
|
||||
func setupTestData() {
|
||||
private func setupTestData() {
|
||||
images = createLocalPhotos()
|
||||
}
|
||||
|
||||
func setupCollectionView() {
|
||||
private func setupCollectionView() {
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
}
|
||||
|
|
@ -166,4 +166,4 @@ var caption = ["Lorem Ipsum is simply dummy text of the printing and typesetting
|
|||
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
|
||||
"It has survived not only five centuries, but also the leap into electronic typesetting",
|
||||
"remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
|
||||
]
|
||||
]
|
||||
|
|
@ -18,31 +18,31 @@ class FromWebViewController: UIViewController, SKPhotoBrowserDelegate {
|
|||
super.viewDidLoad()
|
||||
|
||||
SKCache.sharedCache.imageCache = CustomImageCache()
|
||||
imageView.sd_setImage(with: URL(string: "https://placehold.jp/1500x1500.png")) {
|
||||
guard let url = $0.3?.absoluteString else { return }
|
||||
SKCache.sharedCache.setImage($0.0!, forKey: url)
|
||||
imageView.sd_setImageWithURL(NSURL(string: "https://placehold.jp/1500x1500.png")) {
|
||||
guard let url = $0.3.absoluteString else { return }
|
||||
SKCache.sharedCache.setImage($0.0, forKey: url)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func pushButton(_ sender: AnyObject) {
|
||||
@IBAction func pushButton(sender: AnyObject) {
|
||||
let browser = SKPhotoBrowser(photos: createWebPhotos())
|
||||
browser.initializePageIndex(0)
|
||||
browser.delegate = self
|
||||
|
||||
present(browser, animated: true, completion: nil)
|
||||
presentViewController(browser, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SKPhotoBrowserDelegate
|
||||
|
||||
extension FromWebViewController {
|
||||
func didDismissAtPageIndex(_ index: Int) {
|
||||
func didDismissAtPageIndex(index: Int) {
|
||||
}
|
||||
|
||||
func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int) {
|
||||
func didDismissActionSheetWithButtonIndex(buttonIndex: Int, photoIndex: Int) {
|
||||
}
|
||||
|
||||
func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
|
||||
func removePhoto(browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) {
|
||||
SKCache.sharedCache.removeImageForKey("somekey")
|
||||
reload()
|
||||
}
|
||||
|
|
@ -66,19 +66,19 @@ class CustomImageCache: SKImageCacheable {
|
|||
|
||||
init() {
|
||||
let cache = SDImageCache(namespace: "com.suzuki.custom.cache")
|
||||
self.cache = cache!
|
||||
self.cache = cache
|
||||
}
|
||||
|
||||
func imageForKey(_ key: String) -> UIImage? {
|
||||
guard let image = cache.imageFromDiskCache(forKey: key) else { return nil }
|
||||
func imageForKey(key: String) -> UIImage? {
|
||||
guard let image = cache.imageFromDiskCacheForKey(key) else { return nil }
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
func setImage(_ image: UIImage, forKey key: String) {
|
||||
cache.store(image, forKey: key)
|
||||
func setImage(image: UIImage, forKey key: String) {
|
||||
cache.storeImage(image, forKey: key)
|
||||
}
|
||||
|
||||
func removeImageForKey(_ key: String) {
|
||||
func removeImageForKey(key: String) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,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>NSPhotoLibraryUsageDescription</key>
|
||||
<string>for example, this app accesses the user’s photo library</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
|
@ -51,9 +53,5 @@
|
|||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Used to get photos</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Used to take photos</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
Loading…
Reference in New Issue