Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc52176452 | ||
|
|
259e726146 | ||
|
|
381fe89df9 | ||
|
|
99d7b642c9 | ||
|
|
d5aa310bd6 | ||
|
|
df05fb3424 | ||
|
|
f144e16433 | ||
|
|
c9c710f485 | ||
|
|
49611acdf9 | ||
|
|
283afd04b2 | ||
|
|
7cf93be5b7 | ||
|
|
ae01474fa4 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'FoldingCell'
|
||||
s.version = '3.0.2'
|
||||
s.version = '3.0.3'
|
||||
s.summary = 'UITableViewCell with folding animation.'
|
||||
s.homepage = 'https://github.com/Ramotion/folding-cell'
|
||||
s.license = 'MIT'
|
||||
|
||||
@@ -305,7 +305,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 0800;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = "Alex K.";
|
||||
TargetAttributes = {
|
||||
8498513B1C5639F9006FA400 = {
|
||||
@@ -322,6 +322,7 @@
|
||||
9D57F31B1EDC7A6F0004599F = {
|
||||
CreatedOnToolsVersion = 8.3.2;
|
||||
DevelopmentTeam = 34MUF9YXTA;
|
||||
LastSwiftMigration = 0920;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
9DAA51531EDDBAD700DFC539 = {
|
||||
@@ -485,14 +486,20 @@
|
||||
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_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_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;
|
||||
@@ -531,14 +538,20 @@
|
||||
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_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_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;
|
||||
@@ -666,7 +679,8 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -687,7 +701,8 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "ramotion.com.FoldingCell-Demo";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -25,27 +25,27 @@ import UIKit
|
||||
|
||||
/// UITableViewCell with folding animation
|
||||
open class FoldingCell: UITableViewCell {
|
||||
|
||||
|
||||
/// UIView whitch display when cell open
|
||||
@IBOutlet open var containerView: UIView!
|
||||
@IBOutlet open var containerViewTop: NSLayoutConstraint!
|
||||
|
||||
|
||||
/// UIView whitch display when cell close
|
||||
@IBOutlet open var foregroundView: RotatedView!
|
||||
@IBOutlet open var foregroundViewTop: NSLayoutConstraint!
|
||||
var animationView: UIView?
|
||||
|
||||
|
||||
/// the number of folding elements. Default 2
|
||||
@IBInspectable open var itemCount: NSInteger = 2
|
||||
|
||||
|
||||
/// The color of the back cell
|
||||
@IBInspectable open var backViewColor: UIColor = UIColor.brown
|
||||
|
||||
|
||||
var animationItemViews: [RotatedView]?
|
||||
|
||||
|
||||
/**
|
||||
Folding animation types
|
||||
|
||||
|
||||
- Open: Open direction
|
||||
- Close: Close direction
|
||||
*/
|
||||
@@ -53,73 +53,75 @@ open class FoldingCell: UITableViewCell {
|
||||
case open
|
||||
case close
|
||||
}
|
||||
|
||||
// MARK: Life Cycle
|
||||
|
||||
|
||||
// MARK: Life Cycle
|
||||
|
||||
open override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
|
||||
commonInit()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call this method in methods init(style: UITableViewCellStyle, reuseIdentifier: String?) after creating Views
|
||||
*/
|
||||
open func commonInit() {
|
||||
configureDefaultState()
|
||||
|
||||
|
||||
selectionStyle = .none
|
||||
|
||||
|
||||
containerView.layer.cornerRadius = foregroundView.layer.cornerRadius
|
||||
containerView.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
|
||||
// MARK: configure
|
||||
|
||||
|
||||
func configureDefaultState() {
|
||||
|
||||
|
||||
guard let foregroundViewTop = self.foregroundViewTop,
|
||||
let containerViewTop = self.containerViewTop else {
|
||||
fatalError("set foregroundViewTop or containerViewTop outlets in storyboard")
|
||||
fatalError("set foregroundViewTop or containerViewTop outlets in storyboard")
|
||||
}
|
||||
|
||||
|
||||
containerViewTop.constant = foregroundViewTop.constant
|
||||
containerView.alpha = 0
|
||||
|
||||
|
||||
if let height = (foregroundView.constraints.filter { $0.firstAttribute == .height && $0.secondItem == nil }).first?.constant {
|
||||
foregroundView.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
|
||||
foregroundViewTop.constant += height / 2
|
||||
}
|
||||
foregroundView.layer.transform = foregroundView.transform3d()
|
||||
|
||||
|
||||
createAnimationView()
|
||||
contentView.bringSubview(toFront: foregroundView)
|
||||
}
|
||||
|
||||
|
||||
func createAnimationItemView() -> [RotatedView] {
|
||||
guard let animationView = self.animationView else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
|
||||
var items = [RotatedView]()
|
||||
items.append(foregroundView)
|
||||
var rotatedViews = [RotatedView]()
|
||||
for case let itemView as RotatedView in animationView.subviews.filter({ $0 is RotatedView }).sorted(by: { $0.tag < $1.tag }) {
|
||||
rotatedViews.append(itemView)
|
||||
if let backView = itemView.backView {
|
||||
rotatedViews.append(backView)
|
||||
}
|
||||
|
||||
animationView?.subviews
|
||||
.flatMap({ $0 as? RotatedView })
|
||||
.sorted(by: { $0.tag < $1.tag })
|
||||
.forEach { itemView in
|
||||
rotatedViews.append(itemView)
|
||||
if let backView = itemView.backView {
|
||||
rotatedViews.append(backView)
|
||||
}
|
||||
}
|
||||
|
||||
items.append(contentsOf: rotatedViews)
|
||||
return items
|
||||
}
|
||||
|
||||
|
||||
func configureAnimationItems(_ animationType: AnimationType) {
|
||||
|
||||
|
||||
guard let animationViewSuperView = animationView?.subviews else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
|
||||
if animationType == .open {
|
||||
for view in animationViewSuperView.filter({ $0 is RotatedView }) {
|
||||
view.alpha = 0
|
||||
@@ -135,18 +137,18 @@ open class FoldingCell: UITableViewCell {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func createAnimationView() {
|
||||
animationView = UIView(frame: containerView.frame)
|
||||
animationView?.layer.cornerRadius = foregroundView.layer.cornerRadius
|
||||
animationView?.backgroundColor = .clear
|
||||
animationView?.translatesAutoresizingMaskIntoConstraints = false
|
||||
animationView?.alpha = 0
|
||||
|
||||
|
||||
guard let animationView = self.animationView else { return }
|
||||
|
||||
|
||||
self.contentView.addSubview(animationView)
|
||||
|
||||
|
||||
// copy constraints from containerView
|
||||
var newConstraints = [NSLayoutConstraint]()
|
||||
for constraint in self.contentView.constraints {
|
||||
@@ -154,57 +156,57 @@ open class FoldingCell: UITableViewCell {
|
||||
let newConstraint = NSLayoutConstraint(item: animationView, attribute: constraint.firstAttribute,
|
||||
relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute,
|
||||
multiplier: constraint.multiplier, constant: constraint.constant)
|
||||
|
||||
|
||||
newConstraints.append(newConstraint)
|
||||
} else if let firstItem = constraint.firstItem as? UIView, let secondItem: UIView = constraint.secondItem as? UIView, secondItem == containerView {
|
||||
let newConstraint = NSLayoutConstraint(item: firstItem, attribute: constraint.firstAttribute,
|
||||
relatedBy: constraint.relation, toItem: animationView, attribute: constraint.secondAttribute,
|
||||
multiplier: constraint.multiplier, constant: constraint.constant)
|
||||
|
||||
|
||||
newConstraints.append(newConstraint)
|
||||
}
|
||||
}
|
||||
self.contentView.addConstraints(newConstraints)
|
||||
|
||||
|
||||
for constraint in containerView.constraints { // added height constraint
|
||||
if constraint.firstAttribute == .height, let item: UIView = constraint.firstItem as? UIView, item == containerView {
|
||||
let newConstraint = NSLayoutConstraint(item: animationView, attribute: constraint.firstAttribute,
|
||||
relatedBy: constraint.relation, toItem: nil, attribute: constraint.secondAttribute,
|
||||
multiplier: constraint.multiplier, constant: constraint.constant)
|
||||
|
||||
|
||||
animationView.addConstraint(newConstraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func addImageItemsToAnimationView() {
|
||||
containerView.alpha = 1
|
||||
let containerViewSize = containerView.bounds.size
|
||||
let foregroundViewSize = foregroundView.bounds.size
|
||||
|
||||
|
||||
// added first item
|
||||
var image = containerView.pb_takeSnapshot(CGRect(x: 0, y: 0, width: containerViewSize.width, height: foregroundViewSize.height))
|
||||
var imageView = UIImageView(image: image)
|
||||
imageView.tag = 0
|
||||
imageView.layer.cornerRadius = foregroundView.layer.cornerRadius
|
||||
animationView?.addSubview(imageView)
|
||||
|
||||
|
||||
// added secod item
|
||||
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: foregroundViewSize.height, width: containerViewSize.width, height: foregroundViewSize.height))
|
||||
|
||||
|
||||
imageView = UIImageView(image: image)
|
||||
let rotatedView = RotatedView(frame: imageView.frame)
|
||||
rotatedView.tag = 1
|
||||
rotatedView.layer.anchorPoint = CGPoint(x: 0.5, y: 0)
|
||||
rotatedView.layer.transform = rotatedView.transform3d()
|
||||
|
||||
|
||||
rotatedView.addSubview(imageView)
|
||||
animationView?.addSubview(rotatedView)
|
||||
rotatedView.frame = CGRect(x: imageView.frame.origin.x, y: foregroundViewSize.height, width: containerViewSize.width, height: foregroundViewSize.height)
|
||||
|
||||
|
||||
// added other views
|
||||
let itemHeight = (containerViewSize.height - 2 * foregroundViewSize.height) / CGFloat(itemCount - 2)
|
||||
|
||||
|
||||
if itemCount == 2 {
|
||||
// decrease containerView height or increase itemCount
|
||||
assert(containerViewSize.height - 2 * foregroundViewSize.height == 0, "contanerView.height too high")
|
||||
@@ -212,51 +214,51 @@ open class FoldingCell: UITableViewCell {
|
||||
// decrease containerView height or increase itemCount
|
||||
assert(containerViewSize.height - 2 * foregroundViewSize.height >= itemHeight, "contanerView.height too high")
|
||||
}
|
||||
|
||||
|
||||
var yPosition = 2 * foregroundViewSize.height
|
||||
var tag = 2
|
||||
for _ in 2 ..< itemCount {
|
||||
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: yPosition, width: containerViewSize.width, height: itemHeight))
|
||||
|
||||
|
||||
imageView = UIImageView(image: image)
|
||||
let rotatedView = RotatedView(frame: imageView.frame)
|
||||
|
||||
|
||||
rotatedView.addSubview(imageView)
|
||||
rotatedView.layer.anchorPoint = CGPoint(x: 0.5, y: 0)
|
||||
rotatedView.layer.transform = rotatedView.transform3d()
|
||||
animationView?.addSubview(rotatedView)
|
||||
rotatedView.frame = CGRect(x: 0, y: yPosition, width: rotatedView.bounds.size.width, height: itemHeight)
|
||||
rotatedView.tag = tag
|
||||
|
||||
|
||||
yPosition += itemHeight
|
||||
tag += 1
|
||||
}
|
||||
|
||||
|
||||
containerView.alpha = 0
|
||||
|
||||
|
||||
if let animationView = self.animationView {
|
||||
// added back view
|
||||
var previuosView: RotatedView?
|
||||
for case let container as RotatedView in animationView.subviews.sorted(by: { $0.tag < $1.tag })
|
||||
where container.tag > 0 && container.tag < animationView.subviews.count {
|
||||
previuosView?.addBackView(container.bounds.size.height, color: backViewColor)
|
||||
previuosView = container
|
||||
previuosView?.addBackView(container.bounds.size.height, color: backViewColor)
|
||||
previuosView = container
|
||||
}
|
||||
}
|
||||
animationItemViews = createAnimationItemView()
|
||||
}
|
||||
|
||||
|
||||
fileprivate func removeImageItemsFromAnimationView() {
|
||||
|
||||
|
||||
guard let animationView = self.animationView else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
animationView.subviews.forEach({ $0.removeFromSuperview() })
|
||||
}
|
||||
|
||||
|
||||
// MARK: public
|
||||
|
||||
|
||||
/// Unfold cell.
|
||||
///
|
||||
/// - Parameters:
|
||||
@@ -271,34 +273,22 @@ open class FoldingCell: UITableViewCell {
|
||||
containerView.alpha = value ? 1 : 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Open or close cell
|
||||
|
||||
- parameter isSelected: Specify true if you want to open cell or false if you close cell.
|
||||
- parameter animated: Specify true if you want to animate the change in visibility or false if you want immediately.
|
||||
- parameter completion: A block object to be executed when the animation sequence ends.
|
||||
*/
|
||||
@available(iOS, deprecated, message: "Use unfold(_:animated:completion) method instead.")
|
||||
open func selectedAnimation(_ isSelected: Bool, animated: Bool, completion: (() -> Void)?) {
|
||||
unfold(isSelected, animated: animated, completion: completion)
|
||||
}
|
||||
|
||||
|
||||
open func isAnimating() -> Bool {
|
||||
return animationView?.alpha == 1 ? true : false
|
||||
}
|
||||
|
||||
|
||||
open var isUnfolded = false
|
||||
|
||||
|
||||
// MARK: Animations
|
||||
|
||||
|
||||
open func animationDuration(_ itemIndex: NSInteger, type: AnimationType) -> TimeInterval {
|
||||
return type == .close ? durationsForCollapsedState[itemIndex] : durationsForExpandedState[itemIndex]
|
||||
}
|
||||
|
||||
|
||||
open var durationsForExpandedState: [TimeInterval] = []
|
||||
open var durationsForCollapsedState: [TimeInterval] = []
|
||||
|
||||
|
||||
func durationSequence(_ type: AnimationType) -> [TimeInterval] {
|
||||
var durations = [TimeInterval]()
|
||||
for i in 0 ..< itemCount - 1 {
|
||||
@@ -308,83 +298,83 @@ open class FoldingCell: UITableViewCell {
|
||||
}
|
||||
return durations
|
||||
}
|
||||
|
||||
|
||||
func openAnimation(_ completion: (() -> Void)?) {
|
||||
isUnfolded = true
|
||||
removeImageItemsFromAnimationView()
|
||||
addImageItemsToAnimationView()
|
||||
|
||||
|
||||
animationView?.alpha = 1
|
||||
containerView.alpha = 0
|
||||
|
||||
|
||||
let durations = durationSequence(.open)
|
||||
|
||||
|
||||
var delay: TimeInterval = 0
|
||||
var timing = kCAMediaTimingFunctionEaseIn
|
||||
var from: CGFloat = 0.0
|
||||
var to: CGFloat = -CGFloat.pi / 2
|
||||
var hidden = true
|
||||
configureAnimationItems(.open)
|
||||
|
||||
|
||||
guard let animationItemViews = self.animationItemViews else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
for index in 0 ..< animationItemViews.count {
|
||||
let animatedView = animationItemViews[index]
|
||||
|
||||
|
||||
animatedView.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
|
||||
|
||||
|
||||
from = from == 0.0 ? CGFloat.pi / 2 : 0.0
|
||||
to = to == 0.0 ? -CGFloat.pi / 2 : 0.0
|
||||
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn
|
||||
hidden = !hidden
|
||||
delay += durations[index]
|
||||
}
|
||||
|
||||
|
||||
let firstItemView = animationView?.subviews.filter { $0.tag == 0 }.first
|
||||
|
||||
|
||||
firstItemView?.layer.masksToBounds = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + durations[0], execute: {
|
||||
firstItemView?.layer.cornerRadius = 0
|
||||
})
|
||||
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
|
||||
self.animationView?.alpha = 0
|
||||
self.containerView.alpha = 1
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func closeAnimation(_ completion: (() -> Void)?) {
|
||||
isUnfolded = false
|
||||
removeImageItemsFromAnimationView()
|
||||
addImageItemsToAnimationView()
|
||||
|
||||
|
||||
guard let animationItemViews = self.animationItemViews else {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
|
||||
animationView?.alpha = 1
|
||||
containerView.alpha = 0
|
||||
|
||||
|
||||
var durations: [TimeInterval] = durationSequence(.close).reversed()
|
||||
|
||||
|
||||
var delay: TimeInterval = 0
|
||||
var timing = kCAMediaTimingFunctionEaseIn
|
||||
var from: CGFloat = 0.0
|
||||
var to: CGFloat = CGFloat.pi / 2
|
||||
var hidden = true
|
||||
configureAnimationItems(.close)
|
||||
|
||||
|
||||
if durations.count < animationItemViews.count {
|
||||
fatalError("wrong override func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval")
|
||||
}
|
||||
for index in 0 ..< animationItemViews.count {
|
||||
let animatedView = animationItemViews.reversed()[index]
|
||||
|
||||
|
||||
animatedView.foldingAnimation(timing, from: from, to: to, duration: durations[index], delay: delay, hidden: hidden)
|
||||
|
||||
|
||||
to = to == 0.0 ? CGFloat.pi / 2 : 0.0
|
||||
from = from == 0.0 ? -CGFloat.pi / 2 : 0.0
|
||||
timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn
|
||||
@@ -395,7 +385,7 @@ open class FoldingCell: UITableViewCell {
|
||||
self.animationView?.alpha = 0
|
||||
completion?()
|
||||
})
|
||||
|
||||
|
||||
let firstItemView = animationView?.subviews.filter { $0.tag == 0 }.first
|
||||
firstItemView?.layer.cornerRadius = 0
|
||||
firstItemView?.layer.masksToBounds = true
|
||||
@@ -414,7 +404,7 @@ open class FoldingCell: UITableViewCell {
|
||||
open class RotatedView: UIView {
|
||||
var hiddenAfterAnimation = false
|
||||
var backView: RotatedView?
|
||||
|
||||
|
||||
func addBackView(_ height: CGFloat, color: UIColor) {
|
||||
let view = RotatedView(frame: CGRect.zero)
|
||||
view.backgroundColor = color
|
||||
@@ -423,10 +413,10 @@ open class RotatedView: UIView {
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.addSubview(view)
|
||||
backView = view
|
||||
|
||||
|
||||
view.addConstraint(NSLayoutConstraint(item: view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height,
|
||||
multiplier: 1, constant: height))
|
||||
|
||||
|
||||
self.addConstraints([
|
||||
NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1,
|
||||
constant: self.bounds.size.height - height + height / 2),
|
||||
@@ -434,12 +424,12 @@ open class RotatedView: UIView {
|
||||
multiplier: 1, constant: 0),
|
||||
NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing,
|
||||
multiplier: 1, constant: 0),
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension RotatedView: CAAnimationDelegate {
|
||||
|
||||
|
||||
func rotatedX(_ angle: CGFloat) {
|
||||
var allTransofrom = CATransform3DIdentity
|
||||
let rotateTransform = CATransform3DMakeRotation(angle, 1, 0, 0)
|
||||
@@ -447,17 +437,17 @@ extension RotatedView: CAAnimationDelegate {
|
||||
allTransofrom = CATransform3DConcat(allTransofrom, transform3d())
|
||||
self.layer.transform = allTransofrom
|
||||
}
|
||||
|
||||
|
||||
func transform3d() -> CATransform3D {
|
||||
var transform = CATransform3DIdentity
|
||||
transform.m34 = 2.5 / -2000
|
||||
return transform
|
||||
}
|
||||
|
||||
|
||||
// MARK: animations
|
||||
|
||||
|
||||
func foldingAnimation(_ timing: String, from: CGFloat, to: CGFloat, duration: TimeInterval, delay: TimeInterval, hidden: Bool) {
|
||||
|
||||
|
||||
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation.x")
|
||||
rotateAnimation.timingFunction = CAMediaTimingFunction(name: timing)
|
||||
rotateAnimation.fromValue = from
|
||||
@@ -467,17 +457,17 @@ extension RotatedView: CAAnimationDelegate {
|
||||
rotateAnimation.fillMode = kCAFillModeForwards
|
||||
rotateAnimation.isRemovedOnCompletion = false
|
||||
rotateAnimation.beginTime = CACurrentMediaTime() + delay
|
||||
|
||||
|
||||
self.hiddenAfterAnimation = hidden
|
||||
|
||||
|
||||
self.layer.add(rotateAnimation, forKey: "rotation.x")
|
||||
}
|
||||
|
||||
|
||||
public func animationDidStart(_: CAAnimation) {
|
||||
self.layer.shouldRasterize = true
|
||||
self.alpha = 1
|
||||
}
|
||||
|
||||
|
||||
public func animationDidStop(_: CAAnimation, finished _: Bool) {
|
||||
if hiddenAfterAnimation {
|
||||
self.alpha = 0
|
||||
@@ -489,17 +479,17 @@ extension RotatedView: CAAnimationDelegate {
|
||||
}
|
||||
|
||||
private extension UIView {
|
||||
|
||||
|
||||
func pb_takeSnapshot(_ frame: CGRect) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0)
|
||||
|
||||
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return nil }
|
||||
context.translateBy(x: frame.origin.x * -1, y: frame.origin.y * -1)
|
||||
|
||||
|
||||
layer.render(in: context)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
# FoldingCell
|
||||
[](https://cocoapods.org/pods/FoldingCell)
|
||||
[](http://cocoapods.org/pods/FoldingCell)
|
||||
[](https://github.com/Ramotion/folding-cell)
|
||||
[](http://twitter.com/Ramotion)
|
||||
[](https://travis-ci.org/Ramotion/folding-cell)
|
||||
[](https://codebeat.co/projects/github-com-ramotion-folding-cell)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://developer.apple.com/swift/)
|
||||
[](https://github.com/igrigorik/ga-beacon)
|
||||
|
||||
# Check this library on other platforms:
|
||||
@@ -18,7 +18,7 @@
|
||||
**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://ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell-contact-us/#Get_in_Touch">
|
||||
<a href="https://dev.ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell-contact-us">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a> <br>
|
||||
|
||||
|
||||
@@ -168,10 +168,11 @@ Try this UI component and more like this in our iOS app. Contact us if intereste
|
||||
<a href="https://itunes.apple.com/app/apple-store/id1182360240?pt=550053&ct=folding-cell&mt=8" >
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/app_store@2x.png" width="117" height="34"></a>
|
||||
|
||||
<a href="https://ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell-contact-us/#Get_in_Touch">
|
||||
<a href="https://dev.ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell-contact-us">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
Follow us for the latest updates<br>[](https://twitter.com/intent/tweet?text=https://github.com/ramotion/folding-cell)
|
||||
[](https://twitter.com/ramotion)
|
||||
Follow us for the latest updates<br>
|
||||
<a href="https://goo.gl/rPFpid" >
|
||||
<img src="https://i.imgur.com/ziSqeSo.png/" width="156" height="28"></a>
|
||||
|
||||
Reference in New Issue
Block a user