Compare commits
39 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e87ec9eb72 | |
|
|
2db02eecc0 | |
|
|
d40c5d2c2e | |
|
|
5714a95908 | |
|
|
8d2c1f3b38 | |
|
|
464114e40d | |
|
|
c3f8fa7e8a | |
|
|
3b275293b5 | |
|
|
6a591bcd5d | |
|
|
26378bae91 | |
|
|
709f024135 | |
|
|
49131da2e0 | |
|
|
1704f37363 | |
|
|
554dac6756 | |
|
|
de1f040c91 | |
|
|
c9e3749b0b | |
|
|
e55631cdec | |
|
|
d1b266c5b3 | |
|
|
2e5706c601 | |
|
|
06cd9c082d | |
|
|
a3b47e543e | |
|
|
4c068d83be | |
|
|
6ae7ad024e | |
|
|
5017c33a78 | |
|
|
08aeb6a147 | |
|
|
a53fad69a4 | |
|
|
95755537c3 | |
|
|
2dce338349 | |
|
|
850d584b57 | |
|
|
8fcdfcf535 | |
|
|
d5b42c8b47 | |
|
|
3d46160ef1 | |
|
|
9befa4cc10 | |
|
|
bde450fcff | |
|
|
b93e85dad0 | |
|
|
a091e2e94e | |
|
|
a9561d61d7 | |
|
|
f633789c65 | |
|
|
dca1f9dd4b |
84
CHANGELOG.md
84
CHANGELOG.md
|
|
@ -1,7 +1,51 @@
|
|||
# Change Log
|
||||
|
||||
## 2.1.x
|
||||
Released on 2016-8
|
||||
## 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
|
||||
|
||||
#### Fixed
|
||||
- Issue with multiple actionButtonTitles #137
|
||||
- fix swiftlint warnings #140
|
||||
- Update for Xcode 8 GM (swift 2.3). #141
|
||||
|
||||
## 3.0.2
|
||||
|
||||
Released on 9-2016
|
||||
|
||||
#### Fixed
|
||||
- Issue with multiple actionButtonTitles #137
|
||||
- Impossible to zoom when resolution is 1024x768 #134
|
||||
- Crash bug at zooming scrool view #133
|
||||
|
||||
## 3.0.1
|
||||
|
||||
Released on 9-2016
|
||||
|
||||
#### Fixed
|
||||
- Skip loading image if already loaded #135
|
||||
|
||||
Released on 8-2016
|
||||
|
||||
#### Some Interface is removed, changed this version.
|
||||
- status bar handling is removed.
|
||||
- custom button handling interface is chagned.
|
||||
- custom option goes internal/private. use option via SKPhotoBrowserOptions.
|
||||
|
||||
#### Add
|
||||
- Add changelog
|
||||
|
|
@ -18,7 +62,7 @@ Released on 2016-8
|
|||
- Some public property to internal for improving
|
||||
|
||||
## 2.0.x
|
||||
Released on 2016-8
|
||||
Released on 8-2016
|
||||
|
||||
#### Added
|
||||
- Migrate UIImage cache category to new SKCache
|
||||
|
|
@ -32,7 +76,7 @@ Released on 2016-8
|
|||
---
|
||||
|
||||
## 1.9.x
|
||||
Released on 2016-6
|
||||
Released on 6-2016
|
||||
|
||||
#### Added
|
||||
- Delegate to notify when the user scroll to an index
|
||||
|
|
@ -45,7 +89,7 @@ Released on 2016-6
|
|||
---
|
||||
|
||||
## 1.8.x
|
||||
Released on 2016-4
|
||||
Released on 4-2016
|
||||
|
||||
#### Added
|
||||
- Using SKPhotoProtocol to enable usage from SKLocalPhoto
|
||||
|
|
@ -60,7 +104,7 @@ Released on 2016-4
|
|||
---
|
||||
|
||||
## 1.7.x
|
||||
Released on 2016-3
|
||||
Released on 3-2016
|
||||
|
||||
#### Added
|
||||
- Enable ability to override statusBar style
|
||||
|
|
@ -95,7 +139,7 @@ Released on 2016-3
|
|||
---
|
||||
|
||||
## 1.4.x
|
||||
Released on 2016-2
|
||||
Released on 2-2016
|
||||
|
||||
#### Added
|
||||
- Delegate add for actionbutton.
|
||||
|
|
@ -107,7 +151,7 @@ Released on 2016-2
|
|||
---
|
||||
|
||||
## 1.3.x
|
||||
Released on 2016-1
|
||||
Released on 1-2016
|
||||
|
||||
#### Added
|
||||
- Added action functionality similar to IDMPhotoBrowser.
|
||||
|
|
@ -120,7 +164,7 @@ Released on 2016-1
|
|||
---
|
||||
|
||||
## 1.2.x
|
||||
Released on 2015-10
|
||||
Released on 10-2015
|
||||
|
||||
#### Added
|
||||
- SKPhotoProtocol is implemented.
|
||||
|
|
@ -131,30 +175,12 @@ Released on 2015-10
|
|||
---
|
||||
|
||||
## 1.1.x
|
||||
Released on 2015-10-09.
|
||||
Released on 10-2015
|
||||
|
||||
#### Fixed
|
||||
- some property make private.
|
||||
- layout bug fixed when zoom.
|
||||
|
||||
## 1.0.0
|
||||
Released on 2015-10-09.
|
||||
Released on 10-2015
|
||||
|
||||
#### Added
|
||||
- Tests for upload and download with progress.
|
||||
- Added by [Mattt Thompson](https://github.com/mattt).
|
||||
- Test for question marks in url encoded query.
|
||||
- Added by [Mattt Thompson](https://github.com/mattt).
|
||||
- The `NSURLSessionConfiguration` headers to `cURL` representation.
|
||||
- Added by [Matthias Ryne Cheow](https://github.com/rynecheow) in Pull Request
|
||||
[#140](https://github.com/Alamofire/Alamofire/pull/140).
|
||||
- Parameter encoding tests for key/value pairs containing spaces.
|
||||
- Added by [Mattt Thompson](https://github.com/mattt).
|
||||
- Percent character encoding for the `+` character.
|
||||
- Added by [Niels van Hoorn](https://github.com/nvh) in Pull Request
|
||||
[#167](https://github.com/Alamofire/Alamofire/pull/167).
|
||||
- Escaping for quotes to support JSON in `cURL` commands.
|
||||
- Added by [John Gibb](https://github.com/johngibb) in Pull Request
|
||||
[#178](https://github.com/Alamofire/Alamofire/pull/178).
|
||||
- The `request` method to the `Manager` bringing it more inline with the top-level methods.
|
||||
- Added by Brian Smith.
|
||||
|
|
|
|||
52
README.md
52
README.md
|
|
@ -1,11 +1,15 @@
|
|||
SKPhotoBrowser
|
||||
========================
|
||||
|
||||

|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](http://cocoadocs.org/docsets/SKPhotoBrowser)
|
||||
|
||||
Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift, based on [IDMPhotoBrowser](https://github.com/ideaismobile/IDMPhotoBrowser), [MWPhotoBrowser](https://github.com/mwaterfall/MWPhotoBrowser).
|
||||
|
||||
## Note
|
||||
- released v3.0.x and this version goes some breaking changes. please check [CHANGELOG](https://github.com/suzuki-0000/SKPhotoBrowser/blob/master/CHANGELOG.md).
|
||||
|
||||
## features
|
||||
- Display one or more images by providing either `UIImage` objects, or string of URL array.
|
||||
- Photos can be zoomed and panned, and optional captions can be displayed
|
||||
|
|
@ -103,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)
|
||||
|
||||
|
|
@ -127,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
|
||||
|
|
@ -146,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
|
||||
|
|
@ -180,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 = "2.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,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
|
|
@ -136,6 +138,7 @@
|
|||
8909B5411BC791510060A053 /* SKPhotoBrowser.swift */,
|
||||
89C24A811D657AD1005F09A9 /* SKPhotoBrowserOptions.swift */,
|
||||
890A6F1F1D5D9E53003B01F0 /* SKToolbar.swift */,
|
||||
0AE527511DABB87500619FAD /* SKNavigationBar.swift */,
|
||||
8909B5331BC791280060A053 /* SKPhotoBrowser.h */,
|
||||
8917B1AF1D5A13DE000CE1C4 /* SKPhotoBrowserDelegate.swift */,
|
||||
89D0BA481D59966B002A811B /* SKMesurement.swift */,
|
||||
|
|
@ -224,6 +227,7 @@
|
|||
};
|
||||
A64B89321CB04222000071B9 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -299,6 +303,7 @@
|
|||
8917B1B41D5A14B0000CE1C4 /* SKButtons.swift in Sources */,
|
||||
89C24A821D657AD1005F09A9 /* SKPhotoBrowserOptions.swift in Sources */,
|
||||
26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */,
|
||||
0AE527521DABB87500619FAD /* SKNavigationBar.swift in Sources */,
|
||||
210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */,
|
||||
8909B5431BC791510060A053 /* SKCaptionView.swift in Sources */,
|
||||
8909B5491BC791510060A053 /* SKPhotoBrowser.swift in Sources */,
|
||||
|
|
@ -463,6 +468,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -475,6 +481,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 2.3;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ private extension SKAnimator {
|
|||
self.resizableImageView?.frame = self.finalImageViewFrame
|
||||
},
|
||||
completion: { (Bool) -> Void in
|
||||
UIApplication.sharedApplication().setStatusBarHidden(!SKPhotoBrowserOptions.displayStatusbar, withAnimation: .Fade)
|
||||
|
||||
browser.view.hidden = false
|
||||
browser.view.alpha = 1.0
|
||||
browser.backgroundView.hidden = true
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ class SKButton: UIButton {
|
|||
var showFrame: CGRect!
|
||||
var hideFrame: CGRect!
|
||||
var insets: UIEdgeInsets {
|
||||
|
||||
|
||||
return UI_USER_INTERFACE_IDIOM() == .Phone
|
||||
? UIEdgeInsetsMake(15.25, 15.25, 15.25, 15.25) : UIEdgeInsetsMake(12, 12, 12, 12)
|
||||
? 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)
|
||||
var margin: CGFloat = 5
|
||||
|
|
@ -25,17 +27,25 @@ class SKButton: UIButton {
|
|||
|
||||
func setup(imageName: String) {
|
||||
backgroundColor = .clearColor()
|
||||
tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
imageEdgeInsets = insets
|
||||
// clipsToBounds = true
|
||||
translatesAutoresizingMaskIntoConstraints = true
|
||||
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
|
||||
|
||||
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil) ?? UIImage()
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage()
|
||||
setImage(image, forState: .Normal)
|
||||
}
|
||||
|
||||
func updateFrame() {}
|
||||
|
||||
func updateFrame() { }
|
||||
|
||||
func setFrameSize(size: CGSize) {
|
||||
let newRect = CGRect(x: margin, y: buttonTopOffset, width: size.width, height: size.height)
|
||||
self.frame = newRect
|
||||
showFrame = newRect
|
||||
hideFrame = CGRect(x: margin, y: -20, width: size.width, height: size.height)
|
||||
}
|
||||
}
|
||||
|
||||
class SKCloseButton: SKButton {
|
||||
|
|
@ -64,12 +74,17 @@ class SKDeleteButton: SKButton {
|
|||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
setup(imageName)
|
||||
showFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: buttonTopOffset,
|
||||
width: size.width, height: size.height)
|
||||
hideFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: -20,
|
||||
width: size.width, height: size.height)
|
||||
showFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: buttonTopOffset, width: size.width, height: size.height)
|
||||
hideFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: -20, width: size.width, height: size.height)
|
||||
}
|
||||
|
||||
override func updateFrame() {
|
||||
}
|
||||
|
||||
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
|
||||
hideFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: -20, width: size.width, height: size.height)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,13 +61,13 @@ private extension SKCaptionView {
|
|||
photoLabel.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
|
||||
photoLabel.opaque = false
|
||||
photoLabel.backgroundColor = .clearColor()
|
||||
photoLabel.textColor = .whiteColor()
|
||||
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.systemFontOfSize(17.0)
|
||||
photoLabel.font = SKPhotoBrowserOptions.captionFont
|
||||
photoLabel.text = photo?.caption
|
||||
addSubview(photoLabel)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import Foundation
|
|||
import UIKit
|
||||
|
||||
struct SKMesurement {
|
||||
static let isPhone: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Phone
|
||||
static let isPad: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Pad
|
||||
static var statusBarH: CGFloat {
|
||||
return UIApplication.sharedApplication().statusBarFrame.height
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// SKNavigationBar.swift
|
||||
// SKPhotoBrowser
|
||||
//
|
||||
// Created by Григорий Уланов on 10.10.16.
|
||||
// Copyright © 2016 suzuki_keishi. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SKNavigationBar: UINavigationBar {
|
||||
var showFrame: CGRect!
|
||||
var hideFrame: CGRect!
|
||||
|
||||
private static let toolBarHeight: CGFloat = 64.0
|
||||
|
||||
private weak var browser: SKPhotoBrowser?
|
||||
|
||||
convenience init(browser: SKPhotoBrowser) {
|
||||
self.init(frame: CGRect.zero)
|
||||
|
||||
self.browser = browser
|
||||
|
||||
translucent = false
|
||||
tintColor = UIColor.whiteColor()
|
||||
barTintColor = UIColor.blackColor()
|
||||
titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
|
||||
|
||||
let navigationItem = UINavigationItem()
|
||||
pushNavigationItem(navigationItem, animated: false)
|
||||
}
|
||||
|
||||
func updateNavigationBar(currentPageIndex: Int) {
|
||||
guard let browser = browser else { return }
|
||||
|
||||
if browser.numberOfPhotos > 1 {
|
||||
self.topItem?.title = "\(currentPageIndex + 1) \(SKPhotoBrowserOptions.navigationBarCounterSepatator) \(browser.numberOfPhotos)"
|
||||
} else {
|
||||
self.topItem?.title = nil
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func updateFrame(parentSize: CGSize) {
|
||||
let newRect = CGRect(x: 0, y: 0, width: parentSize.width, height: SKNavigationBar.toolBarHeight)
|
||||
setNewFrame(newRect)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,8 +28,8 @@ class SKPagingScrollView: UIScrollView {
|
|||
super.init(frame: frame)
|
||||
|
||||
pagingEnabled = true
|
||||
showsHorizontalScrollIndicator = true
|
||||
showsVerticalScrollIndicator = true
|
||||
showsHorizontalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator
|
||||
showsVerticalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator
|
||||
}
|
||||
|
||||
convenience init(frame: CGRect, browser: SKPhotoBrowser) {
|
||||
|
|
@ -210,7 +210,7 @@ private extension SKPagingScrollView {
|
|||
}
|
||||
|
||||
func getFirstIndex() -> Int {
|
||||
let firstIndex = Int(floor((CGRectGetMinX(bounds) + sideMargin * 2) / CGRectGetWidth(bounds)))
|
||||
let firstIndex = Int(floor((bounds.minX + sideMargin * 2) / bounds.width))
|
||||
if firstIndex < 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ private extension SKPagingScrollView {
|
|||
}
|
||||
|
||||
func getLastIndex() -> Int {
|
||||
let lastIndex = Int(floor((CGRectGetMaxX(bounds) - sideMargin * 2 - 1) / CGRectGetWidth(bounds)))
|
||||
let lastIndex = Int(floor((bounds.maxX - sideMargin * 2 - 1) / bounds.width))
|
||||
if lastIndex < 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,9 @@ public class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
|
||||
public func loadUnderlyingImageAndNotify() {
|
||||
|
||||
if underlyingImage != nil && photoURL == nil {
|
||||
if underlyingImage != nil {
|
||||
loadUnderlyingImageComplete()
|
||||
return
|
||||
}
|
||||
|
||||
if photoURL != nil {
|
||||
|
|
@ -87,7 +88,7 @@ public class SKPhoto: NSObject, SKPhotoProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
if let res = response, let image = UIImage(data: res) {
|
||||
if let res = response, image = UIImage(data: res) {
|
||||
if _self.shouldCachePhotoURLImage {
|
||||
if SKCache.sharedCache.imageCache is SKRequestResponseCacheable {
|
||||
SKCache.sharedCache.setImageData(response!, response: data!, request: task.originalRequest!)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ public class SKPhotoBrowser: UIViewController {
|
|||
private var closeButton: SKCloseButton!
|
||||
private var deleteButton: SKDeleteButton!
|
||||
private var toolbar: SKToolbar!
|
||||
|
||||
private var navigationBar: SKNavigationBar!
|
||||
|
||||
// actions
|
||||
private var activityViewController: UIActivityViewController!
|
||||
|
|
@ -25,7 +27,7 @@ public class SKPhotoBrowser: UIViewController {
|
|||
|
||||
// tool for controls
|
||||
private var applicationWindow: UIWindow!
|
||||
private var pagingScrollView: SKPagingScrollView!
|
||||
private lazy var pagingScrollView: SKPagingScrollView = SKPagingScrollView(frame: self.view.frame, browser: self)
|
||||
var backgroundView: UIView!
|
||||
|
||||
var initialPageIndex: Int = 0
|
||||
|
|
@ -42,6 +44,10 @@ public class SKPhotoBrowser: UIViewController {
|
|||
|
||||
// timer
|
||||
private var controlVisibilityTimer: NSTimer!
|
||||
|
||||
// blocks
|
||||
public var willDismissPage: (() -> Void)?
|
||||
public var didPresentPage: (() -> Void)?
|
||||
|
||||
// delegate
|
||||
private let animator = SKAnimator()
|
||||
|
|
@ -52,6 +58,10 @@ public class SKPhotoBrowser: UIViewController {
|
|||
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)
|
||||
|
|
@ -85,7 +95,6 @@ public class SKPhotoBrowser: UIViewController {
|
|||
}
|
||||
|
||||
deinit {
|
||||
pagingScrollView = nil
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
|
|
@ -109,11 +118,12 @@ public class SKPhotoBrowser: UIViewController {
|
|||
configureAppearance()
|
||||
configureCloseButton()
|
||||
configureDeleteButton()
|
||||
configureNavigationBar()
|
||||
configureToolbar()
|
||||
|
||||
animator.willPresent(self)
|
||||
didPresentPage?()
|
||||
}
|
||||
|
||||
|
||||
override public func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(true)
|
||||
|
|
@ -132,6 +142,7 @@ public class SKPhotoBrowser: UIViewController {
|
|||
|
||||
closeButton.updateFrame()
|
||||
deleteButton.updateFrame()
|
||||
navigationBar.updateFrame(view.bounds.size)
|
||||
pagingScrollView.updateFrame(view.bounds, currentPageIndex: currentPageIndex)
|
||||
|
||||
toolbar.frame = frameForToolbarAtOrientation()
|
||||
|
|
@ -154,7 +165,7 @@ public class SKPhotoBrowser: UIViewController {
|
|||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), let photo = page.photo else {
|
||||
guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), photo = page.photo else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -181,6 +192,7 @@ public class SKPhotoBrowser: UIViewController {
|
|||
isPerformingLayout = true
|
||||
|
||||
toolbar.updateToolbar(currentPageIndex)
|
||||
navigationBar.updateNavigationBar(currentPageIndex)
|
||||
|
||||
// reset local cache
|
||||
pagingScrollView.reload()
|
||||
|
|
@ -195,6 +207,7 @@ public class SKPhotoBrowser: UIViewController {
|
|||
}
|
||||
|
||||
public func prepareForClosePhotoBrowser() {
|
||||
UIApplication.sharedApplication().setStatusBarHidden(statusbarHidden, withAnimation: .None)
|
||||
cancelControlHiding()
|
||||
applicationWindow.removeGestureRecognizer(panGesture)
|
||||
NSObject.cancelPreviousPerformRequestsWithTarget(self)
|
||||
|
|
@ -216,24 +229,33 @@ public class SKPhotoBrowser: UIViewController {
|
|||
public func determineAndClose() {
|
||||
delegate?.willDismissAtPageIndex?(currentPageIndex)
|
||||
animator.willDismiss(self)
|
||||
willDismissPage?()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public Function For Customizing Buttons
|
||||
|
||||
public extension SKPhotoBrowser {
|
||||
func updateCloseButton(image: UIImage) {
|
||||
func updateCloseButton(image: UIImage, size: CGSize? = nil) {
|
||||
if closeButton == nil {
|
||||
configureCloseButton()
|
||||
}
|
||||
closeButton.setImage(image, forState: .Normal)
|
||||
}
|
||||
|
||||
func updateDeleteButton(image: UIImage) {
|
||||
if let size = size {
|
||||
closeButton.setFrameSize(size)
|
||||
}
|
||||
}
|
||||
|
||||
func updateDeleteButton(image: UIImage, size: CGSize? = nil) {
|
||||
if deleteButton == nil {
|
||||
configureDeleteButton()
|
||||
}
|
||||
deleteButton.setImage(image, forState: .Normal)
|
||||
|
||||
if let size = size {
|
||||
deleteButton.setFrameSize(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +286,7 @@ public extension SKPhotoBrowser {
|
|||
}
|
||||
isEndAnimationByToolBar = false
|
||||
toolbar.updateToolbar(currentPageIndex)
|
||||
navigationBar.updateNavigationBar(currentPageIndex)
|
||||
|
||||
let pageFrame = frameForPageAtIndex(index)
|
||||
pagingScrollView.animate(pageFrame)
|
||||
|
|
@ -312,6 +335,36 @@ public extension SKPhotoBrowser {
|
|||
func areControlsHidden() -> Bool {
|
||||
return toolbar.alpha == 0.0
|
||||
}
|
||||
|
||||
func popupShare(includeCaption includeCaption: Bool = true) {
|
||||
let photo = photos[currentPageIndex]
|
||||
guard let underlyingImage = photo.underlyingImage else {
|
||||
return
|
||||
}
|
||||
|
||||
var activityItems: [AnyObject] = [underlyingImage]
|
||||
if photo.caption != nil && includeCaption {
|
||||
if let shareExtraCaption = SKPhotoBrowserOptions.shareExtraCaption {
|
||||
activityItems.append(photo.caption + shareExtraCaption)
|
||||
} else {
|
||||
activityItems.append(photo.caption)
|
||||
}
|
||||
}
|
||||
activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
activityViewController.completionWithItemsHandler = {
|
||||
(activity, success, items, error) in
|
||||
self.hideControlsAfterDelay()
|
||||
self.activityViewController = nil
|
||||
}
|
||||
if UI_USER_INTERFACE_IDIOM() == .Phone {
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
} else {
|
||||
activityViewController.modalPresentationStyle = .Popover
|
||||
let popover: UIPopoverPresentationController! = activityViewController.popoverPresentationController
|
||||
popover.barButtonItem = toolbar.toolActionButton
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -338,7 +391,7 @@ internal extension SKPhotoBrowser {
|
|||
sender.layer.renderInContext(UIGraphicsGetCurrentContext()!)
|
||||
let result = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return result
|
||||
return result!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +456,7 @@ internal extension SKPhotoBrowser {
|
|||
? zoomingScrollView.center.y - viewHalfHeight
|
||||
: -(zoomingScrollView.center.y - viewHalfHeight)) / viewHalfHeight
|
||||
|
||||
view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(max(0.7, offset))
|
||||
view.alpha = max(0.7, offset)
|
||||
|
||||
// gesture end
|
||||
if sender.state == .Ended {
|
||||
|
|
@ -427,7 +480,8 @@ internal extension SKPhotoBrowser {
|
|||
UIView.beginAnimations(nil, context: nil)
|
||||
UIView.setAnimationDuration(animationDuration)
|
||||
UIView.setAnimationCurve(UIViewAnimationCurve.EaseIn)
|
||||
view.backgroundColor = UIColor.blackColor()
|
||||
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
view.alpha = 1
|
||||
zoomingScrollView.center = CGPoint(x: finalX, y: finalY)
|
||||
UIView.commitAnimations()
|
||||
}
|
||||
|
|
@ -444,7 +498,7 @@ internal extension SKPhotoBrowser {
|
|||
determineAndClose()
|
||||
}
|
||||
|
||||
func actionButtonPressed() {
|
||||
func actionButtonPressed(ignoreAndShare ignoreAndShare: Bool) {
|
||||
delegate?.willShowActionSheet?(currentPageIndex)
|
||||
|
||||
guard numberOfPhotos > 0 else {
|
||||
|
|
@ -474,34 +528,9 @@ internal extension SKPhotoBrowser {
|
|||
presentViewController(actionSheetController, animated: true, completion: { () -> Void in
|
||||
})
|
||||
}
|
||||
} else {
|
||||
let photo = photos[currentPageIndex]
|
||||
guard let underlyingImage = photo.underlyingImage else {
|
||||
return
|
||||
}
|
||||
|
||||
var activityItems: [AnyObject] = [underlyingImage]
|
||||
if photo.caption != nil {
|
||||
if let shareExtraCaption = SKPhotoBrowserOptions.shareExtraCaption {
|
||||
activityItems.append(photo.caption + shareExtraCaption)
|
||||
} else {
|
||||
activityItems.append(photo.caption)
|
||||
}
|
||||
}
|
||||
activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
activityViewController.completionWithItemsHandler = {
|
||||
(activity, success, items, error) in
|
||||
self.hideControlsAfterDelay()
|
||||
self.activityViewController = nil
|
||||
}
|
||||
if UI_USER_INTERFACE_IDIOM() == .Phone {
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
} else {
|
||||
activityViewController.modalPresentationStyle = .Popover
|
||||
let popover: UIPopoverPresentationController! = activityViewController.popoverPresentationController
|
||||
popover.barButtonItem = toolbar.toolActionButton
|
||||
presentViewController(activityViewController, animated: true, completion: nil)
|
||||
}
|
||||
} else {
|
||||
popupShare()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -509,16 +538,15 @@ internal extension SKPhotoBrowser {
|
|||
// MARK: - Private Function
|
||||
private extension SKPhotoBrowser {
|
||||
func configureAppearance() {
|
||||
view.backgroundColor = .blackColor()
|
||||
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
view.clipsToBounds = true
|
||||
view.opaque = false
|
||||
|
||||
backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: SKMesurement.screenWidth, height: SKMesurement.screenHeight))
|
||||
backgroundView.backgroundColor = .blackColor()
|
||||
backgroundView.backgroundColor = SKPhotoBrowserOptions.backgroundColor
|
||||
backgroundView.alpha = 0.0
|
||||
applicationWindow.addSubview(backgroundView)
|
||||
|
||||
pagingScrollView = SKPagingScrollView(frame: view.frame, browser: self)
|
||||
pagingScrollView.delegate = self
|
||||
view.addSubview(pagingScrollView)
|
||||
|
||||
|
|
@ -543,6 +571,13 @@ private extension SKPhotoBrowser {
|
|||
deleteButton.hidden = !SKPhotoBrowserOptions.displayDeleteButton
|
||||
view.addSubview(deleteButton)
|
||||
}
|
||||
|
||||
func configureNavigationBar() {
|
||||
navigationBar = SKNavigationBar(browser: self)
|
||||
navigationBar.updateFrame(view.bounds.size)
|
||||
navigationBar.hidden = !SKPhotoBrowserOptions.displayNavigationBar
|
||||
view.addSubview(navigationBar)
|
||||
}
|
||||
|
||||
func configureToolbar() {
|
||||
toolbar = SKToolbar(frame: frameForToolbarAtOrientation(), browser: self)
|
||||
|
|
@ -568,6 +603,10 @@ private extension SKPhotoBrowser {
|
|||
self.deleteButton.alpha = alpha
|
||||
self.deleteButton.frame = hidden ? self.deleteButton.hideFrame : self.deleteButton.showFrame
|
||||
}
|
||||
if SKPhotoBrowserOptions.displayNavigationBar {
|
||||
self.navigationBar.alpha = alpha
|
||||
self.navigationBar.frame = hidden ? self.navigationBar.hideFrame : self.navigationBar.showFrame
|
||||
}
|
||||
captionViews.forEach { $0.alpha = alpha }
|
||||
},
|
||||
completion: nil)
|
||||
|
|
@ -591,6 +630,7 @@ private extension SKPhotoBrowser {
|
|||
gotoPreviousPage()
|
||||
}
|
||||
toolbar.updateToolbar(currentPageIndex)
|
||||
navigationBar.updateNavigationBar(currentPageIndex)
|
||||
|
||||
} else if photos.count == 1 {
|
||||
dismissPhotoBrowser(animated: false)
|
||||
|
|
@ -615,11 +655,12 @@ extension SKPhotoBrowser: UIScrollViewDelegate {
|
|||
// Calculate current page
|
||||
let previousCurrentPage = currentPageIndex
|
||||
let visibleBounds = pagingScrollView.bounds
|
||||
currentPageIndex = min(max(Int(floor(CGRectGetMidX(visibleBounds) / CGRectGetWidth(visibleBounds))), 0), numberOfPhotos - 1)
|
||||
currentPageIndex = min(max(Int(floor(visibleBounds.midX / visibleBounds.width)), 0), numberOfPhotos - 1)
|
||||
|
||||
if currentPageIndex != previousCurrentPage {
|
||||
delegate?.didShowPhotoAtIndex?(currentPageIndex)
|
||||
toolbar.updateToolbar(currentPageIndex)
|
||||
navigationBar.updateNavigationBar(currentPageIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,5 +71,6 @@ import Foundation
|
|||
- Returns: the view to animate to
|
||||
*/
|
||||
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,10 +20,27 @@ public struct SKPhotoBrowserOptions {
|
|||
public static var displayBackAndForwardButton: Bool = true
|
||||
public static var disableVerticalSwipe: Bool = false
|
||||
|
||||
public static var displayCloseButton = true
|
||||
public static var displayDeleteButton = false
|
||||
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 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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,32 +109,33 @@ private extension SKToolbar {
|
|||
toolCounterLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 95, height: 40))
|
||||
toolCounterLabel.textAlignment = .Center
|
||||
toolCounterLabel.backgroundColor = .clearColor()
|
||||
toolCounterLabel.font = UIFont(name: "Helvetica", size: 16.0)
|
||||
toolCounterLabel.textColor = .whiteColor()
|
||||
toolCounterLabel.shadowColor = .darkTextColor()
|
||||
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 = .whiteColor()
|
||||
toolActionButton.tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SKToolbarButton: UIButton {
|
||||
let insets: UIEdgeInsets = UIEdgeInsetsMake(13.25, 17.25, 13.25, 17.25)
|
||||
let insets: UIEdgeInsets = UIEdgeInsets(top: 13.25, left: 17.25, bottom: 13.25, right: 17.25)
|
||||
|
||||
func setup(imageName: String) {
|
||||
backgroundColor = .clearColor()
|
||||
tintColor = SKPhotoBrowserOptions.textAndIconColor
|
||||
imageEdgeInsets = insets
|
||||
translatesAutoresizingMaskIntoConstraints = true
|
||||
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
|
||||
contentMode = .Center
|
||||
|
||||
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil) ?? UIImage()
|
||||
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage()
|
||||
setImage(image, forState: .Normal)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectingViewDelegate, SKDetectingImageViewDelegate {
|
||||
|
||||
public class SKZoomingScrollView: UIScrollView {
|
||||
var captionView: SKCaptionView!
|
||||
var photo: SKPhotoProtocol! {
|
||||
didSet {
|
||||
|
|
@ -49,7 +48,7 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
// tap
|
||||
tapView = SKDetectingView(frame: bounds)
|
||||
tapView.delegate = self
|
||||
tapView.backgroundColor = UIColor.clearColor()
|
||||
tapView.backgroundColor = .clearColor()
|
||||
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
|
||||
addSubview(tapView)
|
||||
|
||||
|
|
@ -104,7 +103,6 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
}
|
||||
|
||||
public func setMaxMinZoomScalesForCurrentBounds() {
|
||||
|
||||
maximumZoomScale = 1
|
||||
minimumZoomScale = 1
|
||||
zoomScale = 1
|
||||
|
|
@ -119,28 +117,12 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
let xScale = boundsSize.width / imageSize.width
|
||||
let yScale = boundsSize.height / imageSize.height
|
||||
let minScale: CGFloat = min(xScale, yScale)
|
||||
var maxScale: CGFloat!
|
||||
var maxScale: CGFloat = 1.0
|
||||
|
||||
|
||||
let scale = UIScreen.mainScreen().scale
|
||||
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
|
||||
|
||||
// it is 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.sharedApplication().statusBarOrientation.isPortrait {
|
||||
maxScale = deviceScreenHeight / photoImageView.frame.width
|
||||
} else {
|
||||
maxScale = deviceScreenWidth / photoImageView.frame.width
|
||||
}
|
||||
} else if photoImageView.frame.width > deviceScreenWidth {
|
||||
maxScale = 1.0
|
||||
} else {
|
||||
// here if photoImageView.frame.width == deviceScreenWidth
|
||||
maxScale = 2.5
|
||||
} */
|
||||
|
||||
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.sharedApplication().statusBarOrientation.isPortrait {
|
||||
|
|
@ -154,7 +136,7 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
// here if photoImageView.frame.width == deviceScreenWidth
|
||||
maxScale = 2.5
|
||||
}
|
||||
|
||||
|
||||
maximumZoomScale = maxScale
|
||||
minimumZoomScale = minScale
|
||||
zoomScale = minScale
|
||||
|
|
@ -200,10 +182,25 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
}
|
||||
|
||||
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
|
||||
|
|
@ -239,23 +236,18 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
newZoom = maximumZoomScale
|
||||
}
|
||||
*/
|
||||
zoomToRect(zoomRectForScrollViewWith(maximumZoomScale, touchPoint: touchPoint), animated: true)
|
||||
let zoomRect = zoomRectForScrollViewWith(maximumZoomScale, touchPoint: touchPoint)
|
||||
zoomToRect(zoomRect, animated: true)
|
||||
}
|
||||
|
||||
// delay control
|
||||
photoBrowser?.hideControlsAfterDelay()
|
||||
}
|
||||
|
||||
public func zoomRectForScrollViewWith(scale: CGFloat, touchPoint: CGPoint) -> CGRect {
|
||||
let w = frame.size.width / scale
|
||||
let h = frame.size.height / scale
|
||||
let x = touchPoint.x - (w / 2.0)
|
||||
let y = touchPoint.y - (h / 2.0)
|
||||
|
||||
return CGRect(x: x, y: y, width: w, height: h)
|
||||
}
|
||||
|
||||
// MARK: - UIScrollViewDelegate
|
||||
}
|
||||
|
||||
// MARK: - UIScrollViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: UIScrollViewDelegate {
|
||||
public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
|
||||
return photoImageView
|
||||
}
|
||||
|
|
@ -268,9 +260,11 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SKDetectingViewDelegate
|
||||
}
|
||||
|
||||
// MARK: - SKDetectingImageViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: SKDetectingViewDelegate {
|
||||
func handleSingleTap(view: UIView, touch: UITouch) {
|
||||
guard let browser = photoBrowser else {
|
||||
return
|
||||
|
|
@ -292,8 +286,30 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
handleDoubleTap(needPoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SKDetectingImageViewDelegate
|
||||
|
||||
extension SKZoomingScrollView: SKDetectingImageViewDelegate {
|
||||
func handleImageViewSingleTap(touchPoint: CGPoint) {
|
||||
guard let browser = photoBrowser else {
|
||||
return
|
||||
}
|
||||
if SKPhotoBrowserOptions.enableSingleTapDismiss {
|
||||
browser.determineAndClose()
|
||||
} else {
|
||||
browser.toggleControls()
|
||||
}
|
||||
}
|
||||
|
||||
private func getViewFramePercent(view: UIView, touch: UITouch) -> CGPoint {
|
||||
func handleImageViewDoubleTap(touchPoint: CGPoint) {
|
||||
handleDoubleTap(touchPoint)
|
||||
}
|
||||
}
|
||||
|
||||
private extension SKZoomingScrollView {
|
||||
func getViewFramePercent(view: UIView, touch: UITouch) -> CGPoint {
|
||||
let oneWidthViewPercent = view.bounds.width / 100
|
||||
let viewTouchPoint = touch.locationInView(view)
|
||||
let viewWidthTouch = viewTouchPoint.x
|
||||
|
|
@ -314,19 +330,12 @@ public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectin
|
|||
return allPoint
|
||||
}
|
||||
|
||||
// MARK: - SKDetectingImageViewDelegate
|
||||
func handleImageViewSingleTap(touchPoint: CGPoint) {
|
||||
guard let browser = photoBrowser else {
|
||||
return
|
||||
}
|
||||
if SKPhotoBrowserOptions.enableSingleTapDismiss {
|
||||
browser.determineAndClose()
|
||||
} else {
|
||||
browser.toggleControls()
|
||||
}
|
||||
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.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)
|
||||
}
|
||||
|
||||
func handleImageViewDoubleTap(touchPoint: CGPoint) {
|
||||
handleDoubleTap(touchPoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,41 +14,9 @@ extension UIImage {
|
|||
guard self.imageOrientation != .Up else {
|
||||
return self
|
||||
}
|
||||
|
||||
// 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 = CGAffineTransformIdentity
|
||||
|
||||
switch self.imageOrientation {
|
||||
case .Down, .DownMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
|
||||
transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
|
||||
|
||||
case .Left, .LeftMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformRotate(transform, 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 = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
case .LeftMirrored, .RightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.height, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
let transform = calculateAffineTransform()
|
||||
|
||||
// Now we draw the underlying CGImage into a new context, applying the transform
|
||||
// calculated above.
|
||||
let ctx = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height),
|
||||
|
|
@ -72,5 +40,43 @@ extension UIImage {
|
|||
return self
|
||||
}
|
||||
}
|
||||
|
||||
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 = CGAffineTransformIdentity
|
||||
|
||||
switch self.imageOrientation {
|
||||
case .Down, .DownMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
|
||||
transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
|
||||
|
||||
case .Left, .LeftMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformRotate(transform, 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 = CGAffineTransformTranslate(transform, self.size.width, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
case .LeftMirrored, .RightMirrored:
|
||||
transform = CGAffineTransformTranslate(transform, self.size.height, 0)
|
||||
transform = CGAffineTransformScale(transform, -1, 1)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return transform
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -19,7 +19,8 @@ class FromWebViewController: UIViewController, SKPhotoBrowserDelegate {
|
|||
|
||||
SKCache.sharedCache.imageCache = CustomImageCache()
|
||||
imageView.sd_setImageWithURL(NSURL(string: "https://placehold.jp/1500x1500.png")) {
|
||||
SKCache.sharedCache.setImage($0.0, forKey: $0.3.absoluteString)
|
||||
guard let url = $0.3.absoluteString else { return }
|
||||
SKCache.sharedCache.setImage($0.0, forKey: url)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,4 +81,4 @@ class CustomImageCache: SKImageCacheable {
|
|||
|
||||
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>
|
||||
|
|
@ -46,10 +48,10 @@
|
|||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
Loading…
Reference in New Issue