Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e5639f5d0 | ||
|
|
02d5d8431d | ||
|
|
1d20e0bd06 | ||
|
|
4be8ef9b1d | ||
|
|
dd71f7ba65 | ||
|
|
fecd05d93f | ||
|
|
77e99b8708 | ||
|
|
5254378736 | ||
|
|
74e0ca7f7b | ||
|
|
ef3307924a | ||
|
|
39377ad181 | ||
|
|
1cf7a8124f |
+1
-1
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'FoldingCell'
|
||||
s.version = '2.1.0'
|
||||
s.version = '2.1.3'
|
||||
s.summary = 'UITableViewCell with folding animation.'
|
||||
s.homepage = 'https://github.com/Ramotion/folding-cell'
|
||||
s.license = 'MIT'
|
||||
|
||||
@@ -27,6 +27,11 @@ class DemoCell: FoldingCell {
|
||||
super.awakeFromNib()
|
||||
}
|
||||
|
||||
override func animationDuration(_ itemIndex: NSInteger, type: FoldingCell.AnimationType) -> TimeInterval {
|
||||
let durations = [0.26, 0.2, 0.2]
|
||||
return durations[itemIndex]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Actions ⚡️
|
||||
|
||||
@@ -614,7 +614,7 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -641,7 +641,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.FoldingCell;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -777,6 +777,7 @@
|
||||
9DAA51691EDDBAD700DFC539 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ open class FoldingCell: UITableViewCell {
|
||||
}
|
||||
|
||||
containerViewTop.constant = foregroundViewTop.constant
|
||||
containerView.alpha = 0;
|
||||
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)
|
||||
@@ -101,7 +101,7 @@ open class FoldingCell: UITableViewCell {
|
||||
}
|
||||
foregroundView.layer.transform = foregroundView.transform3d()
|
||||
|
||||
createAnimationView();
|
||||
createAnimationView()
|
||||
self.contentView.bringSubview(toFront: foregroundView)
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ open class FoldingCell: UITableViewCell {
|
||||
for view in animationViewSuperView.filter({$0 is RotatedView}) {
|
||||
view.alpha = 0;
|
||||
}
|
||||
} else { // close
|
||||
} else {
|
||||
for case let view as RotatedView in animationViewSuperView.filter({$0 is RotatedView}) {
|
||||
if animationType == .open {
|
||||
view.alpha = 0
|
||||
@@ -146,7 +146,6 @@ open class FoldingCell: UITableViewCell {
|
||||
}
|
||||
|
||||
func createAnimationView() {
|
||||
|
||||
animationView = UIView(frame: containerView.frame)
|
||||
animationView?.layer.cornerRadius = foregroundView.layer.cornerRadius
|
||||
animationView?.backgroundColor = .clear
|
||||
@@ -166,8 +165,8 @@ open class FoldingCell: UITableViewCell {
|
||||
multiplier: constraint.multiplier, constant: constraint.constant)
|
||||
|
||||
newConstraints.append(newConstraint)
|
||||
} else if let item: UIView = constraint.secondItem as? UIView , item == containerView {
|
||||
let newConstraint = NSLayoutConstraint(item: constraint.firstItem, attribute: constraint.firstAttribute,
|
||||
} 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)
|
||||
|
||||
@@ -190,18 +189,18 @@ open class FoldingCell: UITableViewCell {
|
||||
|
||||
func addImageItemsToAnimationView() {
|
||||
containerView.alpha = 1;
|
||||
let contSize = containerView.bounds.size
|
||||
let forgSize = foregroundView.bounds.size
|
||||
let containerViewSize = containerView.bounds.size
|
||||
let foregroundViewSize = foregroundView.bounds.size
|
||||
|
||||
// added first item
|
||||
var image = containerView.pb_takeSnapshot(CGRect(x: 0, y: 0, width: contSize.width, height: forgSize.height))
|
||||
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: forgSize.height, width: contSize.width, height: forgSize.height))
|
||||
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)
|
||||
@@ -211,24 +210,24 @@ open class FoldingCell: UITableViewCell {
|
||||
|
||||
rotatedView.addSubview(imageView)
|
||||
animationView?.addSubview(rotatedView)
|
||||
rotatedView.frame = CGRect(x: imageView.frame.origin.x, y: forgSize.height, width: contSize.width, height: forgSize.height)
|
||||
rotatedView.frame = CGRect(x: imageView.frame.origin.x, y: foregroundViewSize.height, width: containerViewSize.width, height: foregroundViewSize.height)
|
||||
|
||||
// added other views
|
||||
let itemHeight = (contSize.height - 2 * forgSize.height) / CGFloat(itemCount - 2)
|
||||
let itemHeight = (containerViewSize.height - 2 * foregroundViewSize.height) / CGFloat(itemCount - 2)
|
||||
|
||||
if itemCount == 2 {
|
||||
// decrease containerView height or increase itemCount
|
||||
assert(contSize.height - 2 * forgSize.height == 0, "contanerView.height too high")
|
||||
assert(containerViewSize.height - 2 * foregroundViewSize.height == 0, "contanerView.height too high")
|
||||
}
|
||||
else{
|
||||
// decrease containerView height or increase itemCount
|
||||
assert(contSize.height - 2 * forgSize.height >= itemHeight, "contanerView.height too high")
|
||||
assert(containerViewSize.height - 2 * foregroundViewSize.height >= itemHeight, "contanerView.height too high")
|
||||
}
|
||||
|
||||
var yPosition = 2 * forgSize.height
|
||||
var yPosition = 2 * foregroundViewSize.height
|
||||
var tag = 2
|
||||
for _ in 2..<itemCount {
|
||||
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: yPosition, width: contSize.width, height: itemHeight))
|
||||
image = containerView.pb_takeSnapshot(CGRect(x: 0, y: yPosition, width: containerViewSize.width, height: itemHeight))
|
||||
|
||||
imageView = UIImageView(image: image)
|
||||
let rotatedView = RotatedView(frame: imageView.frame)
|
||||
@@ -241,18 +240,18 @@ open class FoldingCell: UITableViewCell {
|
||||
rotatedView.tag = tag
|
||||
|
||||
yPosition += itemHeight
|
||||
tag += 1;
|
||||
tag += 1
|
||||
}
|
||||
|
||||
containerView.alpha = 0;
|
||||
|
||||
if let animationView = self.animationView {
|
||||
// added back view
|
||||
var previusView: RotatedView?
|
||||
for case let contener as RotatedView in animationView.subviews.sorted(by: { $0.tag < $1.tag })
|
||||
where contener.tag > 0 && contener.tag < animationView.subviews.count {
|
||||
previusView?.addBackView(contener.bounds.size.height, color: backViewColor)
|
||||
previusView = contener
|
||||
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
|
||||
}
|
||||
}
|
||||
animationItemViews = createAnimationItemView()
|
||||
@@ -270,6 +269,21 @@ open class FoldingCell: UITableViewCell {
|
||||
|
||||
// MARK: public
|
||||
|
||||
/// Unfold cell.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - value: unfold = true; collapse = false.
|
||||
/// - animated: animate changes.
|
||||
/// - completion: A block object to be executed when the animation sequence ends.
|
||||
open func unfold(_ value: Bool, animated: Bool = true, completion: (() -> Void)? = nil) {
|
||||
if animated {
|
||||
value ? openAnimation(completion) : closeAnimation(completion)
|
||||
} else {
|
||||
foregroundView.alpha = value ? 0 : 1
|
||||
containerView.alpha = value ? 1 : 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Open or close cell
|
||||
|
||||
@@ -277,48 +291,37 @@ open class FoldingCell: UITableViewCell {
|
||||
- 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.
|
||||
*/
|
||||
open func selectedAnimation(_ isSelected: Bool, animated: Bool, completion: ((Void) -> Void)?) {
|
||||
|
||||
if isSelected {
|
||||
|
||||
if animated {
|
||||
containerView.alpha = 0;
|
||||
openAnimation(completion)
|
||||
} else {
|
||||
foregroundView.alpha = 0
|
||||
containerView.alpha = 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if animated {
|
||||
closeAnimation(completion)
|
||||
} else {
|
||||
foregroundView.alpha = 1;
|
||||
containerView.alpha = 0;
|
||||
}
|
||||
}
|
||||
@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 {
|
||||
open func isAnimating() -> Bool {
|
||||
return animationView?.alpha == 1 ? true : false
|
||||
}
|
||||
|
||||
// MARK: animations
|
||||
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 {
|
||||
let duration = type == .close ? durationsForCollapsedState[i] : durationsForExpandedState[i]
|
||||
let duration = animationDuration(i, type: type)
|
||||
durations.append(TimeInterval(duration / 2.0))
|
||||
durations.append(TimeInterval(duration / 2.0))
|
||||
}
|
||||
return durations
|
||||
}
|
||||
|
||||
func openAnimation(_ completion: ((Void) -> Void)?) {
|
||||
|
||||
func openAnimation(_ completion: (() -> Void)?) {
|
||||
isUnfolded = true
|
||||
removeImageItemsFromAnimationView()
|
||||
addImageItemsToAnimationView()
|
||||
|
||||
@@ -326,12 +329,12 @@ open class FoldingCell: UITableViewCell {
|
||||
return
|
||||
}
|
||||
|
||||
animationView.alpha = 1;
|
||||
containerView.alpha = 0;
|
||||
animationView.alpha = 1
|
||||
containerView.alpha = 0
|
||||
|
||||
let durations = durationSequence(.open)
|
||||
|
||||
var delay: TimeInterval = 0
|
||||
var delay: TimeInterval = 0
|
||||
var timing = kCAMediaTimingFunctionEaseIn
|
||||
var from: CGFloat = 0.0;
|
||||
var to: CGFloat = -CGFloat.pi / 2
|
||||
@@ -354,22 +357,22 @@ open class FoldingCell: UITableViewCell {
|
||||
delay += durations[index]
|
||||
}
|
||||
|
||||
let firstItemView = animationView.subviews.filter{$0.tag == 0}.first
|
||||
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: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
|
||||
self.animationView?.alpha = 0
|
||||
self.containerView.alpha = 1
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func closeAnimation(_ completion: ((Void) -> Void)?) {
|
||||
|
||||
func closeAnimation(_ completion: (() -> Void)?) {
|
||||
isUnfolded = false
|
||||
removeImageItemsFromAnimationView()
|
||||
addImageItemsToAnimationView()
|
||||
|
||||
@@ -377,14 +380,14 @@ open class FoldingCell: UITableViewCell {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
animationView?.alpha = 1;
|
||||
containerView.alpha = 0;
|
||||
animationView?.alpha = 1
|
||||
containerView.alpha = 0
|
||||
|
||||
var durations: [TimeInterval] = durationSequence(.close).reversed()
|
||||
|
||||
var delay: TimeInterval = 0
|
||||
var delay: TimeInterval = 0
|
||||
var timing = kCAMediaTimingFunctionEaseIn
|
||||
var from: CGFloat = 0.0;
|
||||
var from: CGFloat = 0.0
|
||||
var to: CGFloat = CGFloat.pi / 2
|
||||
var hidden = true
|
||||
configureAnimationItems(.close)
|
||||
@@ -408,7 +411,7 @@ open class FoldingCell: UITableViewCell {
|
||||
completion?()
|
||||
})
|
||||
|
||||
let firstItemView = animationView?.subviews.filter{$0.tag == 0}.first
|
||||
let firstItemView = animationView?.subviews.filter { $0.tag == 0 }.first
|
||||
firstItemView?.layer.cornerRadius = 0
|
||||
firstItemView?.layer.masksToBounds = true
|
||||
if let durationFirst = durations.first {
|
||||
@@ -432,7 +435,7 @@ open class RotatedView: UIView {
|
||||
view.backgroundColor = color
|
||||
view.layer.anchorPoint = CGPoint.init(x: 0.5, y: 1)
|
||||
view.layer.transform = view.transform3d()
|
||||
view.translatesAutoresizingMaskIntoConstraints = false;
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.addSubview(view)
|
||||
backView = view
|
||||
|
||||
@@ -498,23 +501,22 @@ extension RotatedView: CAAnimationDelegate {
|
||||
self.layer.shouldRasterize = false
|
||||
self.rotatedX(CGFloat(0))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
private extension UIView {
|
||||
|
||||
func pb_takeSnapshot(_ frame: CGRect) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0.0)
|
||||
UIGraphicsBeginImageContextWithOptions(frame.size, false, 0)
|
||||
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return nil }
|
||||
context.translateBy(x: frame.origin.x * -1, y: frame.origin.y * -1)
|
||||
|
||||
guard let currentContext = UIGraphicsGetCurrentContext() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.layer.render(in: currentContext)
|
||||
layer.render(in: context)
|
||||
let image = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[](https://business.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=foolding-cell-logo)
|
||||

|
||||

|
||||
|
||||
# FoldingCell
|
||||
[](https://cocoapods.org/pods/FoldingCell)
|
||||
[](http://cocoapods.org/pods/FoldingCell)
|
||||
[](https://cdn.rawgit.com/Ramotion/folding-cell/master/docs/index.html)
|
||||
[](https://github.com/Ramotion/folding-cell)
|
||||
[](http://twitter.com/Ramotion)
|
||||
[](https://travis-ci.org/Ramotion/folding-cell)
|
||||
@@ -12,19 +13,17 @@
|
||||
|
||||
## About
|
||||
This project is maintained by Ramotion, Inc.<br>
|
||||
We specialize in the designing and coding of custom UI for Mobile Apps and Websites.<br><br>**Looking for developers for your project?**
|
||||
We specialize in the designing and coding of custom UI for Mobile Apps and Websites.<br>
|
||||
|
||||
<a href="https://business.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=foolding-cell-contact-us/#Get_in_Touch" > <img src="https://github.com/Ramotion/navigation-stack/raw/master/contact_our_team@2x.png" width="150" height="30"></a>
|
||||
**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.
|
||||
|
||||
[](https://dribbble.com/shots/2121350-Delivery-Card)
|
||||
<a href="https://ramotion.com/?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell-contact-us/#Get_in_Touch">
|
||||
<img src="https://github.com/ramotion/gliding-collection/raw/master/contact_our_team@2x.png" width="187" height="34"></a> <br>
|
||||
|
||||
|
||||
The [iPhone mockup](https://store.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell) available [here](https://store.ramotion.com?utm_source=gthb&utm_medium=special&utm_campaign=folding-cell).
|
||||
|
||||
## Try this UI control in action
|
||||
|
||||
<a href="https://itunes.apple.com/app/apple-store/id1182360240?pt=550053&ct=gthb-folding-cell&mt=8" > <img src="https://github.com/Ramotion/navigation-stack/raw/master/Download_on_the_App_Store_Badge_US-UK_135x40.png" width="170" height="58"></a>
|
||||
|
||||
## Requirements
|
||||
|
||||
- iOS 8.0+
|
||||
@@ -151,8 +150,7 @@ fileprivate struct C {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### if don't use storyboard and xib files
|
||||
## if don't use storyboard and xib files
|
||||
|
||||
Create foregroundView and containerView from code (steps 2 - 3) look example:
|
||||
[Folding-cell-programmatically](https://github.com/ober01/Folding-cell-programmatically)
|
||||
@@ -162,8 +160,18 @@ Create foregroundView and containerView from code (steps 2 - 3) look example:
|
||||
Folding cell is released under the MIT license.
|
||||
See [LICENSE](./LICENSE) for details.
|
||||
|
||||
<br>
|
||||
|
||||
## Follow Us
|
||||
# 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.
|
||||
|
||||
[](https://twitter.com/intent/tweet?text=https://github.com/ramotion/foolding-cell)
|
||||
<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">
|
||||
<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)
|
||||
|
||||
Reference in New Issue
Block a user