Compare commits

..

No commits in common. "master" and "2.1.0" have entirely different histories.

21 changed files with 1429 additions and 985 deletions

View File

@ -1,51 +1,7 @@
# Change Log # Change Log
## 3.1.2 ## 2.1.x
Released on 2016-8
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
- Add changelog - Add changelog
@ -62,7 +18,7 @@ Released on 8-2016
- Some public property to internal for improving - Some public property to internal for improving
## 2.0.x ## 2.0.x
Released on 8-2016 Released on 2016-8
#### Added #### Added
- Migrate UIImage cache category to new SKCache - Migrate UIImage cache category to new SKCache
@ -76,7 +32,7 @@ Released on 8-2016
--- ---
## 1.9.x ## 1.9.x
Released on 6-2016 Released on 2016-6
#### Added #### Added
- Delegate to notify when the user scroll to an index - Delegate to notify when the user scroll to an index
@ -89,7 +45,7 @@ Released on 6-2016
--- ---
## 1.8.x ## 1.8.x
Released on 4-2016 Released on 2016-4
#### Added #### Added
- Using SKPhotoProtocol to enable usage from SKLocalPhoto - Using SKPhotoProtocol to enable usage from SKLocalPhoto
@ -104,7 +60,7 @@ Released on 4-2016
--- ---
## 1.7.x ## 1.7.x
Released on 3-2016 Released on 2016-3
#### Added #### Added
- Enable ability to override statusBar style - Enable ability to override statusBar style
@ -139,7 +95,7 @@ Released on 2016-3
--- ---
## 1.4.x ## 1.4.x
Released on 2-2016 Released on 2016-2
#### Added #### Added
- Delegate add for actionbutton. - Delegate add for actionbutton.
@ -151,7 +107,7 @@ Released on 2-2016
--- ---
## 1.3.x ## 1.3.x
Released on 1-2016 Released on 2016-1
#### Added #### Added
- Added action functionality similar to IDMPhotoBrowser. - Added action functionality similar to IDMPhotoBrowser.
@ -164,7 +120,7 @@ Released on 1-2016
--- ---
## 1.2.x ## 1.2.x
Released on 10-2015 Released on 2015-10
#### Added #### Added
- SKPhotoProtocol is implemented. - SKPhotoProtocol is implemented.
@ -175,12 +131,30 @@ Released on 10-2015
--- ---
## 1.1.x ## 1.1.x
Released on 10-2015 Released on 2015-10-09.
#### Fixed #### Fixed
- some property make private. - some property make private.
- layout bug fixed when zoom. - layout bug fixed when zoom.
## 1.0.0 ## 1.0.0
Released on 10-2015 Released on 2015-10-09.
#### 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.

View File

@ -1,15 +1,11 @@
SKPhotoBrowser SKPhotoBrowser
======================== ========================
![Language](https://img.shields.io/badge/language-Swift%202.3-orange.svg)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SKPhotoBrowser.svg?style=flat)](http://cocoadocs.org/docsets/SKPhotoBrowser) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SKPhotoBrowser.svg?style=flat)](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). 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 ## features
- Display one or more images by providing either `UIImage` objects, or string of URL array. - 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 - Photos can be zoomed and panned, and optional captions can be displayed
@ -107,39 +103,14 @@ func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath i
You can customize Toolbar via SKPhotoBrowserOptions. You can customize Toolbar via SKPhotoBrowserOptions.
```swift ```swift
SKPhotoBrowserOptions.displayToolbar = false // all tool bar will be hidden SKPhotoBrowserOptions.displayToolbar = false // all tool bar will be hidden
SKPhotoBrowserOptions.displayCounterLabel = false // counter label will be hidden SKPhotoBrowserOptions.displayCounterLabel = false // counter label will be hidden
SKPhotoBrowserOptions.displayBackAndForwardButton = false // back / forward button will be hidden SKPhotoBrowserOptions.displayBackAndForwardButton = false // back / forward button will be hidden
SKPhotoBrowserOptions.displayAction = false // action button will be hidden SKPhotoBrowserOptions.displayAction = false // action button will be hidden
SKPhotoBrowserOptions.displayDeleteButton = true // delete button will be shown 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) 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 #### Custom Cache From Web URL
You can use SKCacheable protocol if others are adaptable. (SKImageCacheable or SKRequestResponseCacheable) You can use SKCacheable protocol if others are adaptable. (SKImageCacheable or SKRequestResponseCacheable)
@ -156,8 +127,8 @@ SKCache.sharedCache.imageCache = CustomImageCache()
#### CustomButton Image #### CustomButton Image
Close, Delete buttons are able to change image and frame. Close, Delete buttons are able to change image and frame.
``` swift ``` swift
browser.updateCloseButton(UIImage()) browser.browser.updateCloseButton(UIImage())
browser.updateUpdateButton(UIImage()) browser.browser.updateUpdateButton(UIImage())
``` ```
#### Delete Photo #### Delete Photo
@ -175,7 +146,8 @@ images.append(photo)
#### SwipeGesture #### SwipeGesture
vertical swipe can enable/disable: vertical swipe can enable/disable:
``` swift ``` swift
SKPhotoBrowserOptions.disableVerticalSwipe = true let browser = SKPhotoBrowser(originImage: originImage, photos: images, animatedFromView: cell)
browser.disableVerticalSwipe = true
``` ```
#### Delegate #### Delegate
@ -208,12 +180,10 @@ func didDismissAtPageIndex(index: Int) {
``` ```
#### Options #### Minor Option
You can access via `SKPhotoBrowserOptions`, which can use for browser control.
- single tap handling, dismiss/noaction
- blackArea handling which is appearing outside of photo - blackArea handling which is appearing outside of photo
- single tap handling, dismiss/noaction
- bounce animation when appearing/dismissing - bounce animation when appearing/dismissing
- text color, font, or more
``` swift ``` swift
SKPhotoBrowserOptions.enableZoomBlackArea = true // default true SKPhotoBrowserOptions.enableZoomBlackArea = true // default true
SKPhotoBrowserOptions.enableSingleTapDismiss = true // default false SKPhotoBrowserOptions.enableSingleTapDismiss = true // default false

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "SKPhotoBrowser" s.name = "SKPhotoBrowser"
s.version = "3.1.2" s.version = "2.1.0"
s.summary = "Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift2.0." s.summary = "Simple PhotoBrowser/Viewer inspired by facebook, twitter photo browsers written by swift2.0."
s.homepage = "https://github.com/suzuki-0000/SKPhotoBrowser" s.homepage = "https://github.com/suzuki-0000/SKPhotoBrowser"
s.license = { :type => "MIT", :file => "LICENSE" } s.license = { :type => "MIT", :file => "LICENSE" }

View File

@ -7,7 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* 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 */; }; 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 */; }; 210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 210E53EE1C986D57008DD5E3 /* UIImage+Rotation.swift */; };
26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C97AD41D0EB6870039F6CB /* SKCache.swift */; }; 26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C97AD41D0EB6870039F6CB /* SKCache.swift */; };
@ -45,7 +44,6 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference 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>"; }; 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>"; }; 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>"; }; 26C97AD41D0EB6870039F6CB /* SKCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SKCache.swift; sourceTree = "<group>"; };
@ -138,7 +136,6 @@
8909B5411BC791510060A053 /* SKPhotoBrowser.swift */, 8909B5411BC791510060A053 /* SKPhotoBrowser.swift */,
89C24A811D657AD1005F09A9 /* SKPhotoBrowserOptions.swift */, 89C24A811D657AD1005F09A9 /* SKPhotoBrowserOptions.swift */,
890A6F1F1D5D9E53003B01F0 /* SKToolbar.swift */, 890A6F1F1D5D9E53003B01F0 /* SKToolbar.swift */,
0AE527511DABB87500619FAD /* SKNavigationBar.swift */,
8909B5331BC791280060A053 /* SKPhotoBrowser.h */, 8909B5331BC791280060A053 /* SKPhotoBrowser.h */,
8917B1AF1D5A13DE000CE1C4 /* SKPhotoBrowserDelegate.swift */, 8917B1AF1D5A13DE000CE1C4 /* SKPhotoBrowserDelegate.swift */,
89D0BA481D59966B002A811B /* SKMesurement.swift */, 89D0BA481D59966B002A811B /* SKMesurement.swift */,
@ -227,7 +224,6 @@
}; };
A64B89321CB04222000071B9 = { A64B89321CB04222000071B9 = {
CreatedOnToolsVersion = 7.3; CreatedOnToolsVersion = 7.3;
LastSwiftMigration = 0800;
}; };
}; };
}; };
@ -303,7 +299,6 @@
8917B1B41D5A14B0000CE1C4 /* SKButtons.swift in Sources */, 8917B1B41D5A14B0000CE1C4 /* SKButtons.swift in Sources */,
89C24A821D657AD1005F09A9 /* SKPhotoBrowserOptions.swift in Sources */, 89C24A821D657AD1005F09A9 /* SKPhotoBrowserOptions.swift in Sources */,
26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */, 26C97AD51D0EB6870039F6CB /* SKCache.swift in Sources */,
0AE527521DABB87500619FAD /* SKNavigationBar.swift in Sources */,
210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */, 210E53EF1C986D57008DD5E3 /* UIImage+Rotation.swift in Sources */,
8909B5431BC791510060A053 /* SKCaptionView.swift in Sources */, 8909B5431BC791510060A053 /* SKCaptionView.swift in Sources */,
8909B5491BC791510060A053 /* SKPhotoBrowser.swift in Sources */, 8909B5491BC791510060A053 /* SKPhotoBrowser.swift in Sources */,
@ -468,7 +463,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests"; PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
}; };
name = Debug; name = Debug;
}; };
@ -481,7 +475,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests"; PRODUCT_BUNDLE_IDENTIFIER = "Alexsander-Khitev.SKPhotoBrowserTests";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
}; };
name = Release; name = Release;
}; };

View File

@ -157,8 +157,6 @@ private extension SKAnimator {
self.resizableImageView?.frame = self.finalImageViewFrame self.resizableImageView?.frame = self.finalImageViewFrame
}, },
completion: { (Bool) -> Void in completion: { (Bool) -> Void in
UIApplication.sharedApplication().setStatusBarHidden(!SKPhotoBrowserOptions.displayStatusbar, withAnimation: .Fade)
browser.view.hidden = false browser.view.hidden = false
browser.view.alpha = 1.0 browser.view.alpha = 1.0
browser.backgroundView.hidden = true browser.backgroundView.hidden = true

View File

@ -15,10 +15,8 @@ class SKButton: UIButton {
var showFrame: CGRect! var showFrame: CGRect!
var hideFrame: CGRect! var hideFrame: CGRect!
var insets: UIEdgeInsets { 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) ? UIEdgeInsetsMake(15.25, 15.25, 15.25, 15.25) : UIEdgeInsetsMake(12, 12, 12, 12)
} }
var size: CGSize = CGSize(width: 44, height: 44) var size: CGSize = CGSize(width: 44, height: 44)
var margin: CGFloat = 5 var margin: CGFloat = 5
@ -27,25 +25,17 @@ class SKButton: UIButton {
func setup(imageName: String) { func setup(imageName: String) {
backgroundColor = .clearColor() backgroundColor = .clearColor()
tintColor = SKPhotoBrowserOptions.textAndIconColor
imageEdgeInsets = insets imageEdgeInsets = insets
// clipsToBounds = true // clipsToBounds = true
translatesAutoresizingMaskIntoConstraints = true translatesAutoresizingMaskIntoConstraints = true
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin] autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)", let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage() inBundle: bundle, compatibleWithTraitCollection: nil) ?? UIImage()
setImage(image, forState: .Normal) 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 { class SKCloseButton: SKButton {
@ -74,17 +64,12 @@ class SKDeleteButton: SKButton {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setup(imageName) setup(imageName)
showFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: buttonTopOffset, width: size.width, height: size.height) showFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: buttonTopOffset,
hideFrame = CGRect(x: SKMesurement.screenWidth - size.width, y: -20, width: size.width, height: size.height) 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 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)
}
} }

View File

@ -61,13 +61,13 @@ private extension SKCaptionView {
photoLabel.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] photoLabel.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
photoLabel.opaque = false photoLabel.opaque = false
photoLabel.backgroundColor = .clearColor() photoLabel.backgroundColor = .clearColor()
photoLabel.textColor = SKPhotoBrowserOptions.textAndIconColor photoLabel.textColor = .whiteColor()
photoLabel.textAlignment = .Center photoLabel.textAlignment = .Center
photoLabel.lineBreakMode = .ByTruncatingTail photoLabel.lineBreakMode = .ByTruncatingTail
photoLabel.numberOfLines = 3 photoLabel.numberOfLines = 3
photoLabel.shadowColor = UIColor(white: 0.0, alpha: 0.5) photoLabel.shadowColor = UIColor(white: 0.0, alpha: 0.5)
photoLabel.shadowOffset = CGSize(width: 0.0, height: 1.0) photoLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
photoLabel.font = SKPhotoBrowserOptions.captionFont photoLabel.font = UIFont.systemFontOfSize(17.0)
photoLabel.text = photo?.caption photoLabel.text = photo?.caption
addSubview(photoLabel) addSubview(photoLabel)
} }

View File

@ -16,6 +16,6 @@ class SKIndicatorView: UIActivityIndicatorView {
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
center = CGPoint(x: frame.width / 2, y: frame.height / 2) center = CGPoint(x: frame.width / 2, y: frame.height / 2)
activityIndicatorViewStyle = SKPhotoBrowserOptions.backgroundColor.isEqual(UIColor.whiteColor()) ? .Gray : .WhiteLarge activityIndicatorViewStyle = .WhiteLarge
} }
} }

View File

@ -10,8 +10,6 @@ import Foundation
import UIKit import UIKit
struct SKMesurement { struct SKMesurement {
static let isPhone: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Phone
static let isPad: Bool = UIDevice.currentDevice().userInterfaceIdiom == .Pad
static var statusBarH: CGFloat { static var statusBarH: CGFloat {
return UIApplication.sharedApplication().statusBarFrame.height return UIApplication.sharedApplication().statusBarFrame.height
} }

View File

@ -1,55 +0,0 @@
//
// 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)
}
}

View File

@ -28,8 +28,8 @@ class SKPagingScrollView: UIScrollView {
super.init(frame: frame) super.init(frame: frame)
pagingEnabled = true pagingEnabled = true
showsHorizontalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator showsHorizontalScrollIndicator = true
showsVerticalScrollIndicator = SKPhotoBrowserOptions.displayHorizontalScrollIndicator showsVerticalScrollIndicator = true
} }
convenience init(frame: CGRect, browser: SKPhotoBrowser) { convenience init(frame: CGRect, browser: SKPhotoBrowser) {
@ -210,7 +210,7 @@ private extension SKPagingScrollView {
} }
func getFirstIndex() -> Int { func getFirstIndex() -> Int {
let firstIndex = Int(floor((bounds.minX + sideMargin * 2) / bounds.width)) let firstIndex = Int(floor((CGRectGetMinX(bounds) + sideMargin * 2) / CGRectGetWidth(bounds)))
if firstIndex < 0 { if firstIndex < 0 {
return 0 return 0
} }
@ -221,7 +221,7 @@ private extension SKPagingScrollView {
} }
func getLastIndex() -> Int { func getLastIndex() -> Int {
let lastIndex = Int(floor((bounds.maxX - sideMargin * 2 - 1) / bounds.width)) let lastIndex = Int(floor((CGRectGetMaxX(bounds) - sideMargin * 2 - 1) / CGRectGetWidth(bounds)))
if lastIndex < 0 { if lastIndex < 0 {
return 0 return 0
} }

View File

@ -69,9 +69,8 @@ public class SKPhoto: NSObject, SKPhotoProtocol {
public func loadUnderlyingImageAndNotify() { public func loadUnderlyingImageAndNotify() {
if underlyingImage != nil { if underlyingImage != nil && photoURL == nil {
loadUnderlyingImageComplete() loadUnderlyingImageComplete()
return
} }
if photoURL != nil { if photoURL != nil {
@ -88,7 +87,7 @@ public class SKPhoto: NSObject, SKPhotoProtocol {
} }
} }
if let res = response, image = UIImage(data: res) { if let res = response, let image = UIImage(data: res) {
if _self.shouldCachePhotoURLImage { if _self.shouldCachePhotoURLImage {
if SKCache.sharedCache.imageCache is SKRequestResponseCacheable { if SKCache.sharedCache.imageCache is SKRequestResponseCacheable {
SKCache.sharedCache.setImageData(response!, response: data!, request: task.originalRequest!) SKCache.sharedCache.setImageData(response!, response: data!, request: task.originalRequest!)

View File

@ -19,15 +19,13 @@ public class SKPhotoBrowser: UIViewController {
private var deleteButton: SKDeleteButton! private var deleteButton: SKDeleteButton!
private var toolbar: SKToolbar! private var toolbar: SKToolbar!
private var navigationBar: SKNavigationBar!
// actions // actions
private var activityViewController: UIActivityViewController! private var activityViewController: UIActivityViewController!
private var panGesture: UIPanGestureRecognizer! private var panGesture: UIPanGestureRecognizer!
// tool for controls // tool for controls
private var applicationWindow: UIWindow! private var applicationWindow: UIWindow!
private lazy var pagingScrollView: SKPagingScrollView = SKPagingScrollView(frame: self.view.frame, browser: self) private var pagingScrollView: SKPagingScrollView!
var backgroundView: UIView! var backgroundView: UIView!
var initialPageIndex: Int = 0 var initialPageIndex: Int = 0
@ -45,10 +43,6 @@ public class SKPhotoBrowser: UIViewController {
// timer // timer
private var controlVisibilityTimer: NSTimer! private var controlVisibilityTimer: NSTimer!
// blocks
public var willDismissPage: (() -> Void)?
public var didPresentPage: (() -> Void)?
// delegate // delegate
private let animator = SKAnimator() private let animator = SKAnimator()
public weak var delegate: SKPhotoBrowserDelegate? public weak var delegate: SKPhotoBrowserDelegate?
@ -58,10 +52,6 @@ public class SKPhotoBrowser: UIViewController {
var numberOfPhotos: Int { var numberOfPhotos: Int {
return photos.count return photos.count
} }
// statusbar initial state
private var statusbarHidden: Bool = UIApplication.sharedApplication().statusBarHidden
// MARK - Initializer // MARK - Initializer
required public init?(coder aDecoder: NSCoder) { required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) super.init(coder: aDecoder)
@ -95,6 +85,7 @@ public class SKPhotoBrowser: UIViewController {
} }
deinit { deinit {
pagingScrollView = nil
NSNotificationCenter.defaultCenter().removeObserver(self) NSNotificationCenter.defaultCenter().removeObserver(self)
} }
@ -118,13 +109,12 @@ public class SKPhotoBrowser: UIViewController {
configureAppearance() configureAppearance()
configureCloseButton() configureCloseButton()
configureDeleteButton() configureDeleteButton()
configureNavigationBar()
configureToolbar() configureToolbar()
animator.willPresent(self) animator.willPresent(self)
didPresentPage?()
} }
override public func viewWillAppear(animated: Bool) { override public func viewWillAppear(animated: Bool) {
super.viewWillAppear(true) super.viewWillAppear(true)
reloadData() reloadData()
@ -142,7 +132,6 @@ public class SKPhotoBrowser: UIViewController {
closeButton.updateFrame() closeButton.updateFrame()
deleteButton.updateFrame() deleteButton.updateFrame()
navigationBar.updateFrame(view.bounds.size)
pagingScrollView.updateFrame(view.bounds, currentPageIndex: currentPageIndex) pagingScrollView.updateFrame(view.bounds, currentPageIndex: currentPageIndex)
toolbar.frame = frameForToolbarAtOrientation() toolbar.frame = frameForToolbarAtOrientation()
@ -165,7 +154,7 @@ public class SKPhotoBrowser: UIViewController {
} }
dispatch_async(dispatch_get_main_queue(), { dispatch_async(dispatch_get_main_queue(), {
guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), photo = page.photo else { guard let page = self.pagingScrollView.pageDisplayingAtPhoto(photo), let photo = page.photo else {
return return
} }
@ -192,7 +181,6 @@ public class SKPhotoBrowser: UIViewController {
isPerformingLayout = true isPerformingLayout = true
toolbar.updateToolbar(currentPageIndex) toolbar.updateToolbar(currentPageIndex)
navigationBar.updateNavigationBar(currentPageIndex)
// reset local cache // reset local cache
pagingScrollView.reload() pagingScrollView.reload()
@ -207,7 +195,6 @@ public class SKPhotoBrowser: UIViewController {
} }
public func prepareForClosePhotoBrowser() { public func prepareForClosePhotoBrowser() {
UIApplication.sharedApplication().setStatusBarHidden(statusbarHidden, withAnimation: .None)
cancelControlHiding() cancelControlHiding()
applicationWindow.removeGestureRecognizer(panGesture) applicationWindow.removeGestureRecognizer(panGesture)
NSObject.cancelPreviousPerformRequestsWithTarget(self) NSObject.cancelPreviousPerformRequestsWithTarget(self)
@ -229,33 +216,24 @@ public class SKPhotoBrowser: UIViewController {
public func determineAndClose() { public func determineAndClose() {
delegate?.willDismissAtPageIndex?(currentPageIndex) delegate?.willDismissAtPageIndex?(currentPageIndex)
animator.willDismiss(self) animator.willDismiss(self)
willDismissPage?()
} }
} }
// MARK: - Public Function For Customizing Buttons // MARK: - Public Function For Customizing Buttons
public extension SKPhotoBrowser { public extension SKPhotoBrowser {
func updateCloseButton(image: UIImage, size: CGSize? = nil) { func updateCloseButton(image: UIImage) {
if closeButton == nil { if closeButton == nil {
configureCloseButton() configureCloseButton()
} }
closeButton.setImage(image, forState: .Normal) closeButton.setImage(image, forState: .Normal)
if let size = size {
closeButton.setFrameSize(size)
}
} }
func updateDeleteButton(image: UIImage, size: CGSize? = nil) { func updateDeleteButton(image: UIImage) {
if deleteButton == nil { if deleteButton == nil {
configureDeleteButton() configureDeleteButton()
} }
deleteButton.setImage(image, forState: .Normal) deleteButton.setImage(image, forState: .Normal)
if let size = size {
deleteButton.setFrameSize(size)
}
} }
} }
@ -286,7 +264,6 @@ public extension SKPhotoBrowser {
} }
isEndAnimationByToolBar = false isEndAnimationByToolBar = false
toolbar.updateToolbar(currentPageIndex) toolbar.updateToolbar(currentPageIndex)
navigationBar.updateNavigationBar(currentPageIndex)
let pageFrame = frameForPageAtIndex(index) let pageFrame = frameForPageAtIndex(index)
pagingScrollView.animate(pageFrame) pagingScrollView.animate(pageFrame)
@ -335,36 +312,6 @@ public extension SKPhotoBrowser {
func areControlsHidden() -> Bool { func areControlsHidden() -> Bool {
return toolbar.alpha == 0.0 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)
}
}
} }
@ -391,7 +338,7 @@ internal extension SKPhotoBrowser {
sender.layer.renderInContext(UIGraphicsGetCurrentContext()!) sender.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let result = UIGraphicsGetImageFromCurrentImageContext() let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext() UIGraphicsEndImageContext()
return result! return result
} }
} }
@ -456,7 +403,7 @@ internal extension SKPhotoBrowser {
? zoomingScrollView.center.y - viewHalfHeight ? zoomingScrollView.center.y - viewHalfHeight
: -(zoomingScrollView.center.y - viewHalfHeight)) / viewHalfHeight : -(zoomingScrollView.center.y - viewHalfHeight)) / viewHalfHeight
view.alpha = max(0.7, offset) view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(max(0.7, offset))
// gesture end // gesture end
if sender.state == .Ended { if sender.state == .Ended {
@ -480,8 +427,7 @@ internal extension SKPhotoBrowser {
UIView.beginAnimations(nil, context: nil) UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(animationDuration) UIView.setAnimationDuration(animationDuration)
UIView.setAnimationCurve(UIViewAnimationCurve.EaseIn) UIView.setAnimationCurve(UIViewAnimationCurve.EaseIn)
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor view.backgroundColor = UIColor.blackColor()
view.alpha = 1
zoomingScrollView.center = CGPoint(x: finalX, y: finalY) zoomingScrollView.center = CGPoint(x: finalX, y: finalY)
UIView.commitAnimations() UIView.commitAnimations()
} }
@ -498,7 +444,7 @@ internal extension SKPhotoBrowser {
determineAndClose() determineAndClose()
} }
func actionButtonPressed(ignoreAndShare ignoreAndShare: Bool) { func actionButtonPressed() {
delegate?.willShowActionSheet?(currentPageIndex) delegate?.willShowActionSheet?(currentPageIndex)
guard numberOfPhotos > 0 else { guard numberOfPhotos > 0 else {
@ -528,9 +474,34 @@ internal extension SKPhotoBrowser {
presentViewController(actionSheetController, animated: true, completion: { () -> Void in presentViewController(actionSheetController, animated: true, completion: { () -> Void in
}) })
} }
} else { } else {
popupShare() 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)
}
} }
} }
} }
@ -538,15 +509,16 @@ internal extension SKPhotoBrowser {
// MARK: - Private Function // MARK: - Private Function
private extension SKPhotoBrowser { private extension SKPhotoBrowser {
func configureAppearance() { func configureAppearance() {
view.backgroundColor = SKPhotoBrowserOptions.backgroundColor view.backgroundColor = .blackColor()
view.clipsToBounds = true view.clipsToBounds = true
view.opaque = false view.opaque = false
backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: SKMesurement.screenWidth, height: SKMesurement.screenHeight)) backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: SKMesurement.screenWidth, height: SKMesurement.screenHeight))
backgroundView.backgroundColor = SKPhotoBrowserOptions.backgroundColor backgroundView.backgroundColor = .blackColor()
backgroundView.alpha = 0.0 backgroundView.alpha = 0.0
applicationWindow.addSubview(backgroundView) applicationWindow.addSubview(backgroundView)
pagingScrollView = SKPagingScrollView(frame: view.frame, browser: self)
pagingScrollView.delegate = self pagingScrollView.delegate = self
view.addSubview(pagingScrollView) view.addSubview(pagingScrollView)
@ -572,13 +544,6 @@ private extension SKPhotoBrowser {
view.addSubview(deleteButton) view.addSubview(deleteButton)
} }
func configureNavigationBar() {
navigationBar = SKNavigationBar(browser: self)
navigationBar.updateFrame(view.bounds.size)
navigationBar.hidden = !SKPhotoBrowserOptions.displayNavigationBar
view.addSubview(navigationBar)
}
func configureToolbar() { func configureToolbar() {
toolbar = SKToolbar(frame: frameForToolbarAtOrientation(), browser: self) toolbar = SKToolbar(frame: frameForToolbarAtOrientation(), browser: self)
view.addSubview(toolbar) view.addSubview(toolbar)
@ -603,10 +568,6 @@ private extension SKPhotoBrowser {
self.deleteButton.alpha = alpha self.deleteButton.alpha = alpha
self.deleteButton.frame = hidden ? self.deleteButton.hideFrame : self.deleteButton.showFrame 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 } captionViews.forEach { $0.alpha = alpha }
}, },
completion: nil) completion: nil)
@ -630,7 +591,6 @@ private extension SKPhotoBrowser {
gotoPreviousPage() gotoPreviousPage()
} }
toolbar.updateToolbar(currentPageIndex) toolbar.updateToolbar(currentPageIndex)
navigationBar.updateNavigationBar(currentPageIndex)
} else if photos.count == 1 { } else if photos.count == 1 {
dismissPhotoBrowser(animated: false) dismissPhotoBrowser(animated: false)
@ -655,12 +615,11 @@ extension SKPhotoBrowser: UIScrollViewDelegate {
// Calculate current page // Calculate current page
let previousCurrentPage = currentPageIndex let previousCurrentPage = currentPageIndex
let visibleBounds = pagingScrollView.bounds let visibleBounds = pagingScrollView.bounds
currentPageIndex = min(max(Int(floor(visibleBounds.midX / visibleBounds.width)), 0), numberOfPhotos - 1) currentPageIndex = min(max(Int(floor(CGRectGetMidX(visibleBounds) / CGRectGetWidth(visibleBounds))), 0), numberOfPhotos - 1)
if currentPageIndex != previousCurrentPage { if currentPageIndex != previousCurrentPage {
delegate?.didShowPhotoAtIndex?(currentPageIndex) delegate?.didShowPhotoAtIndex?(currentPageIndex)
toolbar.updateToolbar(currentPageIndex) toolbar.updateToolbar(currentPageIndex)
navigationBar.updateNavigationBar(currentPageIndex)
} }
} }

View File

@ -71,6 +71,5 @@ import Foundation
- Returns: the view to animate to - Returns: the view to animate to
*/ */
optional func viewForPhoto(browser: SKPhotoBrowser, index: Int) -> UIView? optional func viewForPhoto(browser: SKPhotoBrowser, index: Int) -> UIView?
} }

View File

@ -6,11 +6,9 @@
// Copyright © 2016 suzuki_keishi. All rights reserved. // Copyright © 2016 suzuki_keishi. All rights reserved.
// //
import UIKit import Foundation
public struct SKPhotoBrowserOptions { public struct SKPhotoBrowserOptions {
public static var displayStatusbar: Bool = false
public static var displayAction: Bool = true public static var displayAction: Bool = true
public static var shareExtraCaption: String? = nil public static var shareExtraCaption: String? = nil
public static var actionButtonTitles: [String]? public static var actionButtonTitles: [String]?
@ -20,27 +18,10 @@ public struct SKPhotoBrowserOptions {
public static var displayBackAndForwardButton: Bool = true public static var displayBackAndForwardButton: Bool = true
public static var disableVerticalSwipe: Bool = false public static var disableVerticalSwipe: Bool = false
public static var displayCloseButton: Bool = true public static var displayCloseButton = true
public static var displayNavigationBar: Bool = true public static var displayDeleteButton = false
public static var displayDeleteButton: Bool = false
public static var displayHorizontalScrollIndicator: Bool = true public static var bounceAnimation = false
public static var displayVerticalScrollIndicator: Bool = true public static var enableZoomBlackArea = true
public static var enableSingleTapDismiss = false
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
} }

View File

@ -109,33 +109,32 @@ private extension SKToolbar {
toolCounterLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 95, height: 40)) toolCounterLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 95, height: 40))
toolCounterLabel.textAlignment = .Center toolCounterLabel.textAlignment = .Center
toolCounterLabel.backgroundColor = .clearColor() toolCounterLabel.backgroundColor = .clearColor()
toolCounterLabel.font = SKPhotoBrowserOptions.toolbarFont toolCounterLabel.font = UIFont(name: "Helvetica", size: 16.0)
toolCounterLabel.textColor = SKPhotoBrowserOptions.textAndIconColor toolCounterLabel.textColor = .whiteColor()
toolCounterLabel.shadowColor = SKPhotoBrowserOptions.toolbarTextShadowColor toolCounterLabel.shadowColor = .darkTextColor()
toolCounterLabel.shadowOffset = CGSize(width: 0.0, height: 1.0) toolCounterLabel.shadowOffset = CGSize(width: 0.0, height: 1.0)
toolCounterButton = UIBarButtonItem(customView: toolCounterLabel) toolCounterButton = UIBarButtonItem(customView: toolCounterLabel)
} }
func setupActionButton() { func setupActionButton() {
toolActionButton = UIBarButtonItem(barButtonSystemItem: .Action, target: browser, action: #selector(SKPhotoBrowser.actionButtonPressed)) toolActionButton = UIBarButtonItem(barButtonSystemItem: .Action, target: browser, action: #selector(SKPhotoBrowser.actionButtonPressed))
toolActionButton.tintColor = SKPhotoBrowserOptions.textAndIconColor toolActionButton.tintColor = .whiteColor()
} }
} }
class SKToolbarButton: UIButton { class SKToolbarButton: UIButton {
let insets: UIEdgeInsets = UIEdgeInsets(top: 13.25, left: 17.25, bottom: 13.25, right: 17.25) let insets: UIEdgeInsets = UIEdgeInsetsMake(13.25, 17.25, 13.25, 17.25)
func setup(imageName: String) { func setup(imageName: String) {
backgroundColor = .clearColor() backgroundColor = .clearColor()
tintColor = SKPhotoBrowserOptions.textAndIconColor
imageEdgeInsets = insets imageEdgeInsets = insets
translatesAutoresizingMaskIntoConstraints = true translatesAutoresizingMaskIntoConstraints = true
autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin] autoresizingMask = [.FlexibleBottomMargin, .FlexibleLeftMargin, .FlexibleRightMargin, .FlexibleTopMargin]
contentMode = .Center contentMode = .Center
let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)", let image = UIImage(named: "SKPhotoBrowser.bundle/images/\(imageName)",
inBundle: bundle, compatibleWithTraitCollection: nil)?.imageWithRenderingMode(.AlwaysTemplate) ?? UIImage() inBundle: bundle, compatibleWithTraitCollection: nil) ?? UIImage()
setImage(image, forState: .Normal) setImage(image, forState: .Normal)
} }
} }

View File

@ -8,7 +8,8 @@
import UIKit import UIKit
public class SKZoomingScrollView: UIScrollView { public class SKZoomingScrollView: UIScrollView, UIScrollViewDelegate, SKDetectingViewDelegate, SKDetectingImageViewDelegate {
var captionView: SKCaptionView! var captionView: SKCaptionView!
var photo: SKPhotoProtocol! { var photo: SKPhotoProtocol! {
didSet { didSet {
@ -48,7 +49,7 @@ public class SKZoomingScrollView: UIScrollView {
// tap // tap
tapView = SKDetectingView(frame: bounds) tapView = SKDetectingView(frame: bounds)
tapView.delegate = self tapView.delegate = self
tapView.backgroundColor = .clearColor() tapView.backgroundColor = UIColor.clearColor()
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth] tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
addSubview(tapView) addSubview(tapView)
@ -103,6 +104,7 @@ public class SKZoomingScrollView: UIScrollView {
} }
public func setMaxMinZoomScalesForCurrentBounds() { public func setMaxMinZoomScalesForCurrentBounds() {
maximumZoomScale = 1 maximumZoomScale = 1
minimumZoomScale = 1 minimumZoomScale = 1
zoomScale = 1 zoomScale = 1
@ -117,12 +119,28 @@ public class SKZoomingScrollView: UIScrollView {
let xScale = boundsSize.width / imageSize.width let xScale = boundsSize.width / imageSize.width
let yScale = boundsSize.height / imageSize.height let yScale = boundsSize.height / imageSize.height
let minScale: CGFloat = min(xScale, yScale) let minScale: CGFloat = min(xScale, yScale)
var maxScale: CGFloat = 1.0 var maxScale: CGFloat!
let scale = max(UIScreen.mainScreen().scale, 2.0)
let scale = UIScreen.mainScreen().scale
let deviceScreenWidth = UIScreen.mainScreen().bounds.width * scale // width in pixels. scale needs to remove if to use the old algorithm 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 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 { 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. // 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 { if UIApplication.sharedApplication().statusBarOrientation.isPortrait {
@ -183,24 +201,9 @@ public class SKZoomingScrollView: UIScrollView {
if let image = photo.underlyingImage { 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 // image
photoImageView.image = image photoImageView.image = image
photoImageView.contentMode = photo.contentMode photoImageView.contentMode = photo.contentMode
photoImageView.backgroundColor = SKPhotoBrowserOptions.backgroundColor
var photoImageViewFrame = CGRect.zero var photoImageViewFrame = CGRect.zero
photoImageViewFrame.origin = CGPoint.zero photoImageViewFrame.origin = CGPoint.zero
@ -236,18 +239,23 @@ public class SKZoomingScrollView: UIScrollView {
newZoom = maximumZoomScale newZoom = maximumZoomScale
} }
*/ */
let zoomRect = zoomRectForScrollViewWith(maximumZoomScale, touchPoint: touchPoint) zoomToRect(zoomRectForScrollViewWith(maximumZoomScale, touchPoint: touchPoint), animated: true)
zoomToRect(zoomRect, animated: true)
} }
// delay control // delay control
photoBrowser?.hideControlsAfterDelay() photoBrowser?.hideControlsAfterDelay()
} }
}
// MARK: - UIScrollViewDelegate 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)
extension SKZoomingScrollView: UIScrollViewDelegate { return CGRect(x: x, y: y, width: w, height: h)
}
// MARK: - UIScrollViewDelegate
public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? { public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return photoImageView return photoImageView
} }
@ -260,11 +268,9 @@ extension SKZoomingScrollView: UIScrollViewDelegate {
setNeedsLayout() setNeedsLayout()
layoutIfNeeded() layoutIfNeeded()
} }
}
// MARK: - SKDetectingImageViewDelegate
extension SKZoomingScrollView: SKDetectingViewDelegate { // MARK: - SKDetectingViewDelegate
func handleSingleTap(view: UIView, touch: UITouch) { func handleSingleTap(view: UIView, touch: UITouch) {
guard let browser = photoBrowser else { guard let browser = photoBrowser else {
return return
@ -286,30 +292,8 @@ extension SKZoomingScrollView: SKDetectingViewDelegate {
handleDoubleTap(needPoint) handleDoubleTap(needPoint)
} }
} }
}
private func getViewFramePercent(view: UIView, touch: UITouch) -> CGPoint {
// MARK: - SKDetectingImageViewDelegate
extension SKZoomingScrollView: SKDetectingImageViewDelegate {
func handleImageViewSingleTap(touchPoint: CGPoint) {
guard let browser = photoBrowser else {
return
}
if SKPhotoBrowserOptions.enableSingleTapDismiss {
browser.determineAndClose()
} else {
browser.toggleControls()
}
}
func handleImageViewDoubleTap(touchPoint: CGPoint) {
handleDoubleTap(touchPoint)
}
}
private extension SKZoomingScrollView {
func getViewFramePercent(view: UIView, touch: UITouch) -> CGPoint {
let oneWidthViewPercent = view.bounds.width / 100 let oneWidthViewPercent = view.bounds.width / 100
let viewTouchPoint = touch.locationInView(view) let viewTouchPoint = touch.locationInView(view)
let viewWidthTouch = viewTouchPoint.x let viewWidthTouch = viewTouchPoint.x
@ -330,12 +314,19 @@ private extension SKZoomingScrollView {
return allPoint return allPoint
} }
func zoomRectForScrollViewWith(scale: CGFloat, touchPoint: CGPoint) -> CGRect { // MARK: - SKDetectingImageViewDelegate
let w = frame.size.width / scale func handleImageViewSingleTap(touchPoint: CGPoint) {
let h = frame.size.height / scale guard let browser = photoBrowser else {
let x = touchPoint.x - (h / max(UIScreen.mainScreen().scale, 2.0)) return
let y = touchPoint.y - (w / max(UIScreen.mainScreen().scale, 2.0)) }
if SKPhotoBrowserOptions.enableSingleTapDismiss {
browser.determineAndClose()
} else {
browser.toggleControls()
}
}
return CGRect(x: x, y: y, width: w, height: h) func handleImageViewDoubleTap(touchPoint: CGPoint) {
handleDoubleTap(touchPoint)
} }
} }

View File

@ -15,33 +15,6 @@ extension UIImage {
return self return self
} }
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),
CGImageGetBitsPerComponent(self.CGImage!), 0,
CGImageGetColorSpace(self.CGImage!)!,
CGImageGetBitmapInfo(self.CGImage!).rawValue)
CGContextConcatCTM(ctx!, transform)
switch self.imageOrientation {
case .Left, .LeftMirrored, .Right, .RightMirrored:
CGContextDrawImage(ctx!, CGRect(x: 0, y: 0, width: size.height, height: size.width), self.CGImage!)
default:
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 = CGBitmapContextCreateImage(ctx!) {
return UIImage(CGImage: cgImage)
} else {
return self
}
}
private func calculateAffineTransform() -> CGAffineTransform {
// We need to calculate the proper transformation to make the image upright. // 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. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
var transform = CGAffineTransformIdentity var transform = CGAffineTransformIdentity
@ -76,7 +49,28 @@ extension UIImage {
break break
} }
return transform // 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),
CGImageGetBitsPerComponent(self.CGImage!), 0,
CGImageGetColorSpace(self.CGImage!)!,
CGImageGetBitmapInfo(self.CGImage!).rawValue)
CGContextConcatCTM(ctx!, transform)
switch self.imageOrientation {
case .Left, .LeftMirrored, .Right, .RightMirrored:
CGContextDrawImage(ctx!, CGRect(x: 0, y: 0, width: size.height, height: size.width), self.CGImage!)
default:
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 = CGBitmapContextCreateImage(ctx!) {
return UIImage(CGImage: cgImage)
} else {
return self
}
} }
} }

View File

@ -19,8 +19,7 @@ class FromWebViewController: UIViewController, SKPhotoBrowserDelegate {
SKCache.sharedCache.imageCache = CustomImageCache() SKCache.sharedCache.imageCache = CustomImageCache()
imageView.sd_setImageWithURL(NSURL(string: "https://placehold.jp/1500x1500.png")) { imageView.sd_setImageWithURL(NSURL(string: "https://placehold.jp/1500x1500.png")) {
guard let url = $0.3.absoluteString else { return } SKCache.sharedCache.setImage($0.0, forKey: $0.3.absoluteString)
SKCache.sharedCache.setImage($0.0, forKey: url)
} }
} }

View File

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>for example, this app accesses the users photo library</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@ -48,10 +46,10 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true/>
</dict> </dict>
</dict> </dict>
</plist> </plist>