Commit 09ca9e30 by Daniel Dahan

development: prepare for release Material 2.3.8

parent 5c94cc52
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Material' s.name = 'Material'
s.version = '2.3.7' s.version = '2.3.8'
s.license = 'BSD-3-Clause' s.license = 'BSD-3-Clause'
s.summary = 'Material is an animation and graphics framework that is used to create beautiful applications.' s.summary = 'Material is an animation and graphics framework that is used to create beautiful applications.'
s.homepage = 'http://materialswift.com' s.homepage = 'http://materialswift.com'
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.3.7</string> <string>2.3.8</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
......
...@@ -37,18 +37,10 @@ open class Button: UIButton, Pulseable { ...@@ -37,18 +37,10 @@ open class Button: UIButton, Pulseable {
allows the dropshadow effect on the backing layer, while clipping allows the dropshadow effect on the backing layer, while clipping
the image to a desired shape within the visualLayer. the image to a desired shape within the visualLayer.
*/ */
open internal(set) var visualLayer = CAShapeLayer() open fileprivate(set) var visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
internal var pulse = Pulse() open fileprivate(set) var pulse: Pulse!
/// The layer the pulse layers are added to.
internal var pulseLayer: CALayer {
return visualLayer as CALayer
}
/// An Array of pulse layers.
internal var pulseLayers = [CAShapeLayer]()
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -190,13 +182,12 @@ open class Button: UIButton, Pulseable { ...@@ -190,13 +182,12 @@ open class Button: UIButton, Pulseable {
open func pulse(point: CGPoint? = nil) { open func pulse(point: CGPoint? = nil) {
let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point! let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point!
var s = self pulse.expandAnimation(point: p)
MotionPulse<Button>.expandAnimation(view: &s, point: p)
Motion.delay(time: 0.35) { [weak self] in Motion.delay(time: 0.35) { [weak self] in
guard var s = self else { guard let s = self else {
return return
} }
MotionPulse<Button>.contractAnimation(view: &s) s.pulse.contractAnimation()
} }
} }
...@@ -208,8 +199,7 @@ open class Button: UIButton, Pulseable { ...@@ -208,8 +199,7 @@ open class Button: UIButton, Pulseable {
*/ */
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
var s = self pulse.expandAnimation(point: layer.convert(touches.first!.location(in: self), from: layer))
MotionPulse<Button>.expandAnimation(view: &s, point: layer.convert(touches.first!.location(in: self), from: layer))
} }
/** /**
...@@ -220,8 +210,7 @@ open class Button: UIButton, Pulseable { ...@@ -220,8 +210,7 @@ open class Button: UIButton, Pulseable {
*/ */
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<Button>.contractAnimation(view: &s)
} }
/** /**
...@@ -232,8 +221,7 @@ open class Button: UIButton, Pulseable { ...@@ -232,8 +221,7 @@ open class Button: UIButton, Pulseable {
*/ */
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<Button>.contractAnimation(view: &s)
} }
open func bringImageViewToFront() { open func bringImageViewToFront() {
...@@ -254,19 +242,21 @@ open class Button: UIButton, Pulseable { ...@@ -254,19 +242,21 @@ open class Button: UIButton, Pulseable {
open func prepare() { open func prepare() {
contentScaleFactor = Device.scale contentScaleFactor = Device.scale
prepareVisualLayer() prepareVisualLayer()
preparePulse()
} }
}
extension Button {
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
internal func prepareVisualLayer() { fileprivate func prepareVisualLayer() {
visualLayer.zPosition = 0 visualLayer.zPosition = 0
visualLayer.masksToBounds = true visualLayer.masksToBounds = true
layer.addSublayer(visualLayer) layer.addSublayer(visualLayer)
} }
/// Manages the layout for the visualLayer property. /// Prepares the pulse motion.
internal func layoutVisualLayer() { fileprivate func preparePulse() {
visualLayer.frame = bounds pulse = Pulse(pulseView: self, pulseLayer: visualLayer)
visualLayer.cornerRadius = cornerRadius
} }
/** /**
...@@ -274,7 +264,7 @@ open class Button: UIButton, Pulseable { ...@@ -274,7 +264,7 @@ open class Button: UIButton, Pulseable {
- Parameter image: A UIImage. - Parameter image: A UIImage.
- Parameter tintColor: A UI - Parameter tintColor: A UI
*/ */
private func prepare(with image: UIImage?, tintColor: UIColor) { fileprivate func prepare(with image: UIImage?, tintColor: UIColor) {
self.image = image self.image = image
self.tintColor = tintColor self.tintColor = tintColor
} }
...@@ -284,8 +274,16 @@ open class Button: UIButton, Pulseable { ...@@ -284,8 +274,16 @@ open class Button: UIButton, Pulseable {
- Parameter title: A String. - Parameter title: A String.
- Parameter titleColor: A UI - Parameter titleColor: A UI
*/ */
private func prepare(with title: String?, titleColor: UIColor) { fileprivate func prepare(with title: String?, titleColor: UIColor) {
self.title = title self.title = title
self.titleColor = titleColor self.titleColor = titleColor
} }
} }
extension Button {
/// Manages the layout for the visualLayer property.
fileprivate func layoutVisualLayer() {
visualLayer.frame = bounds
visualLayer.cornerRadius = cornerRadius
}
}
...@@ -38,18 +38,10 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -38,18 +38,10 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
allows the dropshadow effect on the backing layer, while clipping allows the dropshadow effect on the backing layer, while clipping
the image to a desired shape within the visualLayer. the image to a desired shape within the visualLayer.
*/ */
open internal(set) var visualLayer = CAShapeLayer() open fileprivate(set) var visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
internal var pulse = Pulse() open fileprivate(set) var pulse: Pulse!
/// The layer the pulse layers are added to.
internal var pulseLayer: CALayer {
return visualLayer as CALayer
}
/// An Array of pulse layers.
internal var pulseLayers = [CAShapeLayer]()
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -244,13 +236,12 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -244,13 +236,12 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
open func pulse(point: CGPoint? = nil) { open func pulse(point: CGPoint? = nil) {
let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point! let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point!
var s = self pulse.expandAnimation(point: p)
MotionPulse<CollectionReusableView>.expandAnimation(view: &s, point: p)
Motion.delay(time: 0.35) { [weak self] in Motion.delay(time: 0.35) { [weak self] in
guard var s = self else { guard let s = self else {
return return
} }
MotionPulse<CollectionReusableView>.contractAnimation(view: &s) s.pulse.contractAnimation()
} }
} }
...@@ -262,8 +253,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -262,8 +253,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
*/ */
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
var s = self pulse.expandAnimation(point: layer.convert(touches.first!.location(in: self), from: layer))
MotionPulse<CollectionReusableView>.expandAnimation(view: &s, point: layer.convert(touches.first!.location(in: self), from: layer))
} }
/** /**
...@@ -274,8 +264,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -274,8 +264,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
*/ */
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<CollectionReusableView>.contractAnimation(view: &s)
} }
/** /**
...@@ -286,8 +275,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -286,8 +275,7 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
*/ */
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<CollectionReusableView>.contractAnimation(view: &s)
} }
/** /**
...@@ -301,17 +289,27 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable { ...@@ -301,17 +289,27 @@ open class CollectionReusableView: UICollectionReusableView, Pulseable {
contentScaleFactor = Device.scale contentScaleFactor = Device.scale
pulseAnimation = .none pulseAnimation = .none
prepareVisualLayer() prepareVisualLayer()
preparePulse()
}
}
extension CollectionReusableView {
/// Prepares the pulse motion.
fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer)
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
internal func prepareVisualLayer() { fileprivate func prepareVisualLayer() {
visualLayer.zPosition = 0 visualLayer.zPosition = 0
visualLayer.masksToBounds = true visualLayer.masksToBounds = true
layer.addSublayer(visualLayer) layer.addSublayer(visualLayer)
} }
}
extension CollectionReusableView {
/// Manages the layout for the visualLayer property. /// Manages the layout for the visualLayer property.
internal func layoutVisualLayer() { fileprivate func layoutVisualLayer() {
visualLayer.frame = bounds visualLayer.frame = bounds
visualLayer.cornerRadius = cornerRadius visualLayer.cornerRadius = cornerRadius
} }
......
...@@ -38,18 +38,10 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -38,18 +38,10 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
allows the dropshadow effect on the backing layer, while clipping allows the dropshadow effect on the backing layer, while clipping
the image to a desired shape within the visualLayer. the image to a desired shape within the visualLayer.
*/ */
open internal(set) var visualLayer = CAShapeLayer() open fileprivate(set) var visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
internal var pulse = Pulse() open fileprivate(set) var pulse: Pulse!
/// The layer the pulse layers are added to.
internal var pulseLayer: CALayer {
return visualLayer as CALayer
}
/// An Array of pulse layers.
internal var pulseLayers = [CAShapeLayer]()
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -251,13 +243,12 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -251,13 +243,12 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
open func pulse(point: CGPoint? = nil) { open func pulse(point: CGPoint? = nil) {
let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point! let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point!
var s = self pulse.expandAnimation(point: p)
MotionPulse<CollectionViewCell>.expandAnimation(view: &s, point: p)
Motion.delay(time: 0.35) { [weak self] in Motion.delay(time: 0.35) { [weak self] in
guard var s = self else { guard let s = self else {
return return
} }
MotionPulse<CollectionViewCell>.contractAnimation(view: &s) s.pulse.contractAnimation()
} }
} }
...@@ -269,8 +260,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -269,8 +260,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
*/ */
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
var s = self pulse.expandAnimation(point: layer.convert(touches.first!.location(in: self), from: layer))
MotionPulse<CollectionViewCell>.expandAnimation(view: &s, point: layer.convert(touches.first!.location(in: self), from: layer))
} }
/** /**
...@@ -281,8 +271,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -281,8 +271,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
*/ */
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<CollectionViewCell>.contractAnimation(view: &s)
} }
/** /**
...@@ -293,8 +282,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -293,8 +282,7 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
*/ */
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<CollectionViewCell>.contractAnimation(view: &s)
} }
/** /**
...@@ -307,17 +295,27 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable { ...@@ -307,17 +295,27 @@ open class CollectionViewCell: UICollectionViewCell, Pulseable {
open func prepare() { open func prepare() {
contentScaleFactor = Device.scale contentScaleFactor = Device.scale
prepareVisualLayer() prepareVisualLayer()
preparePulse()
}
}
extension CollectionViewCell {
/// Prepares the pulse motion.
fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer)
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
internal func prepareVisualLayer() { fileprivate func prepareVisualLayer() {
visualLayer.zPosition = 0 visualLayer.zPosition = 0
visualLayer.masksToBounds = true visualLayer.masksToBounds = true
layer.addSublayer(visualLayer) layer.addSublayer(visualLayer)
} }
}
extension CollectionViewCell {
/// Manages the layout for the visualLayer property. /// Manages the layout for the visualLayer property.
internal func layoutVisualLayer() { fileprivate func layoutVisualLayer() {
visualLayer.frame = bounds visualLayer.frame = bounds
visualLayer.cornerRadius = cornerRadius visualLayer.cornerRadius = cornerRadius
} }
......
...@@ -204,7 +204,7 @@ open class Editor: View { ...@@ -204,7 +204,7 @@ open class Editor: View {
} }
/// Reference to the TextView. /// Reference to the TextView.
open fileprivate(set) var textView: TextView! open fileprivate(set) var textView: UITextView!
/// A reference to an EditorDelegate. /// A reference to an EditorDelegate.
open weak var delegate: EditorDelegate? open weak var delegate: EditorDelegate?
...@@ -287,7 +287,7 @@ extension Editor { ...@@ -287,7 +287,7 @@ extension Editor {
/// Prepares the textView. /// Prepares the textView.
fileprivate func prepareTextView() { fileprivate func prepareTextView() {
textView = TextView(textContainer: textContainer) textView = UITextView(frame: .zero, textContainer: textContainer)
textView.delegate = self textView.delegate = self
addSubview(textView) addSubview(textView)
} }
...@@ -312,7 +312,7 @@ extension Editor: TextStorageDelegate { ...@@ -312,7 +312,7 @@ extension Editor: TextStorageDelegate {
} }
} }
extension Editor: TextViewDelegate { extension Editor: UITextViewDelegate {
open func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { open func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return delegate?.editor?(editor: self, shouldBeginEditing: textView) ?? true return delegate?.editor?(editor: self, shouldBeginEditing: textView) ?? true
} }
......
...@@ -177,12 +177,12 @@ public struct Grid { ...@@ -177,12 +177,12 @@ public struct Grid {
} }
/// Begins a deferred block. /// Begins a deferred block.
mutating public func begin() { public mutating func begin() {
deferred = true deferred = true
} }
/// Completes a deferred block. /// Completes a deferred block.
mutating public func commit() { public mutating func commit() {
deferred = false deferred = false
reload() reload()
} }
......
...@@ -42,13 +42,7 @@ public enum PulseAnimation: Int { ...@@ -42,13 +42,7 @@ public enum PulseAnimation: Int {
case pointWithBacking case pointWithBacking
} }
internal protocol Pulseable { public protocol Pulseable {
/// The layer the pulse layers are added to.
var pulseLayer: CALayer { get }
/// Pulse layers.
var pulseLayers: [CAShapeLayer] { get set }
/// A reference to the PulseAnimation. /// A reference to the PulseAnimation.
var pulseAnimation: PulseAnimation { get set } var pulseAnimation: PulseAnimation { get set }
...@@ -59,26 +53,49 @@ internal protocol Pulseable { ...@@ -59,26 +53,49 @@ internal protocol Pulseable {
var pulseOpacity: CGFloat { get set } var pulseOpacity: CGFloat { get set }
} }
internal struct Pulse { public struct Pulse {
/// A UIView that is Pulseable.
fileprivate weak var pulseView: UIView?
/// The layer the pulse layers are added to.
fileprivate weak var pulseLayer: CALayer?
/// Pulse layers.
fileprivate var layers = [CAShapeLayer]()
/// A reference to the PulseAnimation. /// A reference to the PulseAnimation.
internal var animation = PulseAnimation.pointWithBacking public var animation = PulseAnimation.pointWithBacking
/// A UIColor. /// A UIColor.
internal var color = Color.grey.base public var color = Color.grey.base
/// The opcaity value for the pulse animation. /// The opcaity value for the pulse animation.
internal var opacity: CGFloat = 0.18 public var opacity: CGFloat = 0.18
}
/**
An initializer that takes a given view and pulse layer.
- Parameter pulseView: An optional UIView.
- Parameter pulseLayer: An optional CALayer.
*/
internal init(pulseView: UIView?, pulseLayer: CALayer?) {
self.pulseView = pulseView
self.pulseLayer = pulseLayer
}
internal struct MotionPulse<T: UIView> where T: Pulseable {
/** /**
Triggers the expanding animation. Triggers the expanding animation.
- Parameter _ view: A Reference to the view to add the
animations too.
- Parameter point: A point to pulse from. - Parameter point: A point to pulse from.
*/ */
internal static func expandAnimation(view: inout T, point: CGPoint) { public mutating func expandAnimation(point: CGPoint) {
guard .none != view.pulseAnimation else { guard let view = pulseView else {
return
}
guard let layer = pulseLayer else {
return
}
guard .none != animation else {
return return
} }
...@@ -86,29 +103,29 @@ internal struct MotionPulse<T: UIView> where T: Pulseable { ...@@ -86,29 +103,29 @@ internal struct MotionPulse<T: UIView> where T: Pulseable {
let pLayer = CAShapeLayer() let pLayer = CAShapeLayer()
bLayer.addSublayer(pLayer) bLayer.addSublayer(pLayer)
view.pulseLayer.addSublayer(bLayer) layer.addSublayer(bLayer)
bLayer.zPosition = 0 bLayer.zPosition = 0
pLayer.zPosition = 0 pLayer.zPosition = 0
view.pulseLayers.insert(bLayer, at: 0) layers.insert(bLayer, at: 0)
view.pulseLayer.masksToBounds = !(.centerRadialBeyondBounds == view.pulseAnimation || .radialBeyondBounds == view.pulseAnimation) layer.masksToBounds = !(.centerRadialBeyondBounds == animation || .radialBeyondBounds == animation)
let w = view.width let w = view.width
let h = view.height let h = view.height
Motion.disable(animations: { [ Motion.disable(animations: { [
n = .center == view.pulseAnimation ? w < h ? w : h : w < h ? h : w, n = .center == animation ? w < h ? w : h : w < h ? h : w,
frame = view.pulseLayer.bounds, frame = layer.bounds,
pulseAnimation = view.pulseAnimation, animation = animation,
pulseColor = view.pulseColor, color = color,
pulseOpacity = view.pulseOpacity opacity = opacity
] in ] in
bLayer.frame = frame bLayer.frame = frame
pLayer.bounds = CGRect(x: 0, y: 0, width: n, height: n) pLayer.bounds = CGRect(x: 0, y: 0, width: n, height: n)
switch pulseAnimation { switch animation {
case .center, .centerWithBacking, .centerRadialBeyondBounds: case .center, .centerWithBacking, .centerRadialBeyondBounds:
pLayer.position = CGPoint(x: w / 2, y: h / 2) pLayer.position = CGPoint(x: w / 2, y: h / 2)
default: default:
...@@ -116,21 +133,21 @@ internal struct MotionPulse<T: UIView> where T: Pulseable { ...@@ -116,21 +133,21 @@ internal struct MotionPulse<T: UIView> where T: Pulseable {
} }
pLayer.cornerRadius = n / 2 pLayer.cornerRadius = n / 2
pLayer.backgroundColor = pulseColor.withAlphaComponent(pulseOpacity).cgColor pLayer.backgroundColor = color.withAlphaComponent(opacity).cgColor
pLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(scaleX: 0, y: 0)) pLayer.transform = CATransform3DMakeAffineTransform(CGAffineTransform(scaleX: 0, y: 0))
}) })
bLayer.setValue(false, forKey: "animated") bLayer.setValue(false, forKey: "animated")
let duration: CFTimeInterval = .center == view.pulseAnimation ? 0.16125 : 0.325 let duration: CFTimeInterval = .center == animation ? 0.16125 : 0.325
switch view.pulseAnimation { switch animation {
case .centerWithBacking, .backing, .pointWithBacking: case .centerWithBacking, .backing, .pointWithBacking:
bLayer.add(Motion.backgroundColor(color: view.pulseColor.withAlphaComponent(view.pulseOpacity / 2), duration: duration), forKey: nil) bLayer.add(Motion.backgroundColor(color: color.withAlphaComponent(opacity / 2), duration: duration), forKey: nil)
default:break default:break
} }
switch view.pulseAnimation { switch animation {
case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking: case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:
pLayer.add(Motion.scale(by: 1, duration: duration), forKey: nil) pLayer.add(Motion.scale(by: 1, duration: duration), forKey: nil)
default:break default:break
...@@ -141,14 +158,9 @@ internal struct MotionPulse<T: UIView> where T: Pulseable { ...@@ -141,14 +158,9 @@ internal struct MotionPulse<T: UIView> where T: Pulseable {
} }
} }
/** /// Triggers the contracting animation.
Triggers the contracting animation. public mutating func contractAnimation() {
- Parameter _ view: A Reference to the view to add the guard let bLayer = layers.popLast() else {
animations too.
- Parameter pulse: A Pulse instance.
*/
internal static func contractAnimation(view: inout T) {
guard let bLayer = view.pulseLayers.popLast() else {
return return
} }
...@@ -156,24 +168,24 @@ internal struct MotionPulse<T: UIView> where T: Pulseable { ...@@ -156,24 +168,24 @@ internal struct MotionPulse<T: UIView> where T: Pulseable {
return return
} }
Motion.delay(time: animated ? 0 : 0.15) { [pulseAnimation = view.pulseAnimation, pulseColor = view.pulseColor] in Motion.delay(time: animated ? 0 : 0.15) { [animation = animation, color = color] in
guard let pLayer = bLayer.sublayers?.first as? CAShapeLayer else { guard let pLayer = bLayer.sublayers?.first as? CAShapeLayer else {
return return
} }
let duration = 0.325 let duration = 0.325
switch pulseAnimation { switch animation {
case .centerWithBacking, .backing, .pointWithBacking: case .centerWithBacking, .backing, .pointWithBacking:
bLayer.add(Motion.backgroundColor(color: pulseColor.withAlphaComponent(0), duration: duration), forKey: nil) bLayer.add(Motion.backgroundColor(color: color.withAlphaComponent(0), duration: duration), forKey: nil)
default:break default:break
} }
switch pulseAnimation { switch animation {
case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking: case .center, .centerWithBacking, .centerRadialBeyondBounds, .radialBeyondBounds, .point, .pointWithBacking:
pLayer.add(Motion.animate(group: [ pLayer.add(Motion.animate(group: [
Motion.scale(by: .center == pulseAnimation ? 1 : 1.325), Motion.scale(by: .center == animation ? 1 : 1.325),
Motion.backgroundColor(color: pulseColor.withAlphaComponent(0)) Motion.backgroundColor(color: color.withAlphaComponent(0))
], duration: duration), forKey: nil) ], duration: duration), forKey: nil)
default:break default:break
} }
......
...@@ -32,15 +32,7 @@ import UIKit ...@@ -32,15 +32,7 @@ import UIKit
open class PulseView: View, Pulseable { open class PulseView: View, Pulseable {
/// A Pulse reference. /// A Pulse reference.
internal var pulse = Pulse() open fileprivate(set) var pulse: Pulse!
/// The layer the pulse layers are added to.
internal var pulseLayer: CALayer {
return visualLayer as CALayer
}
/// An Array of pulse layers.
internal var pulseLayers = [CAShapeLayer]()
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -82,13 +74,12 @@ open class PulseView: View, Pulseable { ...@@ -82,13 +74,12 @@ open class PulseView: View, Pulseable {
open func pulse(point: CGPoint? = nil) { open func pulse(point: CGPoint? = nil) {
let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point! let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point!
var s = self pulse.expandAnimation(point: p)
MotionPulse<PulseView>.expandAnimation(view: &s, point: p)
Motion.delay(time: 0.35) { [weak self] in Motion.delay(time: 0.35) { [weak self] in
guard var s = self else { guard let s = self else {
return return
} }
MotionPulse<PulseView>.contractAnimation(view: &s) s.pulse.contractAnimation()
} }
} }
...@@ -100,8 +91,7 @@ open class PulseView: View, Pulseable { ...@@ -100,8 +91,7 @@ open class PulseView: View, Pulseable {
*/ */
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
var s = self pulse.expandAnimation(point: layer.convert(touches.first!.location(in: self), from: layer))
MotionPulse<PulseView>.expandAnimation(view: &s, point: layer.convert(touches.first!.location(in: self), from: layer))
} }
/** /**
...@@ -112,8 +102,7 @@ open class PulseView: View, Pulseable { ...@@ -112,8 +102,7 @@ open class PulseView: View, Pulseable {
*/ */
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<PulseView>.contractAnimation(view: &s)
} }
/** /**
...@@ -124,7 +113,25 @@ open class PulseView: View, Pulseable { ...@@ -124,7 +113,25 @@ open class PulseView: View, Pulseable {
*/ */
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<PulseView>.contractAnimation(view: &s) }
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open override func prepare() {
super.prepare()
preparePulse()
}
}
extension PulseView {
/// Prepares the pulse motion.
fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer)
} }
} }
...@@ -37,18 +37,10 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -37,18 +37,10 @@ open class TableViewCell: UITableViewCell, Pulseable {
allows the dropshadow effect on the backing layer, while clipping allows the dropshadow effect on the backing layer, while clipping
the image to a desired shape within the visualLayer. the image to a desired shape within the visualLayer.
*/ */
open internal(set) var visualLayer = CAShapeLayer() open fileprivate(set) var visualLayer = CAShapeLayer()
/// A Pulse reference. /// A Pulse reference.
internal var pulse = Pulse() open fileprivate(set) var pulse: Pulse!
/// The layer the pulse layers are added to.
internal var pulseLayer: CALayer {
return visualLayer as CALayer
}
/// An Array of pulse layers.
internal var pulseLayers = [CAShapeLayer]()
/// PulseAnimation value. /// PulseAnimation value.
open var pulseAnimation: PulseAnimation { open var pulseAnimation: PulseAnimation {
...@@ -128,13 +120,12 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -128,13 +120,12 @@ open class TableViewCell: UITableViewCell, Pulseable {
open func pulse(point: CGPoint? = nil) { open func pulse(point: CGPoint? = nil) {
let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point! let p = nil == point ? CGPoint(x: CGFloat(width / 2), y: CGFloat(height / 2)) : point!
var s = self pulse.expandAnimation(point: p)
MotionPulse<TableViewCell>.expandAnimation(view: &s, point: p)
Motion.delay(time: 0.35) { [weak self] in Motion.delay(time: 0.35) { [weak self] in
guard var s = self else { guard let s = self else {
return return
} }
MotionPulse<TableViewCell>.contractAnimation(view: &s) s.pulse.contractAnimation()
} }
} }
...@@ -146,8 +137,7 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -146,8 +137,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
*/ */
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event) super.touchesBegan(touches, with: event)
var s = self pulse.expandAnimation(point: layer.convert(touches.first!.location(in: self), from: layer))
MotionPulse<TableViewCell>.expandAnimation(view: &s, point: layer.convert(touches.first!.location(in: self), from: layer))
} }
/** /**
...@@ -158,8 +148,7 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -158,8 +148,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
*/ */
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<TableViewCell>.contractAnimation(view: &s)
} }
/** /**
...@@ -170,8 +159,7 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -170,8 +159,7 @@ open class TableViewCell: UITableViewCell, Pulseable {
*/ */
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event) super.touchesCancelled(touches, with: event)
var s = self pulse.contractAnimation()
MotionPulse<TableViewCell>.contractAnimation(view: &s)
} }
/** /**
...@@ -189,17 +177,27 @@ open class TableViewCell: UITableViewCell, Pulseable { ...@@ -189,17 +177,27 @@ open class TableViewCell: UITableViewCell, Pulseable {
textLabel?.isUserInteractionEnabled = false textLabel?.isUserInteractionEnabled = false
detailTextLabel?.isUserInteractionEnabled = false detailTextLabel?.isUserInteractionEnabled = false
prepareVisualLayer() prepareVisualLayer()
preparePulse()
}
}
extension TableViewCell {
/// Prepares the pulse motion.
fileprivate func preparePulse() {
pulse = Pulse(pulseView: self, pulseLayer: visualLayer)
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
internal func prepareVisualLayer() { fileprivate func prepareVisualLayer() {
visualLayer.zPosition = 0 visualLayer.zPosition = 0
visualLayer.masksToBounds = true visualLayer.masksToBounds = true
contentView.layer.addSublayer(visualLayer) contentView.layer.addSublayer(visualLayer)
} }
}
extension TableViewCell {
/// Manages the layout for the visualLayer property. /// Manages the layout for the visualLayer property.
internal func layoutVisualLayer() { fileprivate func layoutVisualLayer() {
visualLayer.frame = bounds visualLayer.frame = bounds
visualLayer.cornerRadius = cornerRadius visualLayer.cornerRadius = cornerRadius
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment