@applicaster/quick-brick-native-apple 5.16.0 → 5.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apple/QuickBrickApple.podspec.json +2 -2
- package/apple/ios/LocalNotifications/ReactNativeManager+UNUserNotificationCenterDelegate.swift +7 -5
- package/apple/ios/ReactNative/PushBridge.swift +11 -11
- package/apple/ios/ReactNative/QuickBrickExceptionManager.swift +22 -20
- package/apple/ios/ReactNative/QuickBrickViewController.swift +15 -20
- package/apple/ios/ReactNative/ReactNativeManageriOS+UIApplicationDelegate.swift +15 -18
- package/apple/ios/ReactNativeEventEmitter.swift +19 -21
- package/apple/tvos/Helpers/FocusableGroupManager/FocusableGroupManager.swift +39 -39
- package/apple/tvos/Helpers/FocusableGroupManager/FocusableManagerModule.swift +18 -23
- package/apple/tvos/LocalNotifications/ReactNativeManager+UNUserNotificationCenterDelegate.swift +4 -3
- package/apple/tvos/ReactNative/QuickBrickViewController.swift +3 -3
- package/apple/tvos/Views/FocusableGroupView/FocusableGroupView.swift +118 -114
- package/apple/tvos/Views/FocusableGroupView/FocusableGroupViewConsts.swift +19 -19
- package/apple/tvos/Views/FocusableGroupView/FocusableGroupViewModule.swift +10 -10
- package/apple/tvos/Views/FocusableView/FocusableView+ParallaxViewDelegate.swift +14 -20
- package/apple/tvos/Views/FocusableView/FocusableView.swift +38 -40
- package/apple/tvos/Views/FocusableView/FocusableViewModule.swift +8 -9
- package/apple/tvos/Views/ParallaxView/Extensions/ParallaxableView+Extensions.swift +20 -26
- package/apple/tvos/Views/ParallaxView/Extensions/UIView+ParallaxEffect.swift +26 -28
- package/apple/tvos/Views/ParallaxView/Other/ParallaxEffectOptions.swift +5 -9
- package/apple/tvos/Views/ParallaxView/Other/ParallaxMotionEffect.swift +8 -12
- package/apple/tvos/Views/ParallaxView/Other/ParallaxableView.swift +0 -2
- package/apple/tvos/Views/ParallaxView/ParallaxCollectionViewCell.swift +17 -19
- package/apple/tvos/Views/ParallaxView/ParallaxView.swift +29 -31
- package/apple/tvos/Views/ParallaxView/Protocols/ParallaxViewDelegate.swift +6 -7
- package/apple/universal/ReactNative/AnalyticsBridge.swift +3 -3
- package/apple/universal/ReactNative/LocalNotification/LocalNotificationBridge.swift +8 -6
- package/apple/universal/ReactNative/OfflineAssetsBridge.swift +21 -15
- package/apple/universal/ReactNative/PluginsManagerBridge.swift +20 -15
- package/apple/universal/ReactNative/ReactNativeCommunicationModule.swift +15 -13
- package/apple/universal/ReactNative/ReactNativeManager+UIApplicationDelegate.swift +10 -9
- package/apple/universal/ReactNative/ReactNativeManager.swift +12 -9
- package/apple/universal/Storages/LocalStorage/LocalStorageBridge.swift +35 -20
- package/apple/universal/Storages/SessionStorage/SessionStorageBridge.swift +20 -12
- package/apple/universal/Utils/RTLLocales.swift +5 -5
- package/apple/universal/Utils/XrayLoggerTemplates/QuickBrickViewControllerLogs.swift +0 -2
- package/apple/universal/Utils/XrayLoggerTemplates/ReactNativeManagerLogs.swift +0 -1
- package/package.json +1 -1
|
@@ -7,108 +7,106 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
import Foundation
|
|
10
|
-
import UIKit
|
|
11
10
|
import React
|
|
11
|
+
import UIKit
|
|
12
12
|
|
|
13
13
|
/// RCTTVView subclass that has api how to conects to FocusableGroup
|
|
14
14
|
public class FocusableView: ParallaxView {
|
|
15
|
-
|
|
16
|
-
@objc public var
|
|
17
|
-
@objc public var
|
|
18
|
-
@objc public var
|
|
19
|
-
@objc public var isParallaxDisabled:Bool = false {
|
|
15
|
+
@objc public var onViewFocus: RCTBubblingEventBlock?
|
|
16
|
+
@objc public var onViewPress: RCTBubblingEventBlock?
|
|
17
|
+
@objc public var onViewBlur: RCTBubblingEventBlock?
|
|
18
|
+
@objc public var isParallaxDisabled: Bool = false {
|
|
20
19
|
didSet {
|
|
21
20
|
parallaxEffectOptions.parallaxMotionEffect.isDisabled = isParallaxDisabled
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
@objc public var isPressDisabled:Bool = false {
|
|
24
|
+
@objc public var isPressDisabled: Bool = false {
|
|
26
25
|
didSet {
|
|
27
26
|
isPressActionDisabled = isPressDisabled
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
/// Define if view can become focused
|
|
32
31
|
@objc open var focusable = true
|
|
33
|
-
|
|
34
|
-
@objc public var preferredFocus:Bool = false {
|
|
32
|
+
|
|
33
|
+
@objc public var preferredFocus: Bool = false {
|
|
35
34
|
didSet {
|
|
36
35
|
guard preferredFocus else {
|
|
37
36
|
return
|
|
38
37
|
}
|
|
39
38
|
DispatchQueue.main.async { [weak self] in
|
|
40
39
|
if let groupId = self?.groupId,
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
let focusableGroup = focusableGroups[groupId]
|
|
41
|
+
{
|
|
42
|
+
// Update Prefered focus view in group
|
|
43
43
|
focusableGroup.updatePrefferedFocusEnv(with: self!)
|
|
44
|
-
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
}
|
|
48
|
+
|
|
49
49
|
/// Define if this view is preffered tv focused View
|
|
50
|
-
@objc public var forceFocus:Bool = false {
|
|
51
|
-
|
|
50
|
+
@objc public var forceFocus: Bool = false {
|
|
52
51
|
didSet {
|
|
53
52
|
guard forceFocus else {
|
|
54
53
|
return
|
|
55
54
|
}
|
|
56
55
|
DispatchQueue.main.async { [weak self] in
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
FocusableGroupManager.updateFocus(self?.groupId,
|
|
57
|
+
itemId: self?.itemId,
|
|
58
|
+
needsForceUpdate: true,
|
|
59
|
+
completion: nil)
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
public
|
|
66
|
-
|
|
63
|
+
|
|
64
|
+
override public var canBecomeFocused: Bool {
|
|
65
|
+
focusable
|
|
67
66
|
}
|
|
68
|
-
|
|
67
|
+
|
|
69
68
|
/// Define if view was registered
|
|
70
|
-
var isViewRegistered:Bool = false
|
|
69
|
+
var isViewRegistered: Bool = false
|
|
71
70
|
|
|
72
|
-
public
|
|
71
|
+
override public init(frame: CGRect) {
|
|
73
72
|
super.init(frame: frame)
|
|
74
73
|
initialize()
|
|
75
74
|
}
|
|
76
|
-
|
|
75
|
+
|
|
77
76
|
public required init?(coder aDecoder: NSCoder) {
|
|
78
77
|
super.init(coder: aDecoder)
|
|
79
78
|
initialize()
|
|
80
79
|
}
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
|
|
83
81
|
/// Initialize component
|
|
84
82
|
func initialize() {
|
|
85
83
|
delegate = self
|
|
86
84
|
}
|
|
87
|
-
|
|
85
|
+
|
|
88
86
|
/// ID of the View provided by React-Native env
|
|
89
|
-
@objc public var itemId:String? {
|
|
87
|
+
@objc public var itemId: String? {
|
|
90
88
|
didSet {
|
|
91
89
|
registerView()
|
|
92
90
|
}
|
|
93
91
|
}
|
|
94
|
-
|
|
92
|
+
|
|
95
93
|
/// ID of the View provided by React-Native env
|
|
96
|
-
@objc public var groupId:String? {
|
|
94
|
+
@objc public var groupId: String? {
|
|
97
95
|
didSet {
|
|
98
96
|
registerView()
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
|
-
|
|
99
|
+
|
|
102
100
|
/// Register View in FocusableGroupManager
|
|
103
101
|
func registerView() {
|
|
104
102
|
guard itemId != nil,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
groupId != nil,
|
|
104
|
+
isViewRegistered == false,
|
|
105
|
+
FocusableGroupManager.registerView(item: self)
|
|
106
|
+
else {
|
|
107
|
+
return
|
|
109
108
|
}
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
|
|
110
|
+
isViewRegistered = true
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
|
-
|
|
@@ -12,21 +12,20 @@ import React
|
|
|
12
12
|
@objc(FocusableViewModule)
|
|
13
13
|
public class FocusableViewModule: RCTViewManager {
|
|
14
14
|
static let focusableViewModuleName = "FocusableViewModule"
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
override public static func moduleName() -> String? {
|
|
17
|
-
|
|
17
|
+
focusableViewModuleName
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
override public class func requiresMainQueueSetup() -> Bool {
|
|
21
|
-
|
|
21
|
+
true
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
override open var methodQueue: DispatchQueue {
|
|
25
|
-
|
|
25
|
+
bridge.uiManager.methodQueue
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
override public func view() -> UIView? {
|
|
29
|
-
|
|
29
|
+
FocusableView()
|
|
30
30
|
}
|
|
31
|
-
|
|
32
31
|
}
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import UIKit
|
|
10
10
|
|
|
11
|
-
open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
|
|
12
|
-
|
|
11
|
+
open class ParallaxViewActions<T: UIView> where T: ParallaxableView {
|
|
13
12
|
/// Closure will be called in animation block by ParallaxableView when view should change its appearance to the focused state
|
|
14
13
|
open var setupUnfocusedState: ((T) -> Void)?
|
|
15
14
|
/// Closure will be called in animation block by ParallaxableView when view should change its appearance to the unfocused state
|
|
@@ -19,16 +18,16 @@ open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
|
|
|
19
18
|
/// Closure will be called by ParallaxableView before the animation to the unfocused state start
|
|
20
19
|
open var beforeResignFocusAnimation: ((T) -> Void)?
|
|
21
20
|
/// Closure will be called when didFocusChange happened. In most cases default implementation should work
|
|
22
|
-
open var becomeFocused: ((T, _ context: UIFocusUpdateContext, _ animationCoordinator: UIFocusAnimationCoordinator, _ completion
|
|
21
|
+
open var becomeFocused: ((T, _ context: UIFocusUpdateContext, _ animationCoordinator: UIFocusAnimationCoordinator, _ completion: @escaping (() -> Void)) -> Void)?
|
|
23
22
|
/// Closure will be called when didFocusChange happened. In most cases default implementation should work
|
|
24
|
-
open var resignFocus: ((T, _ context: UIFocusUpdateContext, _ animationCoordinator: UIFocusAnimationCoordinator, _ completion
|
|
23
|
+
open var resignFocus: ((T, _ context: UIFocusUpdateContext, _ animationCoordinator: UIFocusAnimationCoordinator, _ completion: @escaping (() -> Void)) -> Void)?
|
|
25
24
|
/// Default implementation of the press begin animation for the ParallaxableView
|
|
26
|
-
open var animatePressIn: ((T, _ presses: Set<UIPress>, _ event: UIPressesEvent?, _ completion
|
|
25
|
+
open var animatePressIn: ((T, _ presses: Set<UIPress>, _ event: UIPressesEvent?, _ completion: @escaping (() -> Void)) -> Void)?
|
|
27
26
|
/// Default implementation of the press ended animation for the ParallaxableView
|
|
28
|
-
open var animatePressOut: ((T, _ presses: Set<UIPress>, _ event: UIPressesEvent?, _ completion
|
|
27
|
+
open var animatePressOut: ((T, _ presses: Set<UIPress>, _ event: UIPressesEvent?, _ completion: @escaping (() -> Void)) -> Void)?
|
|
29
28
|
|
|
30
29
|
public init() {
|
|
31
|
-
becomeFocused = { [weak self] (view: T,
|
|
30
|
+
becomeFocused = { [weak self] (view: T, _, coordinator, completion) in
|
|
32
31
|
self?.beforeBecomeFocusedAnimation?(view)
|
|
33
32
|
|
|
34
33
|
coordinator.addCoordinatedAnimations({
|
|
@@ -37,21 +36,20 @@ open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
|
|
|
37
36
|
}, completion: {
|
|
38
37
|
completion()
|
|
39
38
|
})
|
|
40
|
-
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
resignFocus = { [weak self] (view: T,
|
|
41
|
+
resignFocus = { [weak self] (view: T, _, coordinator, completion) in
|
|
44
42
|
self?.beforeResignFocusAnimation?(view)
|
|
45
43
|
|
|
46
44
|
coordinator.addCoordinatedAnimations({
|
|
47
45
|
view.removeParallaxMotionEffects(with: view.parallaxEffectOptions)
|
|
48
46
|
self?.setupUnfocusedState?(view)
|
|
49
|
-
},
|
|
47
|
+
}, completion: {
|
|
50
48
|
completion()
|
|
51
49
|
})
|
|
52
50
|
}
|
|
53
51
|
|
|
54
|
-
animatePressIn = { (view: T, presses,
|
|
52
|
+
animatePressIn = { (view: T, presses, _, completion) in
|
|
55
53
|
for press in presses {
|
|
56
54
|
if case .select = press.type {
|
|
57
55
|
UIView.animate(withDuration: 0.12, animations: {
|
|
@@ -59,19 +57,17 @@ open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
|
|
|
59
57
|
})
|
|
60
58
|
UIView.animate(withDuration: 0.12, animations: {
|
|
61
59
|
view.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
|
|
62
|
-
}, completion: {
|
|
60
|
+
}, completion: { _ in
|
|
63
61
|
completion()
|
|
64
62
|
})
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
66
|
|
|
69
|
-
animatePressOut = { [weak self] (view: T, presses,
|
|
67
|
+
animatePressOut = { [weak self] (view: T, presses, _, completion) in
|
|
70
68
|
for press in presses {
|
|
71
69
|
if case .select = press.type {
|
|
72
|
-
UIView.animate(withDuration: 0.12, animations: {
|
|
73
|
-
|
|
74
|
-
})
|
|
70
|
+
UIView.animate(withDuration: 0.12, animations: {})
|
|
75
71
|
UIView.animate(withDuration: 0.12, animations: {
|
|
76
72
|
if view.isFocused {
|
|
77
73
|
view.transform = CGAffineTransform.identity
|
|
@@ -80,30 +76,28 @@ open class ParallaxViewActions<T: UIView> where T:ParallaxableView {
|
|
|
80
76
|
view.transform = CGAffineTransform.identity
|
|
81
77
|
self?.setupUnfocusedState?(view)
|
|
82
78
|
}
|
|
83
|
-
}, completion: {
|
|
79
|
+
}, completion: { _ in
|
|
84
80
|
completion()
|
|
85
81
|
})
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
|
-
|
|
91
86
|
}
|
|
92
87
|
|
|
93
88
|
public extension ParallaxableView where Self: UIView {
|
|
94
|
-
|
|
95
89
|
// MARK: Properties
|
|
96
90
|
|
|
97
91
|
/// Configure radius for parallaxView and glow effect if needed
|
|
98
92
|
var cornerRadius: CGFloat {
|
|
99
93
|
get {
|
|
100
|
-
|
|
94
|
+
layer.cornerRadius
|
|
101
95
|
}
|
|
102
96
|
set {
|
|
103
|
-
|
|
97
|
+
layer.cornerRadius = newValue
|
|
104
98
|
|
|
105
99
|
// Change the glowEffectContainerView corner radius only if it is a direct subview of the parallax view
|
|
106
|
-
if let glowEffectContainerView = parallaxEffectOptions.glowContainerView
|
|
100
|
+
if let glowEffectContainerView = parallaxEffectOptions.glowContainerView, subviews.contains(glowEffectContainerView) {
|
|
107
101
|
glowEffectContainerView.layer.cornerRadius = newValue
|
|
108
102
|
}
|
|
109
103
|
}
|
|
@@ -117,13 +111,13 @@ public extension ParallaxableView where Self: UIView {
|
|
|
117
111
|
- returns: Image with radial gradient/shadow to imitate glow
|
|
118
112
|
*/
|
|
119
113
|
func getGlowImageView() -> UIImageView? {
|
|
120
|
-
|
|
114
|
+
parallaxEffectOptions.glowContainerView?.subviews.filter { view -> Bool in
|
|
121
115
|
if let glowImageView = view as? UIImageView,
|
|
122
|
-
|
|
116
|
+
let glowImage = glowImageView.image, glowImage.accessibilityIdentifier == glowImageAccessibilityIdentifier
|
|
117
|
+
{
|
|
123
118
|
return true
|
|
124
119
|
}
|
|
125
120
|
return false
|
|
126
|
-
}
|
|
121
|
+
}.first as? UIImageView
|
|
127
122
|
}
|
|
128
|
-
|
|
129
123
|
}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
//
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
-
import UIKit
|
|
10
9
|
import React
|
|
10
|
+
import UIKit
|
|
11
11
|
|
|
12
12
|
public protocol AnyParallaxableView {
|
|
13
13
|
func addParallaxMotionEffects()
|
|
@@ -16,7 +16,6 @@ public protocol AnyParallaxableView {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
extension UIView: AnyParallaxableView {
|
|
19
|
-
|
|
20
19
|
public func addParallaxMotionEffects() {
|
|
21
20
|
var options = ParallaxEffectOptions()
|
|
22
21
|
addParallaxMotionEffects(with: &options)
|
|
@@ -63,84 +62,83 @@ extension UIView: AnyParallaxableView {
|
|
|
63
62
|
//
|
|
64
63
|
let motionGroup = UIMotionEffectGroup()
|
|
65
64
|
motionGroup.motionEffects = []
|
|
66
|
-
|
|
65
|
+
|
|
67
66
|
// Add parallax effect
|
|
68
67
|
motionGroup.motionEffects?.append(options.parallaxMotionEffect)
|
|
69
|
-
|
|
68
|
+
|
|
70
69
|
// Configure shadow pan motion effect
|
|
71
70
|
if options.shadowPanDeviation != 0 {
|
|
72
71
|
let veriticalShadowEffect = UIInterpolatingMotionEffect(keyPath: "layer.shadowOffset.height", type: .tiltAlongVerticalAxis)
|
|
73
72
|
veriticalShadowEffect.minimumRelativeValue = -options.shadowPanDeviation
|
|
74
|
-
veriticalShadowEffect.maximumRelativeValue = options.shadowPanDeviation/2
|
|
75
|
-
|
|
73
|
+
veriticalShadowEffect.maximumRelativeValue = options.shadowPanDeviation / 2
|
|
74
|
+
|
|
76
75
|
let horizontalShadowEffect = UIInterpolatingMotionEffect(keyPath: "layer.shadowOffset.width", type: .tiltAlongHorizontalAxis)
|
|
77
76
|
horizontalShadowEffect.minimumRelativeValue = -options.shadowPanDeviation
|
|
78
77
|
horizontalShadowEffect.maximumRelativeValue = options.shadowPanDeviation
|
|
79
|
-
|
|
78
|
+
|
|
80
79
|
motionGroup.motionEffects?.append(contentsOf: [veriticalShadowEffect, horizontalShadowEffect])
|
|
81
80
|
}
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
addMotionEffect(motionGroup)
|
|
84
|
-
|
|
83
|
+
|
|
85
84
|
// Configure pan motion effect for the subviews
|
|
86
85
|
if case .none = options.subviewsParallaxMode {
|
|
87
86
|
} else {
|
|
88
|
-
if
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
if subviews.count > 1,
|
|
88
|
+
let rnView = subviews[1] as? RCTTVView,
|
|
89
|
+
let subviews = findSubview(view: rnView)
|
|
90
|
+
{
|
|
91
91
|
subviews.filter { $0 !== options.glowContainerView }
|
|
92
92
|
.enumerated()
|
|
93
93
|
.forEach { (index: Int, subview: UIView) in
|
|
94
94
|
let relativePanValue: Double
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
switch options.subviewsParallaxMode {
|
|
97
|
-
case .basedOnHierarchyInParallaxView(
|
|
98
|
-
relativePanValue = maxOffset /
|
|
97
|
+
case let .basedOnHierarchyInParallaxView(maxOffset, multipler):
|
|
98
|
+
relativePanValue = maxOffset / Double(index + 1) * (multipler ?? 1.0)
|
|
99
99
|
case .basedOnTag:
|
|
100
100
|
relativePanValue = Double(subview.tag)
|
|
101
101
|
default:
|
|
102
102
|
relativePanValue = 0.0
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
let verticalSubviewEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
|
106
106
|
verticalSubviewEffect.minimumRelativeValue = -relativePanValue
|
|
107
107
|
verticalSubviewEffect.maximumRelativeValue = relativePanValue
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
let horizontalSubviewEffect = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
|
110
110
|
horizontalSubviewEffect.minimumRelativeValue = -relativePanValue
|
|
111
111
|
horizontalSubviewEffect.maximumRelativeValue = relativePanValue
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
let group = UIMotionEffectGroup()
|
|
114
114
|
group.motionEffects = [verticalSubviewEffect, horizontalSubviewEffect]
|
|
115
115
|
subview.addMotionEffect(group)
|
|
116
|
-
|
|
117
|
-
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
-
|
|
121
|
-
func findSubview(view:UIView?) -> [UIView]? {
|
|
122
|
-
|
|
120
|
+
|
|
121
|
+
func findSubview(view: UIView?) -> [UIView]? {
|
|
123
122
|
if let subviews = view?.subviews {
|
|
124
123
|
if subviews.count > 1 {
|
|
125
124
|
return subviews
|
|
126
125
|
} else {
|
|
127
|
-
|
|
126
|
+
return findSubview(view: subviews.first)
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
|
-
|
|
129
|
+
|
|
131
130
|
return nil
|
|
132
131
|
}
|
|
133
|
-
|
|
132
|
+
|
|
134
133
|
public func removeParallaxMotionEffects(with options: ParallaxEffectOptions? = nil) {
|
|
135
134
|
motionEffects.removeAll()
|
|
136
135
|
(options?.parallaxSubviewsContainer ?? self).subviews
|
|
137
136
|
.filter { $0 !== options?.glowContainerView }
|
|
138
137
|
.forEach { (subview: UIView) in
|
|
139
138
|
subview.motionEffects.removeAll()
|
|
140
|
-
|
|
139
|
+
}
|
|
141
140
|
|
|
142
141
|
// options?.glowImageView.motionEffects.removeAll()
|
|
143
142
|
// options?.glowImageView.removeFromSuperview()
|
|
144
143
|
}
|
|
145
|
-
|
|
146
144
|
}
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
import UIKit
|
|
10
10
|
|
|
11
11
|
public struct ParallaxEffectOptions {
|
|
12
|
-
|
|
13
12
|
/// Property allow to customize parallax effect (pan, angles, etc.)
|
|
14
13
|
///
|
|
15
14
|
/// - seealso:
|
|
@@ -41,27 +40,24 @@ public struct ParallaxEffectOptions {
|
|
|
41
40
|
self.parallaxSubviewsContainer = parallaxSubviewsContainer
|
|
42
41
|
self.glowContainerView = glowContainerView
|
|
43
42
|
}
|
|
44
|
-
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
internal let glowImageAccessibilityIdentifier = "com.applicaster"
|
|
48
46
|
|
|
49
47
|
extension ParallaxEffectOptions {
|
|
50
|
-
|
|
51
48
|
static func defaultGlowImageView() -> UIImageView {
|
|
52
|
-
|
|
53
49
|
if case let bundle = Bundle(for: ParallaxView.self),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
let glowImage = UIImage(named: "gloweffect",
|
|
51
|
+
in: bundle,
|
|
52
|
+
compatibleWith: nil)
|
|
53
|
+
{
|
|
57
54
|
glowImage.accessibilityIdentifier = glowImageAccessibilityIdentifier
|
|
58
55
|
let imageView = UIImageView(image: glowImage)
|
|
59
56
|
imageView.contentMode = .scaleAspectFit
|
|
60
|
-
|
|
57
|
+
|
|
61
58
|
return UIImageView(image: glowImage)
|
|
62
59
|
} else {
|
|
63
60
|
fatalError("Can't initialize gloweffect image")
|
|
64
61
|
}
|
|
65
62
|
}
|
|
66
|
-
|
|
67
63
|
}
|
|
@@ -8,36 +8,33 @@
|
|
|
8
8
|
import UIKit
|
|
9
9
|
|
|
10
10
|
open class ParallaxMotionEffect: UIMotionEffect {
|
|
11
|
-
|
|
12
11
|
// MARK: Properties
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
|
|
15
13
|
/// Disables Motion Effect
|
|
16
14
|
open var isDisabled = false
|
|
17
|
-
|
|
15
|
+
|
|
18
16
|
/// How far camera is from the object
|
|
19
17
|
open var cameraPositionZ = CGFloat(0)
|
|
20
18
|
|
|
21
19
|
/// The maximum angle horizontally
|
|
22
|
-
open var viewingAngleX = CGFloat(Double.pi/4/8)
|
|
20
|
+
open var viewingAngleX = CGFloat(Double.pi / 4 / 8)
|
|
23
21
|
|
|
24
22
|
/// The maximum angle vertically
|
|
25
|
-
open var viewingAngleY = CGFloat(Double.pi/4/8)
|
|
23
|
+
open var viewingAngleY = CGFloat(Double.pi / 4 / 8)
|
|
26
24
|
|
|
27
25
|
/// Maximum deviation relative to the center
|
|
28
26
|
open var panValue = CGFloat(10)
|
|
29
27
|
|
|
30
28
|
/// Perspective value. The closer is to 0 the deepest is the perspective
|
|
31
|
-
open var m34 = CGFloat(-1.0/700)
|
|
29
|
+
open var m34 = CGFloat(-1.0 / 700)
|
|
32
30
|
|
|
33
31
|
// MARK: UIMotionEffect
|
|
34
32
|
|
|
35
|
-
override open func keyPathsAndRelativeValues(forViewerOffset viewerOffset: UIOffset) -> [String
|
|
36
|
-
|
|
33
|
+
override open func keyPathsAndRelativeValues(forViewerOffset viewerOffset: UIOffset) -> [String: Any]? {
|
|
37
34
|
guard isDisabled == false else {
|
|
38
35
|
return nil
|
|
39
36
|
}
|
|
40
|
-
|
|
37
|
+
|
|
41
38
|
var transform = CATransform3DIdentity
|
|
42
39
|
transform.m34 = m34
|
|
43
40
|
|
|
@@ -45,12 +42,11 @@ open class ParallaxMotionEffect: UIMotionEffect {
|
|
|
45
42
|
newViewerOffset.horizontal = newViewerOffset.horizontal <= -1.0 ? -1.0 : newViewerOffset.horizontal
|
|
46
43
|
newViewerOffset.vertical = newViewerOffset.vertical <= -1.0 ? -1.0 : newViewerOffset.vertical
|
|
47
44
|
|
|
48
|
-
transform = CATransform3DTranslate(transform, panValue*newViewerOffset.horizontal, panValue*newViewerOffset.vertical, cameraPositionZ)
|
|
45
|
+
transform = CATransform3DTranslate(transform, panValue * newViewerOffset.horizontal, panValue * newViewerOffset.vertical, cameraPositionZ)
|
|
49
46
|
|
|
50
47
|
transform = CATransform3DRotate(transform, viewingAngleX * newViewerOffset.vertical, 1, 0, 0)
|
|
51
48
|
transform = CATransform3DRotate(transform, viewingAngleY * -newViewerOffset.horizontal, 0, 1, 0)
|
|
52
49
|
|
|
53
50
|
return ["layer.transform": NSValue(caTransform3D: transform)]
|
|
54
51
|
}
|
|
55
|
-
|
|
56
52
|
}
|
|
@@ -8,15 +8,14 @@
|
|
|
8
8
|
import UIKit
|
|
9
9
|
|
|
10
10
|
open class ParallaxCollectionViewCell: UICollectionViewCell, ParallaxableView {
|
|
11
|
-
|
|
12
11
|
// MARK: Properties
|
|
13
12
|
|
|
14
13
|
open var parallaxEffectOptions = ParallaxEffectOptions()
|
|
15
14
|
open var parallaxViewActions = ParallaxViewActions<ParallaxCollectionViewCell>()
|
|
16
15
|
|
|
17
16
|
// MARK: Initialization
|
|
18
|
-
|
|
19
|
-
public
|
|
17
|
+
|
|
18
|
+
override public init(frame: CGRect) {
|
|
20
19
|
super.init(frame: frame)
|
|
21
20
|
|
|
22
21
|
commonInit()
|
|
@@ -44,19 +43,19 @@ open class ParallaxCollectionViewCell: UICollectionViewCell, ParallaxableView {
|
|
|
44
43
|
parallaxEffectOptions.parallaxSubviewsContainer = contentView
|
|
45
44
|
}
|
|
46
45
|
|
|
47
|
-
parallaxViewActions.setupUnfocusedState = { [weak self]
|
|
46
|
+
parallaxViewActions.setupUnfocusedState = { [weak self] view in
|
|
48
47
|
guard let _self = self else { return }
|
|
49
48
|
view.transform = CGAffineTransform.identity
|
|
50
49
|
|
|
51
|
-
view.layer.shadowOffset = CGSize(width: 0, height: _self.bounds.height*0.015)
|
|
50
|
+
view.layer.shadowOffset = CGSize(width: 0, height: _self.bounds.height * 0.015)
|
|
52
51
|
view.layer.shadowRadius = 5
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
parallaxViewActions.setupFocusedState = { [weak self]
|
|
54
|
+
parallaxViewActions.setupFocusedState = { [weak self] view in
|
|
56
55
|
guard let _self = self else { return }
|
|
57
56
|
view.transform = CGAffineTransform(scaleX: 1.15, y: 1.15)
|
|
58
57
|
|
|
59
|
-
view.layer.shadowOffset = CGSize(width: 0, height: _self.bounds.height*0.12)
|
|
58
|
+
view.layer.shadowOffset = CGSize(width: 0, height: _self.bounds.height * 0.12)
|
|
60
59
|
view.layer.shadowRadius = 15
|
|
61
60
|
}
|
|
62
61
|
|
|
@@ -66,7 +65,7 @@ open class ParallaxCollectionViewCell: UICollectionViewCell, ParallaxableView {
|
|
|
66
65
|
|
|
67
66
|
// MARK: UIView
|
|
68
67
|
|
|
69
|
-
open
|
|
68
|
+
override open func layoutSubviews() {
|
|
70
69
|
super.layoutSubviews()
|
|
71
70
|
|
|
72
71
|
guard let glowEffectContainerView = parallaxEffectOptions.glowContainerView else { return }
|
|
@@ -75,45 +74,45 @@ open class ParallaxCollectionViewCell: UICollectionViewCell, ParallaxableView {
|
|
|
75
74
|
glowEffectContainerView.frame = glowSuperView.bounds
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
let maxSize = max(glowEffectContainerView.frame.width, glowEffectContainerView.frame.height)*1.7
|
|
77
|
+
let maxSize = max(glowEffectContainerView.frame.width, glowEffectContainerView.frame.height) * 1.7
|
|
79
78
|
// Make glow a litte bit bigger than the superview
|
|
80
79
|
|
|
81
80
|
guard let glowImageView = getGlowImageView() else { return }
|
|
82
81
|
|
|
83
82
|
glowImageView.frame = CGRect(x: 0, y: 0, width: maxSize, height: maxSize)
|
|
84
83
|
// Position in the middle and under the top edge of the superview
|
|
85
|
-
glowImageView.center = CGPoint(x: glowEffectContainerView.frame.width/2, y: -glowImageView.frame.height)
|
|
84
|
+
glowImageView.center = CGPoint(x: glowEffectContainerView.frame.width / 2, y: -glowImageView.frame.height)
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
// MARK: UIResponder
|
|
89
88
|
|
|
90
89
|
// Generally, all responders which do custom touch handling should override all four of these methods.
|
|
91
90
|
// If you want to customize animations for press events do not forget to call super.
|
|
92
|
-
open
|
|
91
|
+
override open func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
|
|
93
92
|
parallaxViewActions.animatePressIn?(self, presses, event, {})
|
|
94
93
|
|
|
95
94
|
super.pressesBegan(presses, with: event)
|
|
96
95
|
}
|
|
97
96
|
|
|
98
|
-
open
|
|
99
|
-
parallaxViewActions.animatePressOut?(self, presses, event,{})
|
|
97
|
+
override open func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
|
|
98
|
+
parallaxViewActions.animatePressOut?(self, presses, event, {})
|
|
100
99
|
|
|
101
100
|
super.pressesCancelled(presses, with: event)
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
open
|
|
105
|
-
parallaxViewActions.animatePressOut?(self, presses, event,{})
|
|
103
|
+
override open func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
|
|
104
|
+
parallaxViewActions.animatePressOut?(self, presses, event, {})
|
|
106
105
|
|
|
107
106
|
super.pressesEnded(presses, with: event)
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
open
|
|
109
|
+
override open func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
|
|
111
110
|
super.pressesChanged(presses, with: event)
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
// MARK: UIFocusEnvironment
|
|
115
114
|
|
|
116
|
-
open
|
|
115
|
+
override open func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
|
|
117
116
|
super.didUpdateFocus(in: context, with: coordinator)
|
|
118
117
|
|
|
119
118
|
if self == context.nextFocusedView {
|
|
@@ -121,8 +120,7 @@ open class ParallaxCollectionViewCell: UICollectionViewCell, ParallaxableView {
|
|
|
121
120
|
parallaxViewActions.becomeFocused?(self, context, coordinator, {})
|
|
122
121
|
} else if self == context.previouslyFocusedView {
|
|
123
122
|
// Remove parallax effect
|
|
124
|
-
parallaxViewActions.resignFocus?(self, context, coordinator,{})
|
|
123
|
+
parallaxViewActions.resignFocus?(self, context, coordinator, {})
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
|
-
|
|
128
126
|
}
|