Skip to content

Commit

Permalink
Format the code and add documentation comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Łukasz Śliwiński committed Aug 4, 2020
1 parent bf3c2ae commit a4165b0
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 56 deletions.
112 changes: 67 additions & 45 deletions Sources/Extensions/ParallaxableView+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

import UIKit

open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
/// Actions for a parallax view
open class ParallaxViewActions<T: UIView> where T: ParallaxableView {

/// Closure will be called in animation block by ParallaxableView when view should change its appearance to the focused state
open var setupUnfocusedState: ((T) -> Void)?
Expand All @@ -27,102 +28,123 @@ open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
/// Default implementation of the press ended animation for the ParallaxableView
open var animatePressOut: ((T, _ presses: Set<UIPress>, _ event: UIPressesEvent?) -> Void)?

/// Creates actions for parallax view with default behaviours
public init() {
becomeFocused = { [weak self] (view: T, context, coordinator) in
self?.beforeBecomeFocusedAnimation?(view)

if #available(tvOS 11.0, *) {
coordinator.addCoordinatedFocusingAnimations({ (context) in
self?.setupFocusedState?(view)
view.addParallaxMotionEffects(with: &view.parallaxEffectOptions)
}, completion: nil)
coordinator.addCoordinatedFocusingAnimations(
{ (context) in
self?.setupFocusedState?(view)
view.addParallaxMotionEffects(with: &view.parallaxEffectOptions)
},
completion: nil
)
} else {
coordinator.addCoordinatedAnimations({
view.addParallaxMotionEffects(with: &view.parallaxEffectOptions)
self?.setupFocusedState?(view)
}, completion: nil)
coordinator.addCoordinatedAnimations(
{
view.addParallaxMotionEffects(with: &view.parallaxEffectOptions)
self?.setupFocusedState?(view)
},
completion: nil
)
}
}

resignFocus = { [weak self] (view: T, context, coordinator) in
self?.beforeResignFocusAnimation?(view)

if #available(tvOS 11.0, *) {
coordinator.addCoordinatedUnfocusingAnimations({ (context) in
view.removeParallaxMotionEffects(with: view.parallaxEffectOptions)
self?.setupUnfocusedState?(view)
}, completion: nil)
coordinator.addCoordinatedUnfocusingAnimations(
{ (context) in
view.removeParallaxMotionEffects(with: view.parallaxEffectOptions)
self?.setupUnfocusedState?(view)
},
completion: nil
)
} else {
coordinator.addCoordinatedAnimations({
view.removeParallaxMotionEffects(with: view.parallaxEffectOptions)
self?.setupUnfocusedState?(view)
}, completion: nil)
coordinator.addCoordinatedAnimations(
{
view.removeParallaxMotionEffects(with: view.parallaxEffectOptions)
self?.setupUnfocusedState?(view)
},
completion: nil
)
}
}

animatePressIn = { (view: T, presses, event) in
for press in presses {
if case .select = press.type {
UIView.animate(withDuration: 0.12, animations: {
view.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
})
UIView.animate(
withDuration: 0.12,
animations: {
view.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
}
)
}
}
}

animatePressOut = { [weak self] (view: T, presses, event) in
for press in presses {
if case .select = press.type {
UIView.animate(withDuration: 0.12, animations: {
if view.isFocused {
view.transform = CGAffineTransform.identity
self?.setupFocusedState?(view)
} else {
view.transform = CGAffineTransform.identity
self?.setupUnfocusedState?(view)
UIView.animate(
withDuration: 0.12,
animations: {
if view.isFocused {
view.transform = CGAffineTransform.identity
self?.setupFocusedState?(view)
} else {
view.transform = CGAffineTransform.identity
self?.setupUnfocusedState?(view)
}
}
})
)
}
}
}
}

}

public extension ParallaxableView where Self: UIView {
extension ParallaxableView where Self: UIView {

// MARK: Properties

/// Configure radius for parallaxView and glow effect if needed
var cornerRadius: CGFloat {
/// The corner radius for the parallax view and if applicable also applied to the glow effect
public var cornerRadius: CGFloat {
get {
return self.layer.cornerRadius
}
set {
self.layer.cornerRadius = newValue

// Change the glowEffectContainerView corner radius only if it is a direct subview of the parallax view
if let glowEffectContainerView = parallaxEffectOptions.glowContainerView , self.subviews.contains(glowEffectContainerView) {
if let glowEffectContainerView = parallaxEffectOptions.glowContainerView,
self.subviews.contains(glowEffectContainerView)
{
glowEffectContainerView.layer.cornerRadius = newValue
}
}
}

// MARK: ParallaxableView

/**
Get the glow image view that can be used to create the glow effect

- returns: Image with radial gradient/shadow to imitate glow
*/
func getGlowImageView() -> UIImageView? {
return parallaxEffectOptions.glowContainerView?.subviews.filter({ (view) -> Bool in
if let glowImageView = view as? UIImageView,
let glowImage = glowImageView.image , glowImage.accessibilityIdentifier == glowImageAccessibilityIdentifier {
return true
}
return false
}).first as? UIImageView
/// Get the glow image view that can be used to create the glow effect
/// - Returns: Image with radial gradient/shadow to imitate glow
public func getGlowImageView() -> UIImageView? {
return
parallaxEffectOptions.glowContainerView?.subviews.filter({ (view) -> Bool in
if let glowImageView = view as? UIImageView,
let glowImage = glowImageView.image,
glowImage.accessibilityIdentifier == glowImageAccessibilityIdentifier
{
return true
}
return false
}).first as? UIImageView
}

}
11 changes: 9 additions & 2 deletions Sources/Extensions/UIView+ParallaxEffect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@

import UIKit

/// A type of a view that can have parallax effect
public protocol AnyParallaxableView {
func addParallaxMotionEffects()
func addParallaxMotionEffects(with options: inout ParallaxEffectOptions)
func removeParallaxMotionEffects(with options: ParallaxEffectOptions?)
}

extension UIView: AnyParallaxableView {


/// Adds parallax motion effect to the view with default motion effect options
public func addParallaxMotionEffects() {
var options = ParallaxEffectOptions()
addParallaxMotionEffects(with: &options)
}

/// Adds parallax motion effect to the view with passed options
/// - Parameter options: Parallax motion effect options to customize the effect
public func addParallaxMotionEffects(with options: inout ParallaxEffectOptions) {
// If glow have to be visible and glowContainerView is not given then set it to self
if options.glowContainerView == nil && options.glowAlpha > 0.0 {
Expand Down Expand Up @@ -122,7 +126,10 @@ extension UIView: AnyParallaxableView {
}
}
}


/// Removes parallax motion effect from the view
/// - Parameter options: If parallax motion effect was added with custom options, the same options should be
/// passed in this paramter to properly remove the effect
public func removeParallaxMotionEffects(with options: ParallaxEffectOptions? = nil) {
motionEffects.removeAll()
(options?.parallaxSubviewsContainer ?? self).subviews
Expand Down
5 changes: 3 additions & 2 deletions Sources/Other/ParallaxEffectOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

import UIKit

/// A type that allows to customize parallax effet
/// A type that allows to customize parallax effect
public struct ParallaxEffectOptions {

/// Property allow to customize parallax effect (pan, angles, etc.)
/// A property to allow customize parallax effect (pan, angles, etc.)
///
/// - seealso:
/// [ParallaxMotionEffect](ParallaxMotionEffect)
Expand Down Expand Up @@ -74,6 +74,7 @@ extension ParallaxEffectOptions {
glowImageView.center = CGPoint(x: glowEffectContainerView.frame.width/2, y: -glowImageView.frame.height/2)
})
}

}

internal let glowImageAccessibilityIdentifier = "com.pgs-soft.parallaxview.gloweffect"
Expand Down
6 changes: 3 additions & 3 deletions Sources/Other/ParallaxableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import UIKit

/// A type that can have parallax view representation
public protocol ParallaxableView: class {

/// Parallax effects options
var parallaxEffectOptions: ParallaxEffectOptions { get set }

/// The radius to use when
var cornerRadius: CGFloat { get set }

}
5 changes: 3 additions & 2 deletions Sources/Other/SkipFirstOffsetInterpolatingMotionEffect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import UIKit

final class SkipFirstOffsetInterpolatingMotionEffectDecorator: UIMotionEffect {
internal final class SkipFirstOffsetInterpolatingMotionEffectDecorator: UIMotionEffect {

private let decoratee: UIMotionEffect
private var motionDidNotStart: Bool = true
Expand All @@ -27,11 +27,12 @@ final class SkipFirstOffsetInterpolatingMotionEffectDecorator: UIMotionEffect {
if motionDidNotStart, viewerOffset.horizontal + viewerOffset.vertical != 0 {
return nil
}

return decoratee.keyPathsAndRelativeValues(forViewerOffset: viewerOffset)
}
}

extension UIMotionEffect {
internal extension UIMotionEffect {

func decorateWithSkipFirstOffset() -> UIMotionEffect {
return SkipFirstOffsetInterpolatingMotionEffectDecorator(decoratee: self)
Expand Down
1 change: 1 addition & 0 deletions Sources/Other/SubviewsParallaxMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation

/// Modes of parallax motion effect that will be used for the subviews of the parallax view
public enum SubviewsParallaxMode {
/// maxParallaxOffset will be divided by the index of the subview inside `ParallaxView`.
/// So view that is the last subview of the `ParallaxView` will be have the biggest offset equal to `maxParallaxOffset`
Expand Down
2 changes: 1 addition & 1 deletion Sources/Views/ParallaxCollectionViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import UIKit

/// It provides default implementation of the parallax effect for the `UICollectionViewCell`.
/// An object that provides default implementation of the parallax effect for the `UICollectionViewCell`.
/// Most of the time you will subclass this class as you would with `UICollectionViewCell` to provide custom content.
/// If you will override `init` method it is important to provide default setup for the unfocused state of the view
/// e.g. `parallaxViewActions.setupUnfocusedState?(self)`
Expand Down
2 changes: 1 addition & 1 deletion Sources/Views/ParallaxView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import UIKit

/// It provides default implementation of the parallax effect for the `UIView`.
/// An object that provides default implementation of the parallax effect for the `UIView`.
/// If you will override `init` method it is important to provide default setup for the unfocused state of the view
/// e.g. `parallaxViewActions.setupUnfocusedState?(self)`
open class ParallaxView: UIView, ParallaxableView {
Expand Down

0 comments on commit a4165b0

Please sign in to comment.