Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb471b2295 | |||
| 0ae093ea75 | |||
| 7bec499be2 | |||
| 74f93c36d5 | |||
| 4deca2d95b | |||
| e15d420969 | |||
| e08f300ebe | |||
| 643469a4b4 | |||
| 2f8f77fb5c | |||
| 2f8eb0632e | |||
| f494d7f185 | |||
| 4f8b51b5bc | |||
| 79537b624f | |||
| 3271e28008 | |||
| 01fdcfd333 | |||
| c0c3d33058 | |||
| 9bae1297b2 | |||
| 13d845634a | |||
| 226b67b654 | |||
| d3f4abfee8 | |||
| 3edf6223f7 | |||
| be9990001f | |||
| 4f143e39c5 | |||
| 1790d05c1d | |||
| cfd8a8349c | |||
| fa277edea0 | |||
| a9f62a47b8 | |||
| 37440b4029 | |||
| 55c93633af | |||
| abc2774b46 | |||
| 67d6842583 | |||
| a7d73c406d | |||
| d6245ea06f | |||
| f531d87663 | |||
| 023d83b9f0 | |||
| 21258e6142 | |||
| f2c52e31d5 | |||
| 5c1681a437 | |||
| 8378f3771b | |||
| 41ee44cd0a | |||
| 884ee6c285 | |||
| b7562a7c54 | |||
| 8eaf56bfcd | |||
| 31e33122de | |||
| 209e2f812c |
@@ -0,0 +1 @@
|
||||
4.2
|
||||
@@ -1,6 +1,11 @@
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode9.2
|
||||
language: objective-c
|
||||
|
||||
xcode_project: PreviewTransitionDemo/PreviewTransitionDemo.xcodeproj
|
||||
xcode_scheme: PreviewTransition
|
||||
xcode_sdk: iphonesimulator
|
||||
xcode_sdk: iphonesimulator11.2
|
||||
|
||||
# whitelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// swift-tools-version:5.1
|
||||
//
|
||||
// Package.swift
|
||||
//
|
||||
// Copyright (c) Ramotion Inc. (https://www.ramotion.com/)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import PackageDescription
|
||||
|
||||
|
||||
let package = Package(
|
||||
name: "PreviewTransition",
|
||||
platforms: [
|
||||
.iOS(.v9)
|
||||
],
|
||||
products: [
|
||||
.library(name: "PreviewTransition",
|
||||
targets: ["PreviewTransition"]),
|
||||
],
|
||||
targets: [
|
||||
.target(name: "PreviewTransition",
|
||||
path: "PreviewTransition")
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'PreviewTransition'
|
||||
s.version = '2.0.0'
|
||||
s.version = '4.1.0'
|
||||
s.summary = 'Transition animation'
|
||||
s.license = 'MIT'
|
||||
s.homepage = 'https://github.com/Ramotion/preview-transition'
|
||||
|
||||
@@ -25,113 +25,96 @@ import UIKit
|
||||
|
||||
/// Base UIViewController for preview transition
|
||||
open class PTDetailViewController: UIViewController {
|
||||
|
||||
var bgImage: UIImage?
|
||||
var titleText: String?
|
||||
|
||||
fileprivate var backgroundImageView: UIImageView?
|
||||
|
||||
var bgImage: UIImage?
|
||||
var titleText: String?
|
||||
|
||||
fileprivate var backgroundImageView: UIImageView?
|
||||
}
|
||||
|
||||
// MARK: life cicle
|
||||
|
||||
extension PTDetailViewController {
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
backgroundImageView = createBackgroundImage(bgImage)
|
||||
view.backgroundColor = .black
|
||||
|
||||
if let titleText = self.titleText {
|
||||
title = titleText
|
||||
extension PTDetailViewController {
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
backgroundImageView = createBackgroundImage(bgImage)
|
||||
view.backgroundColor = .black
|
||||
|
||||
if let titleText = self.titleText {
|
||||
title = titleText
|
||||
}
|
||||
|
||||
// hack
|
||||
if let navigationController = self.navigationController {
|
||||
for case let label as UILabel in navigationController.view.subviews {
|
||||
label.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
_ = createNavBar(UIColor(red: 0, green: 0, blue: 0, alpha: 0.5))
|
||||
}
|
||||
|
||||
// hack
|
||||
if let navigationController = self.navigationController {
|
||||
for case let label as UILabel in navigationController.view.subviews {
|
||||
label.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
let _ = createNavBar(UIColor(red: 0, green: 0, blue: 0, alpha: 0.5))
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: public
|
||||
|
||||
extension PTDetailViewController {
|
||||
|
||||
/**
|
||||
Pops the top view controller from the navigation stack and updates the display with custom animation.
|
||||
*/
|
||||
public func popViewController() {
|
||||
|
||||
if let navigationController = self.navigationController {
|
||||
for case let label as UILabel in navigationController.view.subviews {
|
||||
label.isHidden = false
|
||||
}
|
||||
|
||||
/**
|
||||
Pops the top view controller from the navigation stack and updates the display with custom animation.
|
||||
*/
|
||||
public func popViewController() {
|
||||
|
||||
if let navigationController = self.navigationController {
|
||||
for case let label as UILabel in navigationController.view.subviews {
|
||||
label.isHidden = false
|
||||
}
|
||||
}
|
||||
_ = navigationController?.popViewController(animated: false)
|
||||
}
|
||||
let _ = navigationController?.popViewController(animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: create
|
||||
|
||||
extension PTDetailViewController {
|
||||
|
||||
fileprivate func createBackgroundImage(_ image: UIImage?) -> UIImageView {
|
||||
// add constraint closures
|
||||
let addConstraint: (_ imageView: UIImageView, _ toView: UIView, _ attribute: NSLayoutAttribute) -> () = {
|
||||
(imageView, toView, attribute) in
|
||||
let constraint = NSLayoutConstraint(item: imageView,
|
||||
attribute: attribute,
|
||||
relatedBy: .equal,
|
||||
toItem: toView,
|
||||
attribute: attribute,
|
||||
multiplier: 1,
|
||||
constant: 0)
|
||||
toView.addConstraint(constraint)
|
||||
}
|
||||
|
||||
// crate imageView
|
||||
let imageView = UIImageView(frame: CGRect.zero)
|
||||
imageView.image = image
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.contentMode = .center
|
||||
view.insertSubview(imageView, at: 0)
|
||||
|
||||
// added constraints
|
||||
for attribute in [NSLayoutAttribute.leading, NSLayoutAttribute.trailing, NSLayoutAttribute.top, NSLayoutAttribute.bottom] {
|
||||
addConstraint(imageView, view, attribute)
|
||||
}
|
||||
|
||||
return imageView
|
||||
}
|
||||
|
||||
fileprivate func createNavBar(_ color: UIColor) -> UIView {
|
||||
let navBar = UIView(frame: CGRect.zero)
|
||||
navBar.backgroundColor = color
|
||||
navBar.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(navBar)
|
||||
|
||||
for attributes: NSLayoutAttribute in [.left, .right, .top] {
|
||||
(view, navBar) >>>- {
|
||||
$0.attribute = attributes
|
||||
return
|
||||
}
|
||||
}
|
||||
navBar >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = 64
|
||||
return
|
||||
}
|
||||
|
||||
return navBar
|
||||
}
|
||||
|
||||
fileprivate func createBackgroundImage(_ image: UIImage?) -> UIImageView {
|
||||
|
||||
let imageView = UIImageView(frame: CGRect.zero)
|
||||
imageView.image = image
|
||||
imageView.frame = view.bounds
|
||||
imageView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
|
||||
imageView.contentMode = UIView.ContentMode.scaleAspectFill
|
||||
view.insertSubview(imageView, at: 0)
|
||||
|
||||
return imageView
|
||||
}
|
||||
|
||||
fileprivate func createNavBar(_ color: UIColor) -> UIView {
|
||||
let navBar = UIView(frame: CGRect.zero)
|
||||
navBar.backgroundColor = color
|
||||
navBar.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(navBar)
|
||||
|
||||
for attributes: NSLayoutConstraint.Attribute in [.left, .right, .top] {
|
||||
(view, navBar) >>>- {
|
||||
$0.attribute = attributes
|
||||
return
|
||||
}
|
||||
}
|
||||
navBar >>>- {
|
||||
$0.attribute = .height
|
||||
var constant: CGFloat = 64
|
||||
if #available(iOS 11.0, *) {
|
||||
if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top {
|
||||
constant += topPadding
|
||||
}
|
||||
}
|
||||
$0.constant = constant
|
||||
return
|
||||
}
|
||||
|
||||
return navBar
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,392 +24,409 @@
|
||||
import UIKit
|
||||
|
||||
fileprivate struct C {
|
||||
|
||||
struct Constraints {
|
||||
static let bottom = "Bottom"
|
||||
static let height = "Height"
|
||||
}
|
||||
|
||||
struct Constraints {
|
||||
static let bottom = "Bottom"
|
||||
static let height = "Height"
|
||||
}
|
||||
}
|
||||
|
||||
/// UITableViewCell with parallax background
|
||||
open class ParallaxCell: UITableViewCell {
|
||||
|
||||
/// Custom separator view
|
||||
open var separatorView: UIView?
|
||||
|
||||
var topSeparator: UIView? // only for animation
|
||||
|
||||
enum Direction {
|
||||
case up
|
||||
case down
|
||||
}
|
||||
|
||||
var bgImageY: NSLayoutConstraint?
|
||||
|
||||
var parallaxTitleY: NSLayoutConstraint?
|
||||
|
||||
/// parallax offset
|
||||
@IBInspectable open var difference: CGFloat = 100 // image parallax
|
||||
|
||||
var bgImage: UIImageView?
|
||||
var parallaxTitle: UILabel?
|
||||
|
||||
/// The foreground view’s background color.
|
||||
@IBInspectable open var foregroundColor = UIColor.black
|
||||
|
||||
/// The foreground view’s alpha.
|
||||
@IBInspectable open var foregroundAlpha: CGFloat = 0.5
|
||||
|
||||
var foregroundView: UIView?
|
||||
var isMovedHidden: Bool = false
|
||||
|
||||
fileprivate var closedBgImageYConstant: CGFloat = 0
|
||||
fileprivate var closedYPosition: CGFloat = 0
|
||||
|
||||
fileprivate var damping: CGFloat = 0.78
|
||||
|
||||
/**
|
||||
Initializes a view from data in a given unarchiver.
|
||||
|
||||
- parameter aDecoder: An unarchiver object.
|
||||
|
||||
- returns: An initialized UITableViewCell object.
|
||||
*/
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initializes a table cell with a style and a reuse identifier and returns it to the caller.
|
||||
|
||||
- parameter style: A constant indicating a cell style. See UITableViewCellStyle for descriptions of these constants.
|
||||
- parameter reuseIdentifier: A string used to identify the cell object if it is to be reused for drawing multiple rows of a table view. Pass nil if the cell object is not to be reused. You should use the same reuse identifier for all cells of the same form.
|
||||
|
||||
- returns: an initialized UITableViewCell object or nil if the object could not be created.
|
||||
*/
|
||||
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
commonInit()
|
||||
}
|
||||
/// Custom separator view
|
||||
open var separatorView: UIView?
|
||||
|
||||
var topSeparator: UIView? // only for animation
|
||||
|
||||
enum Direction {
|
||||
case up
|
||||
case down
|
||||
}
|
||||
|
||||
private var bgImageY: NSLayoutConstraint?
|
||||
private var bgImageHeight: NSLayoutConstraint?
|
||||
|
||||
private var parallaxTitleY: NSLayoutConstraint?
|
||||
|
||||
/// parallax offset
|
||||
@IBInspectable open var difference: CGFloat = 100 // image parallax
|
||||
|
||||
var bgImage: UIImageView?
|
||||
var parallaxTitle: UILabel?
|
||||
|
||||
/// The foreground view’s background color.
|
||||
@IBInspectable open var foregroundColor: UIColor = UIColor.black {
|
||||
didSet {
|
||||
foregroundView?.backgroundColor = foregroundColor
|
||||
}
|
||||
}
|
||||
|
||||
/// The foreground view’s alpha.
|
||||
@IBInspectable open var foregroundAlpha: CGFloat = 0.5 {
|
||||
didSet {
|
||||
foregroundView?.alpha = foregroundAlpha
|
||||
}
|
||||
}
|
||||
|
||||
var foregroundView: UIView?
|
||||
var isMovedHidden: Bool = false
|
||||
|
||||
fileprivate var closedBgImageYConstant: CGFloat = 0
|
||||
fileprivate var closedYPosition: CGFloat = 0
|
||||
fileprivate var closedHeight: CGFloat = 0
|
||||
|
||||
fileprivate var damping: CGFloat = 0.78
|
||||
|
||||
/**
|
||||
Initializes a view from data in a given unarchiver.
|
||||
|
||||
- parameter aDecoder: An unarchiver object.
|
||||
|
||||
- returns: An initialized UITableViewCell object.
|
||||
*/
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
commonInit()
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes a table cell with a style and a reuse identifier and returns it to the caller.
|
||||
|
||||
- parameter style: A constant indicating a cell style. See UITableViewCellStyle for descriptions of these constants.
|
||||
- parameter reuseIdentifier: A string used to identify the cell object if it is to be reused for drawing multiple rows of a table view. Pass nil if the cell object is not to be reused. You should use the same reuse identifier for all cells of the same form.
|
||||
|
||||
- returns: an initialized UITableViewCell object or nil if the object could not be created.
|
||||
*/
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
commonInit()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: life cicle
|
||||
|
||||
extension ParallaxCell {
|
||||
|
||||
func commonInit() {
|
||||
|
||||
layer.masksToBounds = false
|
||||
selectionStyle = .none
|
||||
|
||||
// create background image view
|
||||
let backgroundImageView = createBckgroundImage()
|
||||
|
||||
// add constraints
|
||||
if let bgSuperView = backgroundImageView.superview {
|
||||
for attribute: NSLayoutAttribute in [.leading, .trailing] {
|
||||
(bgSuperView, backgroundImageView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
|
||||
func commonInit() {
|
||||
|
||||
layer.masksToBounds = false
|
||||
selectionStyle = .none
|
||||
|
||||
// create background image view
|
||||
let backgroundImageView = createBckgroundImage()
|
||||
|
||||
// add constraints
|
||||
if let bgSuperView = backgroundImageView.superview {
|
||||
for attribute: NSLayoutConstraint.Attribute in [.leading, .trailing] {
|
||||
(bgSuperView, backgroundImageView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
bgImageY = (bgSuperView, backgroundImageView) >>>- {
|
||||
$0.attribute = .centerY
|
||||
return
|
||||
}
|
||||
bgImageHeight = backgroundImageView >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = bounds.height + difference
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
bgImageY = (bgSuperView, backgroundImageView) >>>- {
|
||||
$0.attribute = .centerY
|
||||
return
|
||||
}
|
||||
backgroundImageView >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = bounds.height + difference
|
||||
return
|
||||
}
|
||||
bgImage = backgroundImageView
|
||||
|
||||
foregroundView = createForegroundView(foregroundColor)
|
||||
contentView.backgroundColor = UIColor.black
|
||||
|
||||
// create title label
|
||||
let titleLabel = createTitleLable()
|
||||
for attribute: NSLayoutConstraint.Attribute in [.left, .right] {
|
||||
(contentView, titleLabel) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
parallaxTitleY = (contentView, titleLabel) >>>- {
|
||||
$0.attribute = .centerY
|
||||
return
|
||||
}
|
||||
titleLabel >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = bounds.height + difference
|
||||
return
|
||||
}
|
||||
parallaxTitle = titleLabel
|
||||
|
||||
separatorView = createSeparator(.black, height: 2.0, verticalAttribure: .bottom, verticalConstant: 0.0)
|
||||
}
|
||||
bgImage = backgroundImageView
|
||||
|
||||
foregroundView = createForegroundView(foregroundColor)
|
||||
contentView.backgroundColor = UIColor.black
|
||||
|
||||
// create title label
|
||||
let titleLabel = createTitleLable()
|
||||
for attribute: NSLayoutAttribute in [.left, .right] {
|
||||
(contentView, titleLabel) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
parallaxTitleY = (contentView, titleLabel) >>>- {
|
||||
$0.attribute = .centerY
|
||||
return
|
||||
|
||||
open override func prepareForReuse() {
|
||||
if topSeparator?.superview != nil {
|
||||
topSeparator?.removeFromSuperview()
|
||||
topSeparator = nil
|
||||
}
|
||||
}
|
||||
titleLabel >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = bounds.height + difference
|
||||
return
|
||||
}
|
||||
parallaxTitle = titleLabel
|
||||
|
||||
separatorView = createSeparator(.black, height: 2.0, verticalAttribure: .bottom, verticalConstant: 0.0)
|
||||
}
|
||||
|
||||
open override func prepareForReuse() {
|
||||
if topSeparator?.superview != nil {
|
||||
topSeparator?.removeFromSuperview()
|
||||
topSeparator = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
public extension ParallaxCell {
|
||||
|
||||
/**
|
||||
Sets the contents of the background image and title label
|
||||
|
||||
- parameter image: The image object which set to the backgroundImageView
|
||||
- parameter title: The text to be displayed in the Cell
|
||||
*/
|
||||
public func setImage(_ image: UIImage, title: String) {
|
||||
bgImage?.image = image
|
||||
parallaxTitle?.text = title
|
||||
}
|
||||
/**
|
||||
Sets the contents of the background image and title label
|
||||
|
||||
- parameter image: The image object which set to the backgroundImageView
|
||||
- parameter title: The text to be displayed in the Cell
|
||||
*/
|
||||
func setImage(_ image: UIImage, title: String) {
|
||||
bgImage?.image = image
|
||||
parallaxTitle?.text = title
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: internal
|
||||
|
||||
extension ParallaxCell {
|
||||
|
||||
func parallaxOffset(_ tableView: UITableView) {
|
||||
|
||||
guard let bgImageY = self.bgImageY , isMovedHidden == false else {
|
||||
return
|
||||
}
|
||||
|
||||
var deltaY = (frame.origin.y + frame.height/2) - tableView.contentOffset.y
|
||||
deltaY = min(tableView.bounds.height, max(deltaY, 0)) // range
|
||||
|
||||
var move : CGFloat = (deltaY / tableView.bounds.height) * difference
|
||||
move = move / 2.0 - move
|
||||
|
||||
bgImageY.constant = move
|
||||
}
|
||||
|
||||
func openCell(_ tableView: UITableView, duration: Double) {
|
||||
guard let superview = self.superview,
|
||||
let bgImageY = self.bgImageY else {
|
||||
return
|
||||
}
|
||||
|
||||
closedBgImageYConstant = bgImageY.constant
|
||||
closedYPosition = center.y
|
||||
|
||||
let offsetY = tableView.contentOffset.y
|
||||
let cellY = frame.origin.y - offsetY + frame.size.height / 2.0 + offsetY - tableView.frame.size.height / 2.0
|
||||
let cellFrame = CGRect(x: 0, y: cellY, width: tableView.frame.size.width, height: tableView.frame.size.height)
|
||||
frame = cellFrame
|
||||
superview.sendSubview(toBack: self)
|
||||
|
||||
// animation
|
||||
moveToCenter(duration , offset: offsetY)
|
||||
parallaxTitle?.isHidden = true
|
||||
foregroundHidden(true, duration: duration)
|
||||
}
|
||||
|
||||
func closeCell(_ duration: Double, tableView: UITableView, completion: @escaping () -> Void) {
|
||||
bgImageY?.constant = closedBgImageYConstant
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: damping, initialSpringVelocity: 0, options: UIViewAnimationOptions(), animations: { [weak self] () in
|
||||
guard let `self` = self else { return }
|
||||
self.bgImage?.superview?.layoutIfNeeded()
|
||||
self.center = CGPoint(x: self.center.x, y: self.closedYPosition)
|
||||
}, completion: {[weak self] finished in
|
||||
|
||||
self?.parallaxTitle?.isHidden = false
|
||||
completion()
|
||||
})
|
||||
|
||||
foregroundHidden(false, duration: duration / 2.0)
|
||||
}
|
||||
func parallaxOffset(_ tableView: UITableView) {
|
||||
|
||||
func animationMoveCell(_ direction: Direction, duration: Double, tableView: UITableView, selectedIndexPaht: IndexPath, close: Bool) {
|
||||
|
||||
let selfYPosition = close == false ? frame.origin.y : closedYPosition
|
||||
let selectedCellFrame = tableView.rectForRow(at: selectedIndexPaht)
|
||||
var dy: CGFloat = 0
|
||||
if selfYPosition < selectedCellFrame.origin.y {
|
||||
dy = selectedCellFrame.origin.y - tableView.contentOffset.y
|
||||
} else {
|
||||
dy = tableView.frame.size.height - (selectedCellFrame.origin.y - tableView.contentOffset.y + selectedCellFrame.size.height)
|
||||
guard let bgImageY = self.bgImageY, isMovedHidden == false else {
|
||||
return
|
||||
}
|
||||
|
||||
var deltaY = (frame.origin.y + frame.height / 2) - tableView.contentOffset.y
|
||||
deltaY = min(tableView.bounds.height, max(deltaY, 0)) // range
|
||||
|
||||
var move: CGFloat = (deltaY / tableView.bounds.height) * difference
|
||||
move = move / 2.0 - move
|
||||
|
||||
bgImageY.constant = move
|
||||
}
|
||||
dy = direction == .down ? dy * -1 : dy
|
||||
if close == false {
|
||||
closedYPosition = center.y
|
||||
} else {
|
||||
center.y = closedYPosition - dy
|
||||
|
||||
func openCell(_ tableView: UITableView, duration: Double) {
|
||||
guard let superview = self.superview,
|
||||
let bgImageY = self.bgImageY,
|
||||
let bgImageHeight = self.bgImageHeight else {
|
||||
return
|
||||
}
|
||||
|
||||
closedBgImageYConstant = bgImageY.constant
|
||||
closedYPosition = center.y
|
||||
closedHeight = bgImageHeight.constant
|
||||
|
||||
let offsetY = tableView.contentOffset.y
|
||||
let cellY = frame.origin.y - offsetY + frame.size.height / 2.0 + offsetY - tableView.frame.size.height / 2.0
|
||||
let cellFrame = CGRect(x: 0, y: cellY, width: tableView.frame.size.width, height: tableView.frame.size.height)
|
||||
frame = cellFrame
|
||||
superview.sendSubviewToBack(self)
|
||||
|
||||
// animation
|
||||
bgImageHeight.constant = cellFrame.height
|
||||
moveToCenter(duration, offset: offsetY)
|
||||
parallaxTitle?.isHidden = true
|
||||
foregroundHidden(true, duration: duration)
|
||||
}
|
||||
|
||||
func closeCell(_ duration: Double, tableView _: UITableView, completion: @escaping () -> Void) {
|
||||
bgImageY?.constant = closedBgImageYConstant
|
||||
bgImageHeight?.constant = closedHeight
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: damping, initialSpringVelocity: 0, options: UIView.AnimationOptions(), animations: { [weak self] () in
|
||||
guard let `self` = self else { return }
|
||||
self.bgImage?.superview?.layoutIfNeeded()
|
||||
self.center = CGPoint(x: self.center.x, y: self.closedYPosition)
|
||||
}, completion: { [weak self] _ in
|
||||
|
||||
self?.parallaxTitle?.isHidden = false
|
||||
completion()
|
||||
})
|
||||
|
||||
foregroundHidden(false, duration: duration / 2.0)
|
||||
}
|
||||
|
||||
func animationMoveCell(_ direction: Direction, duration: Double, tableView: UITableView, selectedIndexPaht: IndexPath, close: Bool) {
|
||||
|
||||
let selfYPosition = close == false ? frame.origin.y : closedYPosition
|
||||
let selectedCellFrame = tableView.rectForRow(at: selectedIndexPaht)
|
||||
var dy: CGFloat = 0
|
||||
if selfYPosition < selectedCellFrame.origin.y {
|
||||
dy = selectedCellFrame.origin.y - tableView.contentOffset.y
|
||||
} else {
|
||||
dy = tableView.frame.size.height - (selectedCellFrame.origin.y - tableView.contentOffset.y + selectedCellFrame.size.height)
|
||||
}
|
||||
dy = direction == .down ? dy * -1 : dy
|
||||
if close == false {
|
||||
closedYPosition = center.y
|
||||
} else {
|
||||
center.y = closedYPosition - dy
|
||||
}
|
||||
|
||||
superview?.bringSubviewToFront(self)
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: damping, initialSpringVelocity: 0, options: UIView.AnimationOptions(), animations: { () -> Void in
|
||||
self.center.y = self.center.y + dy
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
func showTopSeparator() {
|
||||
topSeparator = createSeparator(.black, height: 2, verticalAttribure: .top, verticalConstant: -2)
|
||||
}
|
||||
|
||||
superview?.bringSubview(toFront: self)
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: damping, initialSpringVelocity: 0, options: UIViewAnimationOptions(), animations: { () -> Void in
|
||||
self.center.y = self.center.y + dy
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
func showTopSeparator() {
|
||||
topSeparator = createSeparator(.black, height: 2, verticalAttribure: .top, verticalConstant: -2)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: animation
|
||||
|
||||
extension ParallaxCell {
|
||||
|
||||
fileprivate func moveToCenter(_ duration: Double, offset: CGFloat) {
|
||||
bgImageY?.constant = 0
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.78, initialSpringVelocity: 0, options: UIViewAnimationOptions(), animations: { () -> Void in
|
||||
self.frame.origin.y = offset
|
||||
self.bgImage?.superview?.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
fileprivate func foregroundHidden(_ hidden: Bool, duration: Double) {
|
||||
guard let foregroundView = self.foregroundView else {
|
||||
return
|
||||
|
||||
fileprivate func moveToCenter(_ duration: Double, offset: CGFloat) {
|
||||
bgImageY?.constant = 0
|
||||
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.78, initialSpringVelocity: 0, options: UIView.AnimationOptions(), animations: { () -> Void in
|
||||
self.frame.origin.y = offset
|
||||
self.bgImage?.superview?.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
if hidden == true {
|
||||
let currentConstrant = contentView.constraints.filter{return $0.identifier == C.Constraints.bottom ? true : false}
|
||||
contentView.removeConstraints(currentConstrant)
|
||||
|
||||
foregroundView >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = 64
|
||||
$0.identifier = C.Constraints.height
|
||||
return
|
||||
}
|
||||
} else {
|
||||
let currentConstrant = foregroundView.constraints.filter{return $0.identifier == C.Constraints.height ? true : false}
|
||||
foregroundView.removeConstraints(currentConstrant)
|
||||
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = .bottom
|
||||
$0.identifier = C.Constraints.bottom
|
||||
return
|
||||
}
|
||||
|
||||
fileprivate func foregroundHidden(_ hidden: Bool, duration: Double) {
|
||||
guard let foregroundView = self.foregroundView else {
|
||||
return
|
||||
}
|
||||
|
||||
if hidden == true {
|
||||
let currentConstrant = contentView.constraints.filter { return $0.identifier == C.Constraints.bottom ? true : false }
|
||||
contentView.removeConstraints(currentConstrant)
|
||||
|
||||
foregroundView >>>- {
|
||||
$0.attribute = .height
|
||||
var constant: CGFloat = 64
|
||||
if #available(iOS 11.0, *) {
|
||||
if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top {
|
||||
constant += topPadding
|
||||
}
|
||||
}
|
||||
$0.constant = constant
|
||||
$0.identifier = C.Constraints.height
|
||||
return
|
||||
}
|
||||
} else {
|
||||
let currentConstrant = foregroundView.constraints.filter { return $0.identifier == C.Constraints.height ? true : false }
|
||||
foregroundView.removeConstraints(currentConstrant)
|
||||
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = .bottom
|
||||
$0.identifier = C.Constraints.bottom
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: damping * 2.0,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIView.AnimationOptions(),
|
||||
animations: { () -> Void in
|
||||
foregroundView.superview?.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: damping * 2.0,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIViewAnimationOptions(),
|
||||
animations: { () -> Void in
|
||||
foregroundView.superview?.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: create
|
||||
extension ParallaxCell {
|
||||
|
||||
fileprivate func createBckgroundImage() -> UIImageView {
|
||||
|
||||
let container = createImageContainer()
|
||||
let imageView = UIImageView()
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.contentMode = .center
|
||||
container.addSubview(imageView)
|
||||
return imageView
|
||||
}
|
||||
|
||||
fileprivate func createImageContainer() -> UIView {
|
||||
let view = UIView(frame: CGRect.zero)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.layer.masksToBounds = true
|
||||
contentView.addSubview(view)
|
||||
|
||||
// added constraints
|
||||
for attribute: NSLayoutAttribute in [.left, .right, .top, .bottom] {
|
||||
(contentView, view) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
// MARK: create
|
||||
|
||||
|
||||
fileprivate func createTitleLable() -> UILabel {
|
||||
|
||||
let label = UILabel()
|
||||
label.backgroundColor = .clear
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textAlignment = .center
|
||||
if case let font as UIFont = UINavigationBar.appearance().titleTextAttributes?[NSFontAttributeName] {
|
||||
label.font = font
|
||||
extension ParallaxCell {
|
||||
|
||||
fileprivate func createBckgroundImage() -> UIImageView {
|
||||
|
||||
let container = UIView(frame: contentView.bounds)
|
||||
container.translatesAutoresizingMaskIntoConstraints = false
|
||||
container.backgroundColor = .clear
|
||||
container.clipsToBounds = true
|
||||
contentView.addSubview(container)
|
||||
for attribute: NSLayoutConstraint.Attribute in [.left, .right, .top, .bottom] {
|
||||
(contentView, container) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let imageView = UIImageView(frame: container.bounds)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
container.addSubview(imageView)
|
||||
return imageView
|
||||
}
|
||||
|
||||
if case let textColor as UIColor = UINavigationBar.appearance().titleTextAttributes?[NSForegroundColorAttributeName] {
|
||||
label.textColor = textColor
|
||||
|
||||
fileprivate func createTitleLable() -> UILabel {
|
||||
|
||||
let label = UILabel()
|
||||
label.backgroundColor = .clear
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
label.textAlignment = .center
|
||||
if case let font as UIFont = UINavigationBar.appearance().titleTextAttributes?[NSAttributedString.Key.font] {
|
||||
label.font = font
|
||||
}
|
||||
|
||||
if case let textColor as UIColor = UINavigationBar.appearance().titleTextAttributes?[NSAttributedString.Key.foregroundColor] {
|
||||
label.textColor = textColor
|
||||
}
|
||||
contentView.addSubview(label)
|
||||
return label
|
||||
}
|
||||
contentView.addSubview(label)
|
||||
return label
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: cofigure
|
||||
|
||||
extension ParallaxCell {
|
||||
|
||||
fileprivate func createForegroundView(_ color: UIColor) -> UIView {
|
||||
guard let bgImage = self.bgImage else {
|
||||
fatalError("set bgImage")
|
||||
|
||||
fileprivate func createForegroundView(_ color: UIColor) -> UIView {
|
||||
guard let bgImage = self.bgImage else {
|
||||
fatalError("set bgImage")
|
||||
}
|
||||
|
||||
let foregroundView = UIView()
|
||||
foregroundView.alpha = foregroundAlpha
|
||||
foregroundView.backgroundColor = color
|
||||
foregroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
contentView.insertSubview(foregroundView, aboveSubview: bgImage)
|
||||
|
||||
// add constraints
|
||||
for attribute: NSLayoutConstraint.Attribute in [.left, .right, .top] {
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = .bottom
|
||||
$0.identifier = C.Constraints.bottom
|
||||
return
|
||||
}
|
||||
|
||||
return foregroundView
|
||||
}
|
||||
|
||||
let foregroundView = UIView()
|
||||
foregroundView.alpha = foregroundAlpha
|
||||
foregroundView.backgroundColor = color
|
||||
foregroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
contentView.insertSubview(foregroundView, aboveSubview: bgImage)
|
||||
|
||||
// add constraints
|
||||
for attribute: NSLayoutAttribute in [.left, .right, .top] {
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
|
||||
// return bottom constraint
|
||||
fileprivate func createSeparator(_ color: UIColor, height: CGFloat, verticalAttribure: NSLayoutConstraint.Attribute, verticalConstant: CGFloat) -> UIView {
|
||||
let separator = UIView(frame: CGRect.zero)
|
||||
separator.backgroundColor = color
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.addSubview(separator)
|
||||
|
||||
for attribute: NSLayoutConstraint.Attribute in [.leading, .trailing] {
|
||||
(contentView, separator) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
(contentView, separator) >>>- {
|
||||
$0.attribute = verticalAttribure
|
||||
$0.constant = verticalConstant
|
||||
return
|
||||
}
|
||||
// height constraint
|
||||
separator >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = height
|
||||
return
|
||||
}
|
||||
return separator
|
||||
}
|
||||
(contentView, foregroundView) >>>- {
|
||||
$0.attribute = .bottom
|
||||
$0.identifier = C.Constraints.bottom
|
||||
return
|
||||
}
|
||||
|
||||
return foregroundView
|
||||
}
|
||||
|
||||
// return bottom constraint
|
||||
fileprivate func createSeparator(_ color: UIColor, height: CGFloat, verticalAttribure: NSLayoutAttribute, verticalConstant: CGFloat) -> UIView {
|
||||
let separator = UIView(frame: CGRect.zero)
|
||||
separator.backgroundColor = color
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.addSubview(separator)
|
||||
|
||||
for attribute: NSLayoutAttribute in [.leading, .trailing] {
|
||||
(contentView, separator) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
(contentView, separator) >>>- {
|
||||
$0.attribute = verticalAttribure
|
||||
$0.constant = verticalConstant
|
||||
return
|
||||
}
|
||||
// height constraint
|
||||
separator >>>- {
|
||||
$0.attribute = .height
|
||||
$0.constant = height
|
||||
return
|
||||
}
|
||||
return separator
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
func delay(_ delay:Double, closure:@escaping ()->()) {
|
||||
func delay(_ delay: Double, closure: @escaping () -> Void) {
|
||||
DispatchQueue.main.asyncAfter(
|
||||
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
|
||||
deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// ConstraintsHalper.swift
|
||||
// ConstraintsHelper.swift
|
||||
// AnimatedPageView
|
||||
//
|
||||
// Created by Alex K. on 13/04/16.
|
||||
@@ -9,70 +9,69 @@
|
||||
import UIKit
|
||||
|
||||
struct ConstraintInfo {
|
||||
var attribute: NSLayoutAttribute = .left
|
||||
var secondAttribute: NSLayoutAttribute = .notAnAttribute
|
||||
var constant: CGFloat = 0
|
||||
var identifier: String?
|
||||
var relation: NSLayoutRelation = .equal
|
||||
var attribute: NSLayoutConstraint.Attribute = .left
|
||||
var secondAttribute: NSLayoutConstraint.Attribute = .notAnAttribute
|
||||
var constant: CGFloat = 0
|
||||
var identifier: String?
|
||||
var relation: NSLayoutConstraint.Relation = .equal
|
||||
}
|
||||
|
||||
precedencegroup constOp {
|
||||
associativity: left
|
||||
higherThan: AssignmentPrecedence
|
||||
associativity: left
|
||||
higherThan: AssignmentPrecedence
|
||||
}
|
||||
|
||||
infix operator >>>- : constOp
|
||||
infix operator >>>-: constOp
|
||||
|
||||
@discardableResult
|
||||
func >>>- <T: UIView> (left: (T, T), block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
info.secondAttribute = info.secondAttribute == .notAnAttribute ? info.attribute : info.secondAttribute
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left.1,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: left.0,
|
||||
attribute: info.secondAttribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.0.addConstraint(constraint)
|
||||
return constraint
|
||||
func >>>- <T: UIView>(left: (T, T), block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
info.secondAttribute = info.secondAttribute == .notAnAttribute ? info.attribute : info.secondAttribute
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left.1,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: left.0,
|
||||
attribute: info.secondAttribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.0.addConstraint(constraint)
|
||||
return constraint
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func >>>- <T: UIView> (left: T, block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: nil,
|
||||
attribute: info.attribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.addConstraint(constraint)
|
||||
return constraint
|
||||
func >>>- <T: UIView>(left: T, block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: nil,
|
||||
attribute: info.attribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.addConstraint(constraint)
|
||||
return constraint
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func >>>- <T: UIView> (left: (T, T, T), block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
info.secondAttribute = info.secondAttribute == .notAnAttribute ? info.attribute : info.secondAttribute
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left.1,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: left.2,
|
||||
attribute: info.secondAttribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.0.addConstraint(constraint)
|
||||
return constraint
|
||||
}
|
||||
func >>>- <T: UIView>(left: (T, T, T), block: (inout ConstraintInfo) -> Void) -> NSLayoutConstraint {
|
||||
var info = ConstraintInfo()
|
||||
block(&info)
|
||||
info.secondAttribute = info.secondAttribute == .notAnAttribute ? info.attribute : info.secondAttribute
|
||||
|
||||
let constraint = NSLayoutConstraint(item: left.1,
|
||||
attribute: info.attribute,
|
||||
relatedBy: info.relation,
|
||||
toItem: left.2,
|
||||
attribute: info.secondAttribute,
|
||||
multiplier: 1,
|
||||
constant: info.constant)
|
||||
constraint.identifier = info.identifier
|
||||
left.0.addConstraint(constraint)
|
||||
return constraint
|
||||
}
|
||||
|
||||
@@ -29,53 +29,58 @@ internal enum MovingDirection {
|
||||
}
|
||||
|
||||
internal protocol Moving: class {
|
||||
|
||||
var defaultYPosition: CGFloat {get set}
|
||||
|
||||
func move(_ duration: Double, direction: MovingDirection, completion: ((Bool) -> Void)?)
|
||||
|
||||
var defaultYPosition: CGFloat { get set }
|
||||
|
||||
func move(_ duration: Double, direction: MovingDirection, completion: ((Bool) -> Void)?)
|
||||
}
|
||||
|
||||
extension Moving where Self: UIView {
|
||||
|
||||
func move(_ duration: Double, direction: MovingDirection, completion: ((Bool) -> Void)?) {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: 0.78,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIViewAnimationOptions(),
|
||||
animations: { [weak self] () -> Void in
|
||||
guard let `self` = self else { return }
|
||||
var toYPosition = self.defaultYPosition
|
||||
if direction == .up {
|
||||
self.defaultYPosition = self.frame.origin.y
|
||||
toYPosition = 20
|
||||
}
|
||||
self.frame = CGRect(x: 0, y: toYPosition, width: self.frame.size.width, height: self.frame.size.height)
|
||||
}, completion: completion)
|
||||
}
|
||||
|
||||
func move(_ duration: Double, direction: MovingDirection, completion: ((Bool) -> Void)?) {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: 0.78,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIView.AnimationOptions(),
|
||||
animations: { [weak self] () -> Void in
|
||||
guard let `self` = self else { return }
|
||||
var toYPosition = self.defaultYPosition
|
||||
if direction == .up {
|
||||
self.defaultYPosition = self.frame.origin.y
|
||||
var position: CGFloat = 20
|
||||
if #available(iOS 11.0, *) {
|
||||
if let topPadding = UIApplication.shared.keyWindow?.safeAreaInsets.top {
|
||||
position = topPadding
|
||||
}
|
||||
}
|
||||
toYPosition = position
|
||||
}
|
||||
self.frame = CGRect(x: 0, y: toYPosition, width: self.frame.size.width, height: self.frame.size.height)
|
||||
}, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MovingLabel: UILabel, Moving {
|
||||
var defaultYPosition: CGFloat = 0
|
||||
var defaultYPosition: CGFloat = 0
|
||||
}
|
||||
|
||||
internal class MovingView: UIView {
|
||||
var defaultYPosition: CGFloat = 0
|
||||
|
||||
internal func move(_ duration: Double, direction: MovingDirection, distance: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||
var yPosition = defaultYPosition - 2
|
||||
if direction == .down {
|
||||
defaultYPosition = frame.origin.y
|
||||
yPosition = distance
|
||||
}
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: 0.78,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIViewAnimationOptions(),
|
||||
animations: { () -> Void in
|
||||
self.frame.origin.y = yPosition
|
||||
}, completion: completion)
|
||||
}
|
||||
var defaultYPosition: CGFloat = 0
|
||||
|
||||
internal func move(_ duration: Double, direction: MovingDirection, distance: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||
var yPosition = defaultYPosition - 2
|
||||
if direction == .down {
|
||||
defaultYPosition = frame.origin.y
|
||||
yPosition = distance
|
||||
}
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: 0.78,
|
||||
initialSpringVelocity: 0,
|
||||
options: UIView.AnimationOptions(),
|
||||
animations: { () -> Void in
|
||||
self.frame.origin.y = yPosition
|
||||
}, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,214 +22,216 @@
|
||||
// THE SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (l?, r?):
|
||||
return l < r
|
||||
case (nil, _?):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
fileprivate func < <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (l?, r?):
|
||||
return l < r
|
||||
case (nil, _?):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Base UITableViewController for preview transition
|
||||
open class PTTableViewController: UITableViewController {
|
||||
|
||||
internal var currentCell: ParallaxCell?
|
||||
|
||||
fileprivate var duration: Double = 0.65
|
||||
fileprivate var currentTextLabel: MovingLabel?
|
||||
|
||||
internal var currentCell: ParallaxCell?
|
||||
|
||||
fileprivate var duration: Double = 0.8
|
||||
fileprivate var currentTextLabel: MovingLabel?
|
||||
}
|
||||
|
||||
// MARK: public
|
||||
|
||||
public extension PTTableViewController {
|
||||
|
||||
/**
|
||||
Pushes a view controller onto the receiver’s stack and updates the display whith custom animation.
|
||||
|
||||
- parameter viewController: The view controller to push onto the stack.
|
||||
*/
|
||||
public func pushViewController(_ viewController: PTDetailViewController) {
|
||||
|
||||
guard let currentCell = currentCell,
|
||||
let navigationController = self.navigationController else {
|
||||
fatalError("current cell is empty or add navigationController")
|
||||
|
||||
/**
|
||||
Pushes a view controller onto the receiver’s stack and updates the display whith custom animation.
|
||||
|
||||
- parameter viewController: The view controller to push onto the stack.
|
||||
*/
|
||||
func pushViewController(_ viewController: PTDetailViewController) {
|
||||
|
||||
guard let currentCell = currentCell,
|
||||
let navigationController = self.navigationController else {
|
||||
fatalError("current cell is empty or add navigationController")
|
||||
}
|
||||
|
||||
if let currentIndex = tableView.indexPath(for: currentCell) {
|
||||
let nextIndex = IndexPath(row: (currentIndex as NSIndexPath).row + 1, section: (currentIndex as NSIndexPath).section)
|
||||
if case let nextCell as ParallaxCell = tableView.cellForRow(at: nextIndex) {
|
||||
nextCell.showTopSeparator()
|
||||
nextCell.superview?.bringSubviewToFront(nextCell)
|
||||
}
|
||||
}
|
||||
|
||||
currentTextLabel = createTitleLable(currentCell)
|
||||
currentTextLabel?.move(duration, direction: .up, completion: nil)
|
||||
|
||||
currentCell.openCell(tableView, duration: duration)
|
||||
moveCells(tableView, currentCell: currentCell, duration: duration)
|
||||
if let bgImage = currentCell.bgImage?.image {
|
||||
viewController.bgImage = bgImage
|
||||
}
|
||||
if let text = currentCell.parallaxTitle?.text {
|
||||
viewController.titleText = text
|
||||
}
|
||||
delay(duration) {
|
||||
navigationController.pushViewController(viewController, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
if let currentIndex = tableView.indexPath(for: currentCell) {
|
||||
let nextIndex = IndexPath(row: (currentIndex as NSIndexPath).row + 1, section: (currentIndex as NSIndexPath).section)
|
||||
if case let nextCell as ParallaxCell = tableView.cellForRow(at: nextIndex) {
|
||||
nextCell.showTopSeparator()
|
||||
nextCell.superview?.bringSubview(toFront: nextCell)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.currentTextLabel = createTitleLable(currentCell)
|
||||
currentTextLabel?.move(duration, direction: .up, completion: nil)
|
||||
|
||||
currentCell.openCell(tableView, duration: duration)
|
||||
moveCells(tableView, currentCell: currentCell, duration: duration)
|
||||
if let bgImage = currentCell.bgImage?.image {
|
||||
viewController.bgImage = bgImage
|
||||
}
|
||||
if let text = currentCell.parallaxTitle?.text {
|
||||
viewController.titleText = text
|
||||
}
|
||||
delay(duration) {
|
||||
navigationController.pushViewController(viewController, animated: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: life cicle
|
||||
|
||||
extension PTTableViewController {
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0);
|
||||
tableView.separatorStyle = .none
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
moveCellsBackIfNeed(duration) {
|
||||
self.tableView.reloadData()
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.separatorStyle = .none
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
tableView.contentInsetAdjustmentBehavior = .never
|
||||
} else {
|
||||
tableView.contentInset = UIEdgeInsets.init(top: -64, left: 0, bottom: 0, right: 0)
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
moveCellsBackIfNeed(duration) {
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
closeCurrentCellIfNeed(duration)
|
||||
moveDownCurrentLabelIfNeed()
|
||||
}
|
||||
closeCurrentCellIfNeed(duration)
|
||||
moveDownCurrentLabelIfNeed()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: create
|
||||
|
||||
extension PTTableViewController {
|
||||
|
||||
fileprivate func createTitleLable(_ cell: ParallaxCell) -> MovingLabel {
|
||||
|
||||
let yPosition = cell.frame.origin.y + cell.frame.size.height / 2.0 - 22 - tableView.contentOffset.y
|
||||
let label = MovingLabel(frame: CGRect(x: 0, y: yPosition, width: UIScreen.main.bounds.size.width, height: 44))
|
||||
label.textAlignment = .center
|
||||
label.backgroundColor = .clear
|
||||
if let font = cell.parallaxTitle?.font,
|
||||
let text = cell.parallaxTitle?.text,
|
||||
let textColor = cell.parallaxTitle?.textColor {
|
||||
label.font = font
|
||||
label.text = text
|
||||
label.textColor = textColor
|
||||
|
||||
fileprivate func createTitleLable(_ cell: ParallaxCell) -> MovingLabel {
|
||||
|
||||
let yPosition = cell.frame.origin.y + cell.frame.size.height / 2.0 - 22 - tableView.contentOffset.y
|
||||
let label = MovingLabel(frame: CGRect(x: 0, y: yPosition, width: UIScreen.main.bounds.size.width, height: 44))
|
||||
label.textAlignment = .center
|
||||
label.backgroundColor = .clear
|
||||
if let font = cell.parallaxTitle?.font,
|
||||
let text = cell.parallaxTitle?.text,
|
||||
let textColor = cell.parallaxTitle?.textColor {
|
||||
label.font = font
|
||||
label.text = text
|
||||
label.textColor = textColor
|
||||
}
|
||||
|
||||
navigationController?.view.addSubview(label)
|
||||
return label
|
||||
}
|
||||
|
||||
navigationController?.view.addSubview(label)
|
||||
return label
|
||||
}
|
||||
|
||||
fileprivate func createSeparator(_ color: UIColor?, height: CGFloat, cell: UITableViewCell) -> MovingView {
|
||||
|
||||
let yPosition = cell.frame.origin.y + cell.frame.size.height - tableView.contentOffset.y
|
||||
let separator = MovingView(frame: CGRect(x:0.0, y: yPosition, width: tableView.bounds.size.width, height: height))
|
||||
if let color = color {
|
||||
separator.backgroundColor = color
|
||||
|
||||
fileprivate func createSeparator(_ color: UIColor?, height: CGFloat, cell: UITableViewCell) -> MovingView {
|
||||
|
||||
let yPosition = cell.frame.origin.y + cell.frame.size.height - tableView.contentOffset.y
|
||||
let separator = MovingView(frame: CGRect(x: 0.0, y: yPosition, width: tableView.bounds.size.width, height: height))
|
||||
if let color = color {
|
||||
separator.backgroundColor = color
|
||||
}
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
navigationController?.view.addSubview(separator)
|
||||
return separator
|
||||
}
|
||||
separator.translatesAutoresizingMaskIntoConstraints = false
|
||||
navigationController?.view.addSubview(separator)
|
||||
return separator
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: tableView dataSource
|
||||
|
||||
extension PTTableViewController {
|
||||
|
||||
final public override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||
|
||||
guard let currentCell = tableView.cellForRow(at: indexPath) as? ParallaxCell else {
|
||||
return indexPath
|
||||
|
||||
public final override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||
|
||||
guard let currentCell = tableView.cellForRow(at: indexPath) as? ParallaxCell else {
|
||||
return indexPath
|
||||
}
|
||||
|
||||
self.currentCell = currentCell
|
||||
return indexPath
|
||||
}
|
||||
|
||||
self.currentCell = currentCell
|
||||
return indexPath
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: helpers
|
||||
|
||||
extension PTTableViewController {
|
||||
|
||||
fileprivate func parallaxOffsetDidChange(_ offset: CGFloat) {
|
||||
|
||||
let _ = tableView.visibleCells
|
||||
.filter{$0 != currentCell }
|
||||
.forEach { if case let cell as ParallaxCell = $0 { cell.parallaxOffset(tableView) } }
|
||||
}
|
||||
|
||||
fileprivate func moveCellsBackIfNeed(_ duration: Double, completion: @escaping () -> Void) {
|
||||
|
||||
guard let currentCell = self.currentCell,
|
||||
let currentIndex = tableView.indexPath(for: currentCell) else {
|
||||
return
|
||||
|
||||
fileprivate func parallaxOffsetDidChange(_: CGFloat) {
|
||||
|
||||
_ = tableView.visibleCells
|
||||
.filter { $0 != currentCell }
|
||||
.forEach { if case let cell as ParallaxCell = $0 { cell.parallaxOffset(tableView) } }
|
||||
}
|
||||
|
||||
for case let cell as ParallaxCell in tableView.visibleCells where cell != currentCell {
|
||||
|
||||
if cell.isMovedHidden == false {continue}
|
||||
|
||||
if let index = tableView.indexPath(for: cell) {
|
||||
let direction = (index as NSIndexPath).row < (currentIndex as NSIndexPath).row ? ParallaxCell.Direction .up : ParallaxCell.Direction.down
|
||||
cell.animationMoveCell(direction, duration: duration, tableView: tableView, selectedIndexPaht: currentIndex, close: true)
|
||||
cell.isMovedHidden = false
|
||||
}
|
||||
|
||||
fileprivate func moveCellsBackIfNeed(_ duration: Double, completion: @escaping () -> Void) {
|
||||
|
||||
guard let currentCell = self.currentCell,
|
||||
let currentIndex = tableView.indexPath(for: currentCell) else {
|
||||
return
|
||||
}
|
||||
|
||||
for case let cell as ParallaxCell in tableView.visibleCells where cell != currentCell {
|
||||
|
||||
if cell.isMovedHidden == false { continue }
|
||||
|
||||
if let index = tableView.indexPath(for: cell) {
|
||||
let direction = (index as NSIndexPath).row < (currentIndex as NSIndexPath).row ? ParallaxCell.Direction.up : ParallaxCell.Direction.down
|
||||
cell.animationMoveCell(direction, duration: duration, tableView: tableView, selectedIndexPaht: currentIndex, close: true)
|
||||
cell.isMovedHidden = false
|
||||
}
|
||||
}
|
||||
delay(duration, closure: completion)
|
||||
}
|
||||
delay(duration, closure: completion)
|
||||
}
|
||||
|
||||
fileprivate func closeCurrentCellIfNeed(_ duration: Double) {
|
||||
|
||||
guard let currentCell = self.currentCell else {
|
||||
return
|
||||
|
||||
fileprivate func closeCurrentCellIfNeed(_ duration: Double) {
|
||||
|
||||
guard let currentCell = self.currentCell else {
|
||||
return
|
||||
}
|
||||
|
||||
currentCell.closeCell(duration, tableView: tableView) { () -> Void in
|
||||
self.currentCell = nil
|
||||
}
|
||||
}
|
||||
|
||||
currentCell.closeCell(duration, tableView: tableView) { () -> Void in
|
||||
self.currentCell = nil
|
||||
|
||||
fileprivate func moveDownCurrentLabelIfNeed() {
|
||||
|
||||
guard let currentTextLabel = self.currentTextLabel else {
|
||||
return
|
||||
}
|
||||
currentTextLabel.move(duration, direction: .down) { _ in
|
||||
currentTextLabel.removeFromSuperview()
|
||||
self.currentTextLabel = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func moveDownCurrentLabelIfNeed() {
|
||||
|
||||
guard let currentTextLabel = self.currentTextLabel else {
|
||||
return
|
||||
|
||||
// animtaions
|
||||
fileprivate func moveCells(_ tableView: UITableView, currentCell: ParallaxCell, duration: Double) {
|
||||
guard let currentIndex = tableView.indexPath(for: currentCell) else {
|
||||
return
|
||||
}
|
||||
|
||||
for case let cell as ParallaxCell in tableView.visibleCells where cell != currentCell {
|
||||
cell.isMovedHidden = true
|
||||
let row = (tableView.indexPath(for: cell) as NSIndexPath?)?.row
|
||||
let direction = row < (currentIndex as NSIndexPath).row ? ParallaxCell.Direction.down : ParallaxCell.Direction.up
|
||||
cell.animationMoveCell(direction, duration: duration, tableView: tableView, selectedIndexPaht: currentIndex, close: false)
|
||||
}
|
||||
}
|
||||
currentTextLabel.move(duration, direction: .down) { (finished) in
|
||||
currentTextLabel.removeFromSuperview()
|
||||
self.currentTextLabel = nil
|
||||
}
|
||||
}
|
||||
|
||||
// animtaions
|
||||
fileprivate func moveCells(_ tableView: UITableView, currentCell: ParallaxCell, duration: Double) {
|
||||
guard let currentIndex = tableView.indexPath(for: currentCell) else {
|
||||
return
|
||||
}
|
||||
|
||||
for case let cell as ParallaxCell in tableView.visibleCells where cell != currentCell {
|
||||
cell.isMovedHidden = true
|
||||
let row = (tableView.indexPath(for: cell) as NSIndexPath?)?.row
|
||||
let direction = row < (currentIndex as NSIndexPath).row ? ParallaxCell.Direction .down : ParallaxCell.Direction.up
|
||||
cell.animationMoveCell(direction, duration: duration, tableView: tableView, selectedIndexPaht: currentIndex, close: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: ScroolViewDelegate
|
||||
|
||||
extension PTTableViewController {
|
||||
|
||||
override open func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
parallaxOffsetDidChange(scrollView.contentOffset.y)
|
||||
}
|
||||
|
||||
open override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
parallaxOffsetDidChange(scrollView.contentOffset.y)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
//
|
||||
// LayerAnimationHalper.swift
|
||||
// PreviewTransitionDemo
|
||||
//
|
||||
// Created by Alex K. on 03/05/16.
|
||||
// Copyright © 2016 Alex K. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
|
||||
private func createAnimationFromKey(key: String, duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) -> CABasicAnimation {
|
||||
let animation = CABasicAnimation(keyPath: key)
|
||||
animation.duration = duration
|
||||
animation.toValue = to
|
||||
animation.fromValue = from
|
||||
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
|
||||
animation.beginTime = CACurrentMediaTime() + delay
|
||||
if remove == false {
|
||||
animation.isRemovedOnCompletion = remove
|
||||
animation.fillMode = kCAFillModeForwards
|
||||
}
|
||||
return animation
|
||||
}
|
||||
|
||||
|
||||
func rotateDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "transform.rotation.z",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
|
||||
|
||||
func scaleDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "transform.scale",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
|
||||
|
||||
func opacityDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "opacity",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// LayerAnimationHelper.swift
|
||||
// PreviewTransitionDemo
|
||||
//
|
||||
// Created by Alex K. on 03/05/16.
|
||||
// Copyright © 2016 Alex K. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
|
||||
private func createAnimationFromKey(key: String, duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) -> CABasicAnimation {
|
||||
let animation = CABasicAnimation(keyPath: key)
|
||||
animation.duration = duration
|
||||
animation.toValue = to
|
||||
animation.fromValue = from
|
||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
|
||||
animation.beginTime = CACurrentMediaTime() + delay
|
||||
if remove == false {
|
||||
animation.isRemovedOnCompletion = remove
|
||||
animation.fillMode = CAMediaTimingFillMode.forwards
|
||||
}
|
||||
return animation
|
||||
}
|
||||
|
||||
func rotateDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "transform.rotation.z",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
|
||||
func scaleDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "transform.scale",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
|
||||
func opacityDuration(duration: Double, from: CGFloat, to: CGFloat, delay: Double = 0, remove: Bool = true) {
|
||||
let animation = createAnimationFromKey(key: "opacity",
|
||||
duration: duration,
|
||||
from: from,
|
||||
to: to,
|
||||
delay: delay,
|
||||
remove: remove)
|
||||
|
||||
layer.add(animation, forKey: nil)
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,24 @@ import Foundation
|
||||
import UIKit
|
||||
|
||||
extension UIImage {
|
||||
enum Asset: String {
|
||||
case _1 = "1"
|
||||
case _2 = "2"
|
||||
case _3 = "3"
|
||||
case _4 = "4"
|
||||
case _5 = "5"
|
||||
case Back = "back"
|
||||
case HertIcon = "HertIcon"
|
||||
case PlusIcon = "PlusIcon"
|
||||
case ShareIcon = "ShareIcon"
|
||||
case TransparentPixel = "TransparentPixel"
|
||||
enum Asset: String {
|
||||
case _1 = "1"
|
||||
case _2 = "2"
|
||||
case _3 = "3"
|
||||
case _4 = "4"
|
||||
case _5 = "5"
|
||||
case Back = "back"
|
||||
case HertIcon
|
||||
case PlusIcon
|
||||
case ShareIcon
|
||||
case TransparentPixel
|
||||
|
||||
var image: UIImage {
|
||||
return UIImage(asset: self)
|
||||
var image: UIImage {
|
||||
return UIImage(asset: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convenience init!(asset: Asset) {
|
||||
self.init(named: asset.rawValue)
|
||||
}
|
||||
convenience init!(asset: Asset) {
|
||||
self.init(named: asset.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,36 +11,32 @@ import UIKit
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
var window: UIWindow?
|
||||
|
||||
func application(application _: UIApplication, didFinishLaunchingWithOptions _: [NSObject: AnyObject]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
func applicationWillResignActive(application _: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationWillResignActive(application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
func applicationDidEnterBackground(application _: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(application: UIApplication) {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
func applicationWillEnterForeground(application _: UIApplication) {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(application _: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(application _: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,31 +10,28 @@ import UIKit
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var lableText: UILabel!
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
let animation = CABasicAnimation(keyPath: "fontSize")
|
||||
animation.toValue = 10
|
||||
animation.duration = 3
|
||||
|
||||
let textLayer = CATextLayer()
|
||||
textLayer.font = UIFont.systemFontOfSize(50)
|
||||
textLayer.fontSize = 50
|
||||
textLayer.string = "text"
|
||||
textLayer.foregroundColor = UIColor.redColor().CGColor
|
||||
textLayer.backgroundColor = UIColor.blackColor().CGColor
|
||||
textLayer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
|
||||
view.layer.addSublayer(textLayer)
|
||||
|
||||
lableText.layer.addAnimation(animation, forKey: nil)
|
||||
}
|
||||
@IBOutlet var lableText: UILabel!
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
let animation = CABasicAnimation(keyPath: "fontSize")
|
||||
animation.toValue = 10
|
||||
animation.duration = 3
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
let textLayer = CATextLayer()
|
||||
textLayer.font = UIFont.systemFontOfSize(50)
|
||||
textLayer.fontSize = 50
|
||||
textLayer.string = "text"
|
||||
textLayer.foregroundColor = UIColor.redColor().CGColor
|
||||
textLayer.backgroundColor = UIColor.blackColor().CGColor
|
||||
textLayer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
|
||||
view.layer.addSublayer(textLayer)
|
||||
|
||||
lableText.layer.addAnimation(animation, forKey: nil)
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,30 +8,19 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8416D9EA1CB28E2600BB599D /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8416D9E91CB28E2600BB599D /* Extensions.swift */; };
|
||||
8416D9EB1CB28E2600BB599D /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8416D9E91CB28E2600BB599D /* Extensions.swift */; };
|
||||
84204DFD1CB2869E001FC263 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204DFC1CB2869E001FC263 /* AppDelegate.swift */; };
|
||||
84204E021CB2869E001FC263 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84204E001CB2869E001FC263 /* Main.storyboard */; };
|
||||
84204E041CB2869E001FC263 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84204E031CB2869E001FC263 /* Assets.xcassets */; };
|
||||
84204E071CB2869E001FC263 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84204E051CB2869E001FC263 /* LaunchScreen.storyboard */; };
|
||||
84204E121CB2869E001FC263 /* PreviewTransitionDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E111CB2869E001FC263 /* PreviewTransitionDemoTests.swift */; };
|
||||
84204E1F1CB289B3001FC263 /* PTDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E1E1CB289B3001FC263 /* PTDetailViewController.swift */; };
|
||||
84204E281CB289DC001FC263 /* ParallaxCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E221CB289DC001FC263 /* ParallaxCell.swift */; };
|
||||
84204E291CB289DC001FC263 /* TimeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E241CB289DC001FC263 /* TimeExtensions.swift */; };
|
||||
84204E2A1CB289DC001FC263 /* MovingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E261CB289DC001FC263 /* MovingViews.swift */; };
|
||||
84204E2B1CB289DC001FC263 /* PTTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E271CB289DC001FC263 /* PTTableViewController.swift */; };
|
||||
84204E2F1CB28B5B001FC263 /* DemoDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E2D1CB28B5B001FC263 /* DemoDetailViewController.swift */; };
|
||||
84204E301CB28B5B001FC263 /* DemoDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E2D1CB28B5B001FC263 /* DemoDetailViewController.swift */; };
|
||||
84204E311CB28B5B001FC263 /* DemoTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E2E1CB28B5B001FC263 /* DemoTableViewController.swift */; };
|
||||
84204E321CB28B5B001FC263 /* DemoTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E2E1CB28B5B001FC263 /* DemoTableViewController.swift */; };
|
||||
842D7E9B1CB395C800DE59DE /* ParallaxCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E221CB289DC001FC263 /* ParallaxCell.swift */; };
|
||||
842D7E9C1CB395D900DE59DE /* PTTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E271CB289DC001FC263 /* PTTableViewController.swift */; };
|
||||
842D7E9D1CB395FC00DE59DE /* TimeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E241CB289DC001FC263 /* TimeExtensions.swift */; };
|
||||
842D7E9E1CB3960200DE59DE /* MovingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E261CB289DC001FC263 /* MovingViews.swift */; };
|
||||
842D7E9F1CB3960A00DE59DE /* PTDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E1E1CB289B3001FC263 /* PTDetailViewController.swift */; };
|
||||
848526521CD39CFB0052BEAD /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848526511CD39CFB0052BEAD /* Images.swift */; };
|
||||
848526531CD39CFB0052BEAD /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848526511CD39CFB0052BEAD /* Images.swift */; };
|
||||
848BD7E51CCF54620046DC13 /* ConstraintsHalper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848BD7E41CCF54620046DC13 /* ConstraintsHalper.swift */; };
|
||||
848BD7E61CCF54620046DC13 /* ConstraintsHalper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848BD7E41CCF54620046DC13 /* ConstraintsHalper.swift */; };
|
||||
8499D8BA1D006020004B5B37 /* PreivewTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 8499D8B91D006020004B5B37 /* PreivewTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8499D8BE1D006020004B5B37 /* PreviewTransition.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8499D8B71D006020004B5B37 /* PreviewTransition.framework */; };
|
||||
8499D8BF1D006020004B5B37 /* PreviewTransition.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8499D8B71D006020004B5B37 /* PreviewTransition.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
@@ -41,20 +30,11 @@
|
||||
8499D8C71D006082004B5B37 /* MovingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E261CB289DC001FC263 /* MovingViews.swift */; };
|
||||
8499D8C81D006085004B5B37 /* PTTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E271CB289DC001FC263 /* PTTableViewController.swift */; };
|
||||
8499D8C91D00608B004B5B37 /* PTDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84204E1E1CB289B3001FC263 /* PTDetailViewController.swift */; };
|
||||
84A36E0E1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift */; };
|
||||
84A36E0F1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift */; };
|
||||
84A36E0E1CD88EEA00AEC2F2 /* LayerAnimationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHelper.swift */; };
|
||||
84A36E141CD8C70F00AEC2F2 /* ScreenShot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A36E131CD8C70F00AEC2F2 /* ScreenShot.swift */; };
|
||||
84A36E151CD8C70F00AEC2F2 /* ScreenShot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A36E131CD8C70F00AEC2F2 /* ScreenShot.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
84204E0E1CB2869E001FC263 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 84204DF11CB2869E001FC263 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 84204DF81CB2869E001FC263;
|
||||
remoteInfo = PreviewTransitionDemo;
|
||||
};
|
||||
8499D8BC1D006020004B5B37 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 84204DF11CB2869E001FC263 /* Project object */;
|
||||
@@ -86,9 +66,6 @@
|
||||
84204E031CB2869E001FC263 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
84204E061CB2869E001FC263 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
84204E081CB2869E001FC263 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
84204E0D1CB2869E001FC263 /* PreviewTransitionDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PreviewTransitionDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
84204E111CB2869E001FC263 /* PreviewTransitionDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewTransitionDemoTests.swift; sourceTree = "<group>"; };
|
||||
84204E131CB2869E001FC263 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
84204E1E1CB289B3001FC263 /* PTDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PTDetailViewController.swift; sourceTree = "<group>"; };
|
||||
84204E221CB289DC001FC263 /* ParallaxCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParallaxCell.swift; sourceTree = "<group>"; };
|
||||
84204E241CB289DC001FC263 /* TimeExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeExtensions.swift; sourceTree = "<group>"; };
|
||||
@@ -101,7 +78,7 @@
|
||||
8499D8B71D006020004B5B37 /* PreviewTransition.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PreviewTransition.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8499D8B91D006020004B5B37 /* PreivewTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PreivewTransition.h; sourceTree = "<group>"; };
|
||||
8499D8BB1D006020004B5B37 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerAnimationHalper.swift; sourceTree = "<group>"; };
|
||||
84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayerAnimationHelper.swift; sourceTree = "<group>"; };
|
||||
84A36E131CD8C70F00AEC2F2 /* ScreenShot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenShot.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -114,13 +91,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
84204E0A1CB2869E001FC263 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8499D8B31D006020004B5B37 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -142,11 +112,10 @@
|
||||
84204DF01CB2869E001FC263 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84A36E111CD8C31C00AEC2F2 /* Halpers */,
|
||||
84A36E111CD8C31C00AEC2F2 /* Helpers */,
|
||||
848526501CD39CDD0052BEAD /* Constants */,
|
||||
84204E1C1CB286DD001FC263 /* PreviewTransition */,
|
||||
84204DFB1CB2869E001FC263 /* PreviewTransitionDemo */,
|
||||
84204E101CB2869E001FC263 /* PreviewTransitionDemoTests */,
|
||||
8499D8B81D006020004B5B37 /* PreivewTransition */,
|
||||
84204DFA1CB2869E001FC263 /* Products */,
|
||||
);
|
||||
@@ -156,7 +125,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84204DF91CB2869E001FC263 /* PreviewTransitionDemo.app */,
|
||||
84204E0D1CB2869E001FC263 /* PreviewTransitionDemoTests.xctest */,
|
||||
8499D8B71D006020004B5B37 /* PreviewTransition.framework */,
|
||||
);
|
||||
name = Products;
|
||||
@@ -176,15 +144,6 @@
|
||||
path = PreviewTransitionDemo;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84204E101CB2869E001FC263 /* PreviewTransitionDemoTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84204E111CB2869E001FC263 /* PreviewTransitionDemoTests.swift */,
|
||||
84204E131CB2869E001FC263 /* Info.plist */,
|
||||
);
|
||||
path = PreviewTransitionDemoTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84204E1C1CB286DD001FC263 /* PreviewTransition */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -274,21 +233,21 @@
|
||||
path = PreivewTransition;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84A36E0C1CD88EB200AEC2F2 /* AnimationHalpers */ = {
|
||||
84A36E0C1CD88EB200AEC2F2 /* AnimationHelpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift */,
|
||||
84A36E0D1CD88EEA00AEC2F2 /* LayerAnimationHelper.swift */,
|
||||
);
|
||||
path = AnimationHalpers;
|
||||
path = AnimationHelpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84A36E111CD8C31C00AEC2F2 /* Halpers */ = {
|
||||
84A36E111CD8C31C00AEC2F2 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84A36E121CD8C32600AEC2F2 /* ScreenShot */,
|
||||
84A36E0C1CD88EB200AEC2F2 /* AnimationHalpers */,
|
||||
84A36E0C1CD88EB200AEC2F2 /* AnimationHelpers */,
|
||||
);
|
||||
name = Halpers;
|
||||
name = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84A36E121CD8C32600AEC2F2 /* ScreenShot */ = {
|
||||
@@ -321,7 +280,6 @@
|
||||
84204DF51CB2869E001FC263 /* Sources */,
|
||||
84204DF61CB2869E001FC263 /* Frameworks */,
|
||||
84204DF71CB2869E001FC263 /* Resources */,
|
||||
8485264F1CD39C880052BEAD /* image enum gen */,
|
||||
8499D8C31D006020004B5B37 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
@@ -334,24 +292,6 @@
|
||||
productReference = 84204DF91CB2869E001FC263 /* PreviewTransitionDemo.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
84204E0C1CB2869E001FC263 /* PreviewTransitionDemoTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 84204E191CB2869E001FC263 /* Build configuration list for PBXNativeTarget "PreviewTransitionDemoTests" */;
|
||||
buildPhases = (
|
||||
84204E091CB2869E001FC263 /* Sources */,
|
||||
84204E0A1CB2869E001FC263 /* Frameworks */,
|
||||
84204E0B1CB2869E001FC263 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
84204E0F1CB2869E001FC263 /* PBXTargetDependency */,
|
||||
);
|
||||
name = PreviewTransitionDemoTests;
|
||||
productName = PreviewTransitionDemoTests;
|
||||
productReference = 84204E0D1CB2869E001FC263 /* PreviewTransitionDemoTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
8499D8B61D006020004B5B37 /* PreviewTransition */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8499D8C21D006020004B5B37 /* Build configuration list for PBXNativeTarget "PreviewTransition" */;
|
||||
@@ -377,28 +317,24 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = "Alex K.";
|
||||
TargetAttributes = {
|
||||
84204DF81CB2869E001FC263 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
DevelopmentTeam = 34MUF9YXTA;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
84204E0C1CB2869E001FC263 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
TestTargetID = 84204DF81CB2869E001FC263;
|
||||
LastSwiftMigration = 1020;
|
||||
};
|
||||
8499D8B61D006020004B5B37 = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
DevelopmentTeam = LEAZS7L33U;
|
||||
LastSwiftMigration = 0800;
|
||||
LastSwiftMigration = 1020;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 84204DF41CB2869E001FC263 /* Build configuration list for PBXProject "PreviewTransitionDemo" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
@@ -410,7 +346,6 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
84204DF81CB2869E001FC263 /* PreviewTransitionDemo */,
|
||||
84204E0C1CB2869E001FC263 /* PreviewTransitionDemoTests */,
|
||||
8499D8B61D006020004B5B37 /* PreviewTransition */,
|
||||
);
|
||||
};
|
||||
@@ -427,13 +362,6 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
84204E0B1CB2869E001FC263 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8499D8B51D006020004B5B37 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -443,23 +371,6 @@
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
8485264F1CD39C880052BEAD /* image enum gen */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "image enum gen";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if which swiftgen >/dev/null; then\nswiftgen images \"$PROJECT_DIR/PreviewTransitionDemo/Assets.xcassets\" --output \"$PROJECT_DIR/Constants/Images.swift\"\nelse\necho \"warning: SwiftGen not installed, download it from https://github.com/AliSoftware/SwiftGen\"\nfi";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
84204DF51CB2869E001FC263 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
@@ -476,31 +387,11 @@
|
||||
848BD7E51CCF54620046DC13 /* ConstraintsHalper.swift in Sources */,
|
||||
84204E2B1CB289DC001FC263 /* PTTableViewController.swift in Sources */,
|
||||
84204DFD1CB2869E001FC263 /* AppDelegate.swift in Sources */,
|
||||
84A36E0E1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift in Sources */,
|
||||
84A36E0E1CD88EEA00AEC2F2 /* LayerAnimationHelper.swift in Sources */,
|
||||
84204E2F1CB28B5B001FC263 /* DemoDetailViewController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
84204E091CB2869E001FC263 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
842D7E9B1CB395C800DE59DE /* ParallaxCell.swift in Sources */,
|
||||
84204E301CB28B5B001FC263 /* DemoDetailViewController.swift in Sources */,
|
||||
842D7E9E1CB3960200DE59DE /* MovingViews.swift in Sources */,
|
||||
848526531CD39CFB0052BEAD /* Images.swift in Sources */,
|
||||
84204E121CB2869E001FC263 /* PreviewTransitionDemoTests.swift in Sources */,
|
||||
842D7E9F1CB3960A00DE59DE /* PTDetailViewController.swift in Sources */,
|
||||
84A36E151CD8C70F00AEC2F2 /* ScreenShot.swift in Sources */,
|
||||
84204E321CB28B5B001FC263 /* DemoTableViewController.swift in Sources */,
|
||||
848BD7E61CCF54620046DC13 /* ConstraintsHalper.swift in Sources */,
|
||||
8416D9EB1CB28E2600BB599D /* Extensions.swift in Sources */,
|
||||
842D7E9C1CB395D900DE59DE /* PTTableViewController.swift in Sources */,
|
||||
84A36E0F1CD88EEA00AEC2F2 /* LayerAnimationHalper.swift in Sources */,
|
||||
842D7E9D1CB395FC00DE59DE /* TimeExtensions.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
8499D8B21D006020004B5B37 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -517,11 +408,6 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
84204E0F1CB2869E001FC263 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 84204DF81CB2869E001FC263 /* PreviewTransitionDemo */;
|
||||
targetProxy = 84204E0E1CB2869E001FC263 /* PBXContainerItemProxy */;
|
||||
};
|
||||
8499D8BD1D006020004B5B37 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 8499D8B61D006020004B5B37 /* PreviewTransition */;
|
||||
@@ -553,19 +439,28 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -588,7 +483,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -600,19 +495,28 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
@@ -629,7 +533,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
@@ -651,7 +555,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.dev;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -669,31 +573,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.dev;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
84204E1A1CB2869E001FC263 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = PreviewTransitionDemoTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.PreviewTransitionDemoTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PreviewTransitionDemo.app/PreviewTransitionDemo";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
84204E1B1CB2869E001FC263 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
INFOPLIST_FILE = PreviewTransitionDemoTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.PreviewTransitionDemoTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PreviewTransitionDemo.app/PreviewTransitionDemo";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -713,8 +593,8 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.PreivewTransition;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SKIP_INSTALL = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -737,8 +617,8 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.PreivewTransition;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SKIP_INSTALL = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -766,15 +646,6 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
84204E191CB2869E001FC263 /* Build configuration list for PBXNativeTarget "PreviewTransitionDemoTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
84204E1A1CB2869E001FC263 /* Debug */,
|
||||
84204E1B1CB2869E001FC263 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8499D8C21D006020004B5B37 /* Build configuration list for PBXNativeTarget "PreviewTransition" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0800"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -11,30 +11,26 @@ import UIKit
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
var window: UIWindow?
|
||||
|
||||
func applicationDidFinishLaunching(_ application: UIApplication) {
|
||||
|
||||
configureNavigationBar()
|
||||
}
|
||||
|
||||
func applicationDidFinishLaunching(_: UIApplication) {
|
||||
configureNavigationBar()
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate {
|
||||
|
||||
fileprivate func configureNavigationBar() {
|
||||
//transparent background
|
||||
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
|
||||
UINavigationBar.appearance().shadowImage = UIImage()
|
||||
UINavigationBar.appearance().isTranslucent = true
|
||||
|
||||
|
||||
if let font = UIFont(name: "Avenir-medium" , size: 18) {
|
||||
UINavigationBar.appearance().titleTextAttributes = [
|
||||
NSForegroundColorAttributeName : UIColor.white,
|
||||
NSFontAttributeName : font
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func configureNavigationBar() {
|
||||
//transparent background
|
||||
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
|
||||
UINavigationBar.appearance().shadowImage = UIImage()
|
||||
UINavigationBar.appearance().isTranslucent = true
|
||||
|
||||
if let font = UIFont(name: "Avenir-medium", size: 18) {
|
||||
UINavigationBar.appearance().titleTextAttributes = [
|
||||
NSAttributedString.Key.foregroundColor: UIColor.white,
|
||||
NSAttributedString.Key.font: font,
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,119 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-60.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-58.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-87.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-80.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-120.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-120.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon-180.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-20.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-29.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-58.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-40.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-80.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-76.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-152.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon-167.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Ramotion.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"pre-rendered" : true
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 475 B |
|
After Width: | Height: | Size: 620 B |
|
After Width: | Height: | Size: 792 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -1,8 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
@@ -14,14 +19,35 @@
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2018 Ramotion. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fcf-sN-ku0">
|
||||
<rect key="frame" x="16" y="630" width="343" height="17"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Preview Transition" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bCd-3b-lHA">
|
||||
<rect key="frame" x="111.5" y="323" width="152" height="21"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="fcf-sN-ku0" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leadingMargin" id="811-hI-Egq"/>
|
||||
<constraint firstItem="bCd-3b-lHA" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="T4x-O3-JqD"/>
|
||||
<constraint firstItem="bCd-3b-lHA" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="VFr-tp-sPw"/>
|
||||
<constraint firstItem="fcf-sN-ku0" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailingMargin" id="dS9-pv-ebe"/>
|
||||
<constraint firstItem="xb3-aO-Qok" firstAttribute="top" secondItem="fcf-sN-ku0" secondAttribute="bottom" constant="20" id="kbD-dX-t3N"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
<point key="canvasLocation" x="52" y="374.66266866566718"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="rNz-sP-Qod">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="rNz-sP-Qod">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<customFonts key="customFonts">
|
||||
<array key="Avenir.ttc">
|
||||
<string>Avenir-Medium</string>
|
||||
</array>
|
||||
</customFonts>
|
||||
<scenes>
|
||||
<!--Demo Table View Controller-->
|
||||
<scene sceneID="TS0-JK-FG8">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="DemoTableViewController" id="R4r-KK-4wR" customClass="DemoTableViewController" customModule="PreviewTransitionDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="240" sectionHeaderHeight="28" sectionFooterHeight="28" id="bOE-4i-fSR">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="240" sectionHeaderHeight="28" sectionFooterHeight="28" id="bOE-4i-fSR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ParallaxCell" id="AII-q7-Txi" customClass="ParallaxCell" customModule="PreviewTransitionDemo" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="92" width="375" height="240"/>
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="240"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="AII-q7-Txi" id="dOL-VB-4JN">
|
||||
<frame key="frameInset" width="375" height="239"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="239.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
@@ -48,63 +57,80 @@
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<view key="view" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bep-Nt-aTe" userLabel="BottomView">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e87-Lw-D6d" userLabel="ControlsViewContainer">
|
||||
<rect key="frame" x="0.0" y="592" width="375" height="75"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="PlusIcon" translatesAutoresizingMaskIntoConstraints="NO" id="cNu-DQ-KVS">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bep-Nt-aTe" userLabel="ControlsView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="75"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="PlusIcon" translatesAutoresizingMaskIntoConstraints="NO" id="cNu-DQ-KVS">
|
||||
<rect key="frame" x="26" y="23.5" width="28" height="28"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="28" id="Oez-4a-Ajf"/>
|
||||
<constraint firstAttribute="height" constant="28" id="dVU-d2-hQD"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UPLOAD" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="of2-Mb-6dK">
|
||||
<rect key="frame" x="72" y="26.5" width="65.5" height="22"/>
|
||||
<fontDescription key="fontDescription" name="Avenir-Medium" family="Avenir" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="HertIcon" translatesAutoresizingMaskIntoConstraints="NO" id="qf5-7H-m8I">
|
||||
<rect key="frame" x="329" y="27.5" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="20" id="7vC-Kj-Xhh"/>
|
||||
<constraint firstAttribute="height" constant="20" id="y9j-Rr-ADZ"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShareIcon" translatesAutoresizingMaskIntoConstraints="NO" id="fYq-Bm-C3g">
|
||||
<rect key="frame" x="278" y="27.5" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="20" id="AdG-0M-DE8"/>
|
||||
<constraint firstAttribute="height" constant="20" id="npa-OF-Phw"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.2418571412563324" green="0.17698898911476135" blue="0.1230514720082283" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="28" id="Oez-4a-Ajf"/>
|
||||
<constraint firstAttribute="height" constant="28" id="dVU-d2-hQD"/>
|
||||
<constraint firstItem="qf5-7H-m8I" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="7Sl-Yf-TPT"/>
|
||||
<constraint firstItem="qf5-7H-m8I" firstAttribute="leading" secondItem="fYq-Bm-C3g" secondAttribute="trailing" constant="31" id="CbF-3f-1Rz"/>
|
||||
<constraint firstItem="fYq-Bm-C3g" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="Q7R-nz-kDO"/>
|
||||
<constraint firstItem="cNu-DQ-KVS" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="VSr-aL-49x"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qf5-7H-m8I" secondAttribute="trailing" constant="26" id="dyM-CD-2Xy"/>
|
||||
<constraint firstItem="of2-Mb-6dK" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="ndt-gV-UNC"/>
|
||||
<constraint firstItem="cNu-DQ-KVS" firstAttribute="leading" secondItem="bep-Nt-aTe" secondAttribute="leading" constant="26" id="sM2-by-tp2"/>
|
||||
<constraint firstItem="of2-Mb-6dK" firstAttribute="leading" secondItem="cNu-DQ-KVS" secondAttribute="trailing" constant="18" id="u48-EN-PaD"/>
|
||||
<constraint firstAttribute="height" constant="75" id="y5q-xC-6PW"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="UPLOAD" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="of2-Mb-6dK">
|
||||
<fontDescription key="fontDescription" name="Avenir-Medium" family="Avenir" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="HertIcon" translatesAutoresizingMaskIntoConstraints="NO" id="qf5-7H-m8I">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="29" id="7vC-Kj-Xhh"/>
|
||||
<constraint firstAttribute="height" constant="29" id="y9j-Rr-ADZ"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" alpha="0.65000000000000002" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShareIcon" translatesAutoresizingMaskIntoConstraints="NO" id="fYq-Bm-C3g">
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="29" id="AdG-0M-DE8"/>
|
||||
<constraint firstAttribute="height" constant="29" id="npa-OF-Phw"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.2418571412563324" green="0.17698898911476135" blue="0.1230514720082283" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="qf5-7H-m8I" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="7Sl-Yf-TPT"/>
|
||||
<constraint firstItem="qf5-7H-m8I" firstAttribute="leading" secondItem="fYq-Bm-C3g" secondAttribute="trailing" constant="31" id="CbF-3f-1Rz"/>
|
||||
<constraint firstItem="fYq-Bm-C3g" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="Q7R-nz-kDO"/>
|
||||
<constraint firstItem="cNu-DQ-KVS" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="VSr-aL-49x"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qf5-7H-m8I" secondAttribute="trailing" constant="26" id="dyM-CD-2Xy"/>
|
||||
<constraint firstItem="of2-Mb-6dK" firstAttribute="centerY" secondItem="bep-Nt-aTe" secondAttribute="centerY" id="ndt-gV-UNC"/>
|
||||
<constraint firstItem="cNu-DQ-KVS" firstAttribute="leading" secondItem="bep-Nt-aTe" secondAttribute="leading" constant="26" id="sM2-by-tp2"/>
|
||||
<constraint firstItem="of2-Mb-6dK" firstAttribute="leading" secondItem="cNu-DQ-KVS" secondAttribute="trailing" constant="18" id="u48-EN-PaD"/>
|
||||
<constraint firstAttribute="height" constant="75" id="y5q-xC-6PW"/>
|
||||
<constraint firstItem="bep-Nt-aTe" firstAttribute="top" secondItem="e87-Lw-D6d" secondAttribute="top" id="AQh-Mt-Zu0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bep-Nt-aTe" secondAttribute="trailing" id="R5F-Ml-C1h"/>
|
||||
<constraint firstItem="bep-Nt-aTe" firstAttribute="leading" secondItem="e87-Lw-D6d" secondAttribute="leading" id="e33-px-zT6"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="bep-Nt-aTe" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="HoE-lK-c1w"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="bep-Nt-aTe" secondAttribute="bottom" id="Ye7-fc-GvE"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bep-Nt-aTe" secondAttribute="trailing" id="fVz-GY-Jz2"/>
|
||||
<constraint firstItem="e87-Lw-D6d" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="WtK-eJ-Evt"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e87-Lw-D6d" secondAttribute="trailing" id="Xfw-qN-wKE"/>
|
||||
<constraint firstAttribute="bottom" secondItem="e87-Lw-D6d" secondAttribute="bottom" id="Z1u-Zc-6Gx"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="bep-Nt-aTe" secondAttribute="bottom" id="qoN-F2-pl4"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="controlBottomConstrant" destination="Ye7-fc-GvE" id="Z4z-3v-JPd"/>
|
||||
<outlet property="controlHeightConstraint" destination="y5q-xC-6PW" id="bj2-EN-9sN"/>
|
||||
<outlet property="controlBottomConstrant" destination="qoN-F2-pl4" id="7vP-GT-O7y"/>
|
||||
<outlet property="controlTextLabel" destination="of2-Mb-6dK" id="8VW-Qx-njJ"/>
|
||||
<outlet property="controlTextLableLending" destination="u48-EN-PaD" id="THf-Gf-6Oe"/>
|
||||
<outlet property="controlView" destination="bep-Nt-aTe" id="lB6-d4-1rx"/>
|
||||
<outlet property="controlsViewContainer" destination="e87-Lw-D6d" id="vqd-db-r0q"/>
|
||||
<outlet property="hertIconView" destination="qf5-7H-m8I" id="LUd-B6-aY7"/>
|
||||
<outlet property="plusImageView" destination="cNu-DQ-KVS" id="xQY-UZ-Bve"/>
|
||||
<outlet property="shareImageView" destination="fYq-Bm-C3g" id="mW0-7l-wPb"/>
|
||||
@@ -112,7 +138,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1609" y="484"/>
|
||||
<point key="canvasLocation" x="1608.8" y="483.50824587706148"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="cXS-jQ-bIr">
|
||||
@@ -121,7 +147,7 @@
|
||||
<toolbarItems/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="crh-l4-DmE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textAttributes key="titleTextAttributes">
|
||||
<color key="textColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
|
||||
@@ -26,65 +26,64 @@ import UIKit
|
||||
// MARK: tableview
|
||||
|
||||
extension UITableView {
|
||||
func getReusableCellWithIdentifier<T: UITableViewCell>(indexPath: IndexPath) -> T where T: TableViewCellIdentifiable {
|
||||
guard let cell = self.dequeueReusableCell(withIdentifier: T.cellIdentifier, for: indexPath as IndexPath) as? T else {
|
||||
fatalError("Couldn't instantiate view controller with identifier \(T.cellIdentifier) ")
|
||||
func getReusableCellWithIdentifier<T: UITableViewCell>(indexPath: IndexPath) -> T {
|
||||
guard let cell = self.dequeueReusableCell(withIdentifier: T.cellIdentifier, for: indexPath as IndexPath) as? T else {
|
||||
fatalError("Couldn't instantiate view controller with identifier \(T.cellIdentifier) ")
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UITableViewCell
|
||||
|
||||
protocol TableViewCellIdentifiable {
|
||||
static var cellIdentifier: String { get }
|
||||
static var cellIdentifier: String { get }
|
||||
}
|
||||
|
||||
extension TableViewCellIdentifiable where Self: UITableViewCell {
|
||||
static var cellIdentifier: String {
|
||||
return String(describing: self)
|
||||
}
|
||||
static var cellIdentifier: String {
|
||||
return String(describing: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension UITableViewCell : TableViewCellIdentifiable { }
|
||||
|
||||
extension UITableViewCell: TableViewCellIdentifiable {}
|
||||
|
||||
// MARK: storyboard
|
||||
|
||||
extension UIStoryboard {
|
||||
|
||||
enum Storyboard : String {
|
||||
case Main
|
||||
}
|
||||
|
||||
convenience init(storyboard: Storyboard, bundle: Bundle? = nil) {
|
||||
self.init(name: storyboard.rawValue, bundle: bundle)
|
||||
}
|
||||
|
||||
class func storyboard(storyboard: Storyboard, bundle: Bundle? = nil) -> UIStoryboard {
|
||||
return UIStoryboard(name: storyboard.rawValue, bundle: bundle)
|
||||
}
|
||||
|
||||
func instantiateViewController<T: UIViewController>() -> T where T: StoryboardIdentifiable {
|
||||
guard let viewController = self.instantiateViewController(withIdentifier: T.storyboardIdentifier) as? T else {
|
||||
fatalError("Couldn't instantiate view controller with identifier \(T.storyboardIdentifier) ")
|
||||
|
||||
enum Storyboard: String {
|
||||
case Main
|
||||
}
|
||||
|
||||
convenience init(storyboard: Storyboard, bundle: Bundle? = nil) {
|
||||
self.init(name: storyboard.rawValue, bundle: bundle)
|
||||
}
|
||||
|
||||
class func storyboard(storyboard: Storyboard, bundle: Bundle? = nil) -> UIStoryboard {
|
||||
return UIStoryboard(name: storyboard.rawValue, bundle: bundle)
|
||||
}
|
||||
|
||||
func instantiateViewController<T: UIViewController>() -> T {
|
||||
guard let viewController = self.instantiateViewController(withIdentifier: T.storyboardIdentifier) as? T else {
|
||||
fatalError("Couldn't instantiate view controller with identifier \(T.storyboardIdentifier) ")
|
||||
}
|
||||
|
||||
return viewController
|
||||
}
|
||||
|
||||
return viewController
|
||||
}
|
||||
}
|
||||
|
||||
extension UIViewController : StoryboardIdentifiable { }
|
||||
extension UIViewController: StoryboardIdentifiable {}
|
||||
|
||||
// MARK: identifiable
|
||||
|
||||
protocol StoryboardIdentifiable {
|
||||
static var storyboardIdentifier: String { get }
|
||||
static var storyboardIdentifier: String { get }
|
||||
}
|
||||
|
||||
extension StoryboardIdentifiable where Self: UIViewController {
|
||||
static var storyboardIdentifier: String {
|
||||
return String(describing: self)
|
||||
}
|
||||
static var storyboardIdentifier: String {
|
||||
return String(describing: self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,157 +21,150 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
import UIKit
|
||||
|
||||
public class DemoDetailViewController: PTDetailViewController {
|
||||
|
||||
@IBOutlet weak var controlHeightConstraint: NSLayoutConstraint!
|
||||
@IBOutlet weak var controlBottomConstrant: NSLayoutConstraint!
|
||||
|
||||
// bottom control icons
|
||||
@IBOutlet weak var controlView: UIView!
|
||||
@IBOutlet weak var plusImageView: UIImageView!
|
||||
@IBOutlet weak var controlTextLabel: UILabel!
|
||||
@IBOutlet weak var controlTextLableLending: NSLayoutConstraint!
|
||||
@IBOutlet weak var shareImageView: UIImageView!
|
||||
@IBOutlet weak var hertIconView: UIImageView!
|
||||
|
||||
var backButton: UIButton?
|
||||
|
||||
@IBOutlet var controlBottomConstrant: NSLayoutConstraint!
|
||||
|
||||
// bottom control icons
|
||||
@IBOutlet var controlsViewContainer: UIView!
|
||||
@IBOutlet var controlView: UIView!
|
||||
@IBOutlet var plusImageView: UIImageView!
|
||||
@IBOutlet var controlTextLabel: UILabel!
|
||||
@IBOutlet var controlTextLableLending: NSLayoutConstraint!
|
||||
@IBOutlet var shareImageView: UIImageView!
|
||||
@IBOutlet var hertIconView: UIImageView!
|
||||
|
||||
var backButton: UIButton?
|
||||
|
||||
var bottomSafeArea: CGFloat {
|
||||
var result: CGFloat = 0
|
||||
if #available(iOS 11.0, *) {
|
||||
result = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: life cicle
|
||||
|
||||
extension DemoDetailViewController {
|
||||
|
||||
public override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
backButton = createBackButton()
|
||||
let _ = createNavigationBarBackItem(button: backButton)
|
||||
|
||||
// animations
|
||||
showBackButtonDuration(duration: 0.3)
|
||||
showControlViewDuration(duration: 0.3)
|
||||
|
||||
let _ = createBlurView()
|
||||
}
|
||||
|
||||
public override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
backButton = createBackButton()
|
||||
_ = createNavigationBarBackItem(button: backButton)
|
||||
|
||||
// animations
|
||||
showBackButtonDuration(duration: 0.3)
|
||||
showControlViewDuration(duration: 0.3)
|
||||
|
||||
_ = createBlurView()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: helpers
|
||||
|
||||
extension DemoDetailViewController {
|
||||
|
||||
fileprivate func createBackButton() -> UIButton {
|
||||
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 22, height: 44))
|
||||
button.setImage(UIImage.Asset.Back.image, for: .normal)
|
||||
button.addTarget(self, action: #selector(DemoDetailViewController.backButtonHandler) , for: .touchUpInside)
|
||||
return button
|
||||
}
|
||||
|
||||
fileprivate func createNavigationBarBackItem(button: UIButton?) -> UIBarButtonItem? {
|
||||
guard let button = button else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let buttonItem = UIBarButtonItem(customView: button)
|
||||
navigationItem.leftBarButtonItem = buttonItem
|
||||
return buttonItem
|
||||
}
|
||||
|
||||
fileprivate func createBlurView() -> UIView {
|
||||
let imageFrame = CGRect(x: 0, y: view.frame.size.height - controlHeightConstraint.constant, width: view.frame.width, height: controlHeightConstraint.constant)
|
||||
let image = view.makeScreenShotFromFrame(frame: imageFrame)
|
||||
let screnShotImageView = UIImageView(image: image)
|
||||
screnShotImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
screnShotImageView.blurViewValue(value: 5)
|
||||
controlView.insertSubview(screnShotImageView, at: 0)
|
||||
// added constraints
|
||||
[NSLayoutAttribute.left, .right, .bottom, .top].forEach { attribute in
|
||||
(self.controlView, screnShotImageView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createMaskView(onView: screnShotImageView)
|
||||
|
||||
return screnShotImageView
|
||||
}
|
||||
|
||||
fileprivate func createMaskView(onView: UIView) {
|
||||
let blueView = UIView(frame: CGRect.zero)
|
||||
blueView.backgroundColor = .black
|
||||
blueView.translatesAutoresizingMaskIntoConstraints = false
|
||||
blueView.alpha = 0.4
|
||||
onView.addSubview(blueView)
|
||||
|
||||
// add constraints
|
||||
[NSLayoutAttribute.left, .right, .bottom, .top].forEach { attribute in
|
||||
(onView, blueView) >>>- {
|
||||
$0.attribute = attribute
|
||||
return
|
||||
}
|
||||
fileprivate func createBackButton() -> UIButton {
|
||||
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 22, height: 44))
|
||||
button.setImage(UIImage.Asset.Back.image, for: .normal)
|
||||
button.addTarget(self, action: #selector(DemoDetailViewController.backButtonHandler), for: .touchUpInside)
|
||||
return button
|
||||
}
|
||||
|
||||
fileprivate func createNavigationBarBackItem(button: UIButton?) -> UIBarButtonItem? {
|
||||
guard let button = button else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let buttonItem = UIBarButtonItem(customView: button)
|
||||
navigationItem.leftBarButtonItem = buttonItem
|
||||
return buttonItem
|
||||
}
|
||||
|
||||
fileprivate func createBlurView() -> UIView {
|
||||
let height = controlView.bounds.height + bottomSafeArea
|
||||
let imageFrame = CGRect(x: 0, y: view.frame.size.height - height, width: view.frame.width, height: height)
|
||||
let image = view.makeScreenShotFromFrame(frame: imageFrame)
|
||||
let screnShotImageView = UIImageView(image: image)
|
||||
screnShotImageView.blurViewValue(value: 5)
|
||||
screnShotImageView.frame = controlsViewContainer.bounds
|
||||
screnShotImageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
controlsViewContainer.insertSubview(screnShotImageView, at: 0)
|
||||
addOverlay(toView: screnShotImageView)
|
||||
return screnShotImageView
|
||||
}
|
||||
|
||||
fileprivate func addOverlay(toView view: UIView) {
|
||||
let overlayView = UIView(frame: view.bounds)
|
||||
overlayView.backgroundColor = .black
|
||||
overlayView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
overlayView.alpha = 0.4
|
||||
view.addSubview(overlayView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: animations
|
||||
|
||||
extension DemoDetailViewController {
|
||||
|
||||
fileprivate func showBackButtonDuration(duration: Double) {
|
||||
backButton?.rotateDuration(duration: duration, from: CGFloat(-M_PI_4), to: 0)
|
||||
backButton?.scaleDuration(duration: duration, from: 0.5, to: 1)
|
||||
backButton?.opacityDuration(duration: duration, from: 0, to: 1)
|
||||
}
|
||||
|
||||
fileprivate func showControlViewDuration(duration: Double) {
|
||||
moveUpControllerDuration(duration: duration)
|
||||
showControlButtonsDuration(duration: duration)
|
||||
showControlLabelDuration(duration: duration)
|
||||
}
|
||||
|
||||
fileprivate func moveUpControllerDuration(duration: Double) {
|
||||
controlBottomConstrant.constant = -controlHeightConstraint.constant
|
||||
view.layoutIfNeeded()
|
||||
|
||||
controlBottomConstrant.constant = 0
|
||||
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
fileprivate func showControlButtonsDuration(duration: Double) {
|
||||
[plusImageView, shareImageView, hertIconView].forEach {
|
||||
$0?.rotateDuration(duration: duration, from: CGFloat(-M_PI_4), to: 0, delay: duration)
|
||||
$0?.scaleDuration(duration: duration, from: 0.5, to: 1, delay: duration)
|
||||
$0?.alpha = 0
|
||||
$0?.opacityDuration(duration: duration, from: 0, to: 1, delay: duration, remove: false)
|
||||
fileprivate func showBackButtonDuration(duration: Double) {
|
||||
backButton?.rotateDuration(duration: duration, from: -CGFloat.pi / 4, to: 0)
|
||||
backButton?.scaleDuration(duration: duration, from: 0.5, to: 1)
|
||||
backButton?.opacityDuration(duration: duration, from: 0, to: 1)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func showControlLabelDuration(duration: Double) {
|
||||
controlTextLabel.alpha = 0
|
||||
controlTextLabel.opacityDuration(duration: duration, from: 0, to: 1, delay: duration, remove: false)
|
||||
|
||||
// move rigth
|
||||
let offSet: CGFloat = 20
|
||||
controlTextLableLending.constant -= offSet
|
||||
view.layoutIfNeeded()
|
||||
|
||||
controlTextLableLending.constant += offSet
|
||||
UIView.animate(withDuration: duration * 2, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
fileprivate func showControlViewDuration(duration: Double) {
|
||||
moveUpControllerDuration(duration: duration)
|
||||
showControlButtonsDuration(duration: duration)
|
||||
showControlLabelDuration(duration: duration)
|
||||
}
|
||||
|
||||
fileprivate func moveUpControllerDuration(duration: Double) {
|
||||
|
||||
controlBottomConstrant.constant = -controlsViewContainer.bounds.height
|
||||
view.layoutIfNeeded()
|
||||
|
||||
controlBottomConstrant.constant = 0
|
||||
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
fileprivate func showControlButtonsDuration(duration: Double) {
|
||||
[plusImageView, shareImageView, hertIconView].forEach {
|
||||
$0?.rotateDuration(duration: duration, from: CGFloat.pi / 4, to: 0, delay: duration)
|
||||
$0?.scaleDuration(duration: duration, from: 0.5, to: 1, delay: duration)
|
||||
$0?.alpha = 0
|
||||
$0?.opacityDuration(duration: duration, from: 0, to: 1, delay: duration, remove: false)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func showControlLabelDuration(duration: Double) {
|
||||
controlTextLabel.alpha = 0
|
||||
controlTextLabel.opacityDuration(duration: duration, from: 0, to: 1, delay: duration, remove: false)
|
||||
|
||||
// move rigth
|
||||
let offSet: CGFloat = 20
|
||||
controlTextLableLending.constant -= offSet
|
||||
view.layoutIfNeeded()
|
||||
|
||||
controlTextLableLending.constant += offSet
|
||||
UIView.animate(withDuration: duration * 2, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: actions
|
||||
|
||||
extension DemoDetailViewController {
|
||||
|
||||
func backButtonHandler() {
|
||||
popViewController()
|
||||
}
|
||||
|
||||
@objc func backButtonHandler() {
|
||||
popViewController()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,38 +24,38 @@
|
||||
import UIKit
|
||||
|
||||
public class DemoTableViewController: PTTableViewController {
|
||||
|
||||
fileprivate let items = [("1", "River cruise"), ("2", "North Island"), ("3", "Mountain trail"), ("4", "Southern Coast"), ("5", "Fishing place")] // image names
|
||||
|
||||
fileprivate let items = [("1", "River cruise"), ("2", "North Island"), ("3", "Mountain trail"), ("4", "Southern Coast"), ("5", "Fishing place")] // image names
|
||||
}
|
||||
|
||||
// MARK: UITableViewDelegate
|
||||
extension DemoTableViewController {
|
||||
|
||||
public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 100
|
||||
}
|
||||
|
||||
public override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
guard let cell = cell as? ParallaxCell else { return }
|
||||
|
||||
let index = indexPath.row % items.count
|
||||
let imageName = items[index].0
|
||||
let title = items[index].1
|
||||
|
||||
if let image = UIImage(named: imageName) {
|
||||
cell.setImage(image, title: title)
|
||||
}
|
||||
}
|
||||
|
||||
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell: ParallaxCell = tableView.getReusableCellWithIdentifier(indexPath: indexPath)
|
||||
return cell
|
||||
}
|
||||
|
||||
public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let storyboard = UIStoryboard.storyboard(storyboard: .Main)
|
||||
let detaleViewController: DemoDetailViewController = storyboard.instantiateViewController()
|
||||
pushViewController(detaleViewController)
|
||||
}
|
||||
|
||||
extension DemoTableViewController {
|
||||
|
||||
public override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
|
||||
return 100
|
||||
}
|
||||
|
||||
public override func tableView(_: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
guard let cell = cell as? ParallaxCell else { return }
|
||||
|
||||
let index = indexPath.row % items.count
|
||||
let imageName = items[index].0
|
||||
let title = items[index].1
|
||||
|
||||
if let image = UIImage(named: imageName) {
|
||||
cell.setImage(image, title: title)
|
||||
}
|
||||
}
|
||||
|
||||
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell: ParallaxCell = tableView.getReusableCellWithIdentifier(indexPath: indexPath)
|
||||
return cell
|
||||
}
|
||||
|
||||
public override func tableView(_: UITableView, didSelectRowAt _: IndexPath) {
|
||||
let storyboard = UIStoryboard.storyboard(storyboard: .Main)
|
||||
let detaleViewController: DemoDetailViewController = storyboard.instantiateViewController()
|
||||
pushViewController(detaleViewController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,30 +0,0 @@
|
||||
//
|
||||
// PreviewTransitionDemoTests.swift
|
||||
// PreviewTransitionDemoTests
|
||||
//
|
||||
// Created by Alex K. on 04/04/16.
|
||||
// Copyright © 2016 Alex K. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import PreviewTransitionDemo
|
||||
|
||||
class PreviewTransitionDemoTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
self.measureBlock {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,43 +9,41 @@
|
||||
import UIKit
|
||||
|
||||
extension UIView {
|
||||
|
||||
func makeScreenShotFromFrame(frame: CGRect) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0)
|
||||
|
||||
let context = UIGraphicsGetCurrentContext();
|
||||
context!.translateBy(x: frame.origin.x * -1, y: frame.origin.y * -1)
|
||||
|
||||
guard let currentContext = UIGraphicsGetCurrentContext() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.layer.render(in: currentContext)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
func makeScreenShotFromFrame(frame: CGRect) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0)
|
||||
|
||||
let context = UIGraphicsGetCurrentContext()
|
||||
context!.translateBy(x: frame.origin.x * -1, y: frame.origin.y * -1)
|
||||
|
||||
guard let currentContext = UIGraphicsGetCurrentContext() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
layer.render(in: currentContext)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
extension UIImageView {
|
||||
|
||||
func blurViewValue(value: CGFloat) {
|
||||
guard let image = self.image,
|
||||
let blurfilter = CIFilter(name: "CIGaussianBlur"),
|
||||
let imageToBlur = CIImage(image: image)
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
blurfilter.setValue(value, forKey: kCIInputRadiusKey)
|
||||
blurfilter.setValue(imageToBlur, forKey: "inputImage")
|
||||
let resultImage = blurfilter.value(forKey: "outputImage") as! CIImage
|
||||
var blurredImage = UIImage(ciImage: resultImage)
|
||||
let cropped:CIImage=resultImage.cropping(to: CGRect(x: 0, y: 0, width: imageToBlur.extent.size.width, height: imageToBlur.extent.size.height))
|
||||
blurredImage = UIImage(ciImage: cropped)
|
||||
self.image = blurredImage
|
||||
}
|
||||
|
||||
func blurViewValue(value: CGFloat) {
|
||||
guard let image = self.image,
|
||||
let blurfilter = CIFilter(name: "CIGaussianBlur"),
|
||||
let imageToBlur = CIImage(image: image)
|
||||
else {
|
||||
return
|
||||
}
|
||||
|
||||
blurfilter.setValue(value, forKey: kCIInputRadiusKey)
|
||||
blurfilter.setValue(imageToBlur, forKey: "inputImage")
|
||||
let resultImage = blurfilter.value(forKey: "outputImage") as! CIImage
|
||||
var blurredImage = UIImage(ciImage: resultImage)
|
||||
let cropped: CIImage = resultImage.cropped(to: CGRect(x: 0, y: 0, width: imageToBlur.extent.size.width, height: imageToBlur.extent.size.height))
|
||||
blurredImage = UIImage(ciImage: cropped)
|
||||
self.image = blurredImage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,50 @@
|
||||
[](https://business.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=preview-transition-logo)
|
||||
# Preview-transition [](http://twitter.com/Ramotion)
|
||||
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=preview-transition"><img src="https://github.com/Ramotion/folding-cell/blob/master/header.png"></a>
|
||||
|
||||
<a href="https://github.com/Ramotion/fpreview-transition">
|
||||
<img align="left" src="https://github.com/Ramotion/preview-transition/blob/master/preview-transition.gif" width="480" height="360" /></a>
|
||||
|
||||
<p><h1 align="left">PREVIEW TRANSITION</h1></p>
|
||||
|
||||
<h4>Preview Transition is a simple preview gallery UI controller with animated tranisitions</h4>
|
||||
|
||||
|
||||
___
|
||||
|
||||
|
||||
|
||||
<p><h6>We specialize in the designing and coding of custom UI for Mobile Apps and Websites.</h6>
|
||||
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=preview-transition">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
|
||||
</p>
|
||||
<p><h6>Stay tuned for the latest updates:</h6>
|
||||
<a href="https://goo.gl/rPFpid" >
|
||||
<img src="https://i.imgur.com/ziSqeSo.png/" width="156" height="28"></a></p>
|
||||
|
||||
</br>
|
||||
|
||||
[](http://twitter.com/Ramotion)
|
||||
[](https://travis-ci.org/Ramotion/preview-transition.svg?branch=master)
|
||||
[](https://github.com/Ramotion/preview-transition)
|
||||
[](https://cocoapods.org/pods/PreviewTransition)
|
||||
[](http://cocoapods.org/pods/PreviewTransition)
|
||||
[](https://cdn.rawgit.com/Ramotion/preview-transition/master/docs/index.html)
|
||||
[](https://codebeat.co/projects/github-com-ramotion-preview-transition)
|
||||
[](https://paypal.me/Ramotion)
|
||||
|
||||
|
||||
## About
|
||||
This project is maintained by Ramotion, an agency specialized in building dedicated engineering teams and developing custom software.<br><br> [Contact our team](https://business.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=preview-transition-contact-us) and we’ll help you work with the best engineers from Eastern Europe.
|
||||
This project is maintained by Ramotion, Inc.<br>
|
||||
We specialize in the designing and coding of custom UI for Mobile Apps and Websites.<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://dribbble.com/shots/2724735-iOS-Preview-Transition-Open-Source"><img src="https://raw.githubusercontent.com/Ramotion/preview-transition/master/preview.gif" width="890" height="668" alt="StackViewController Example App" /></a>
|
||||
</p>
|
||||
|
||||
The [iPhone mockup](https://store.ramotion.com/product/iphone-6-mockups?utm_source=gthb&utm_medium=special&utm_campaign=preview-transition) available [here](https://store.ramotion.com/product/iphone-6-mockups?utm_source=gthb&utm_medium=special&utm_campaign=preview-transition).
|
||||
**Looking for developers for your project?**<br>
|
||||
This project is maintained by Ramotion, Inc. We specialize in the designing and coding of custom UI for Mobile Apps and Websites.
|
||||
|
||||
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=preview-transition">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a> <br>
|
||||
|
||||
## Requirements
|
||||
|
||||
- iOS 8.0+
|
||||
- Xcode 7.3
|
||||
- iOS 9.0+
|
||||
- Xcode 9
|
||||
|
||||
## Licence
|
||||
|
||||
@@ -31,16 +55,13 @@ See [LICENSE](./LICENSE) for details.
|
||||
|
||||
Just add the Source folder to your project or use [CocoaPods](https://cocoapods.org) like this:
|
||||
``` ruby
|
||||
pod "PreviewTransition", "~> 2.0.0" swift 3
|
||||
|
||||
pod "PreviewTransition", "~> 1.1.5" swift 2
|
||||
pod "PreviewTransition"
|
||||
```
|
||||
|
||||
or [Carthage](https://github.com/Carthage/Carthage) users can simply add to their `Cartfile`:
|
||||
```
|
||||
github "Ramotion/preview-transition"
|
||||
|
||||
github "Ramotion/preview-transition"
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -138,7 +159,22 @@ if let font = UIFont(name: <Font name> , size: 18) {
|
||||
}
|
||||
```
|
||||
|
||||
## Follow us
|
||||
## 📄 License
|
||||
|
||||
[](https://twitter.com/intent/tweet?text=https://github.com/ramotion/preview-transition)
|
||||
[](https://twitter.com/ramotion)
|
||||
Preview Transition is released under the MIT license.
|
||||
See [LICENSE](./LICENSE) for details.
|
||||
|
||||
This library is a part of a <a href="https://github.com/Ramotion/swift-ui-animation-components-and-libraries"><b>selection of our best UI open-source projects.</b></a>
|
||||
|
||||
If you use the open-source library in your project, please make sure to credit and backlink to https://www.ramotion.com/
|
||||
|
||||
## 📱 Get the Showroom App for iOS to give it a try
|
||||
Try this UI component and more like this in our iOS app. Contact us if interested.
|
||||
|
||||
<a href="https://itunes.apple.com/app/apple-store/id1182360240?pt=550053&ct=preview-transition&mt=8" >
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/app_store@2x.png" width="117" height="34"></a>
|
||||
|
||||
<a href="https://www.ramotion.com/agency/app-development/?utm_source=gthb&utm_medium=repo&utm_campaign=preview-transition">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
|
After Width: | Height: | Size: 13 MiB |