Skip to content

Commit 4d2a0f4

Browse files
committed
iOS animation tweaks
1 parent dd8f14e commit 4d2a0f4

File tree

4 files changed

+61
-48
lines changed

4 files changed

+61
-48
lines changed

common/src/iosMain/kotlin/com/willowtreeapps/common/UI.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ import kotlin.coroutines.CoroutineContext
1212
*/
1313
class UI : CoroutineDispatcher() {
1414
override fun dispatch(context: CoroutineContext, block: Runnable) {
15-
Logger.d("dispatching block")
1615
val queue = dispatch_get_main_queue()
1716
dispatch_async(queue) {
18-
Logger.d("inside dispatched block")
1917
block.run()
2018
}
2119
}

iOS/NameGame/NameGame/Base.lproj/Main.storyboard

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1111
</dependencies>
1212
<scenes>
13-
<!--Start Screen View Controller-->
13+
<!--Start View Controller-->
1414
<scene sceneID="tne-QT-ifu">
1515
<objects>
1616
<viewController storyboardIdentifier="startScreen" id="BYZ-38-t0r" customClass="StartViewController" customModule="NameGame" customModuleProvider="target" sceneMemberID="viewController">
@@ -32,7 +32,7 @@
3232
<rect key="frame" x="0.0" y="0.0" width="375" height="492"/>
3333
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
3434
</imageView>
35-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Name Game" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Bf-oQ-a1f">
35+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Name Game" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Bf-oQ-a1f">
3636
<rect key="frame" x="123" y="396" width="129" height="29"/>
3737
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
3838
<fontDescription key="fontDescription" type="system" pointSize="24"/>

iOS/NameGame/NameGame/ImageUtils.swift

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,32 @@
88

99
import Foundation
1010
import UIKit
11+
import main
1112

1213
public extension UIImageView {
13-
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
14+
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit, onComplete: @escaping () -> ()) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
1415
contentMode = mode
1516
URLSession.shared.dataTask(with: url) { data, response, error in
1617
guard
17-
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
18-
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
19-
let data = data, error == nil,
20-
let image = UIImage(data: data)
21-
else { return }
18+
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
19+
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
20+
let data = data, error == nil,
21+
let image = UIImage(data: data)
22+
else {
23+
Logger().d(message: "error fetching image " + url.absoluteString + " " + error!.localizedDescription)
24+
return
25+
}
2226
DispatchQueue.main.async() {
2327
self.image = image
28+
onComplete()
2429
}
25-
}.resume()
30+
}.resume()
2631
}
27-
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
28-
guard let url = URL(string: link) else { return }
29-
downloaded(from: url, contentMode: mode)
32+
33+
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit, onComplete: @escaping () -> ()) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
34+
guard let url = URL(string: link) else {
35+
return
36+
}
37+
downloaded(from: url, contentMode: mode, onComplete: onComplete)
3038
}
3139
}

iOS/NameGame/NameGame/QuestionViewController.swift

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@ class QuestionViewController: UIViewController, QuestionView {
1212
@IBOutlet weak var button4: UIButton!
1313
@IBOutlet weak var buttonNext: UIButton!
1414
@IBOutlet weak var buttonEndGame: UIButton!
15-
15+
1616
@IBAction func onAnswerTap(_ sender: Any) {
1717
presenter?.namePicked(name: (sender as? UIButton)!.titleLabel!.text!)
1818
}
19-
20-
@IBAction func onNextTreeTap(_ sender: Any) { presenter?.nextTapped() }
21-
22-
@IBAction func onEndGameTap(_ sender: Any) { presenter?.endGameTapped() }
23-
19+
20+
@IBAction func onNextTreeTap(_ sender: Any) {
21+
presenter?.nextTapped()
22+
}
23+
24+
@IBAction func onEndGameTap(_ sender: Any) {
25+
presenter?.endGameTapped()
26+
}
27+
2428
var presenter: QuestionPresenter?
2529
var confettiView: SAConfettiView?
2630
var restoreX: CGFloat?
@@ -29,50 +33,52 @@ class QuestionViewController: UIViewController, QuestionView {
2933
var lastSelectedBtn: UIButton?
3034
var lastSelectedColor: UIColor?
3135

32-
36+
3337
override func viewWillAppear(_ animated: Bool) {
3438
confettiView = SAConfettiView(frame: self.view.bounds)
3539
self.view.addSubview(confettiView!)
3640
confettiView?.isUserInteractionEnabled = false
3741
let appDelegate = UIApplication.shared.delegate as! AppDelegate
3842
presenter = appDelegate.gameEngine!.attachView(view: self) as? QuestionPresenter
3943
}
40-
44+
4145
override func viewDidDisappear(_ animated: Bool) {
4246
let appDelegate = UIApplication.shared.delegate as! AppDelegate
4347
appDelegate.gameEngine!.detachView(presenter: presenter!)
4448
if (isMovingFromParent) {
4549
presenter?.onBackPressed()
4650
}
4751
}
48-
52+
4953
func showProfile(viewState: QuestionViewState) {
5054
stopCelebration()
5155
if (!buttonNext.isHidden) {
52-
fadeNextButton { self.setProfileAndFadeIn(viewState: viewState) }
56+
fadeNextButton {
57+
self.setProfileAndFadeIn(viewState: viewState)
58+
}
5359
} else {
5460
setProfileAndFadeIn(viewState: viewState)
5561
}
5662
}
57-
63+
5864
func showCorrectAnswer(viewState: QuestionViewState) {
5965
hideButtonsShowNext(viewState: viewState, isEndGame: false)
6066
celebrate()
6167
}
62-
68+
6369
func showWrongAnswer(viewState: QuestionViewState) {
6470
wrongShakeAnimation(viewState: viewState, after: { self.hideButtonsShowNext(viewState: viewState, isEndGame: false) })
6571
}
66-
72+
6773
func showCorrectAnswerEndGame(viewState: QuestionViewState) {
6874
hideButtonsShowNext(viewState: viewState, isEndGame: true)
6975
celebrate()
7076
}
71-
77+
7278
func showWrongAnswerEndGame(viewState: QuestionViewState) {
73-
wrongShakeAnimation(viewState: viewState, after: { self.hideButtonsShowNext(viewState: viewState, isEndGame: true)} )
79+
wrongShakeAnimation(viewState: viewState, after: { self.hideButtonsShowNext(viewState: viewState, isEndGame: true) })
7480
}
75-
81+
7682

7783
private func wrongShakeAnimation(viewState: QuestionViewState, after: @escaping () -> ()) {
7884
let selectedBtn = getBtnByNum(num: viewState.selectedBtnNum)
@@ -81,22 +87,22 @@ class QuestionViewController: UIViewController, QuestionView {
8187
selectedBtn.transform = CGAffineTransform(translationX: 20, y: 0)
8288
UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 1, options: .curveEaseInOut, animations: {
8389
selectedBtn.transform = CGAffineTransform.identity
84-
}, completion: {_ in after()})
90+
}, completion: { _ in after() })
8591
}
86-
92+
8793
/**
8894
* Hides the incorrect buttons and animates the correct name to be centered below profile image
8995
*/
9096
private func hideButtonsShowNext(viewState: QuestionViewState, isEndGame: Bool) {
9197
let correctBtn = getBtnByNum(num: viewState.correctBtnNum)
9298
let selectedBtn = getBtnByNum(num: viewState.selectedBtnNum)
93-
99+
94100
func hideOrMoveAnimation(view: UIView) {
95101
if (view == correctBtn) {
96102
view.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
97103

98104
let p = profileImageView.convert(profileImageView.bounds, to: nil)
99-
105+
100106
let endX = p.minX + (profileImageView.frame.width - view.frame.size.width) / 2
101107
let endY = p.minY + profileImageView.bounds.height
102108

@@ -106,17 +112,18 @@ class QuestionViewController: UIViewController, QuestionView {
106112
view.alpha = 0
107113
}
108114
}
115+
109116
restoreX = correctBtn.frame.origin.x
110117
restoreY = correctBtn.frame.origin.y
111118
lastCorrectBtn = correctBtn
112119
lastSelectedBtn = selectedBtn
113-
114-
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut,animations: {
120+
121+
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {
115122
hideOrMoveAnimation(view: self.button1)
116123
hideOrMoveAnimation(view: self.button2)
117124
hideOrMoveAnimation(view: self.button3)
118125
hideOrMoveAnimation(view: self.button4)
119-
}, completion: {_ in
126+
}, completion: { _ in
120127
var btn: UIButton
121128
if (isEndGame) {
122129
btn = self.buttonEndGame
@@ -125,18 +132,18 @@ class QuestionViewController: UIViewController, QuestionView {
125132
}
126133
btn.isHidden = false
127134
UIView.animate(withDuration: 0.5, animations: {
128-
btn.alpha = 1
135+
btn.alpha = 1
129136
})
130137
})
131138
}
132-
139+
133140
private func showButtons() {
134141
if (restoreX != nil && restoreY != nil) {
142+
lastCorrectBtn?.alpha = 0
135143
lastCorrectBtn?.frame.origin.x = restoreX!
136144
lastCorrectBtn?.frame.origin.y = restoreY!
137-
lastCorrectBtn?.transform = CGAffineTransform(scaleX: 1, y: 1)
138-
lastCorrectBtn?.alpha = 0
139145
lastSelectedBtn?.tintColor = lastSelectedColor
146+
lastCorrectBtn?.transform = CGAffineTransform(scaleX: 1, y: 1)
140147
}
141148
UIView.animate(withDuration: 0.5, animations: {
142149
self.button1.alpha = 1.0
@@ -146,31 +153,31 @@ class QuestionViewController: UIViewController, QuestionView {
146153
self.profileImageView.alpha = 1.0
147154
})
148155
}
149-
156+
150157
private func fadeNextButton(after: @escaping () -> ()) {
151158
UIView.animate(withDuration: 0.5, animations: {
159+
self.lastCorrectBtn?.alpha = 0
152160
self.buttonNext.alpha = 0
153161
self.profileImageView.alpha = 0
154-
}, completion: {_ in
162+
}, completion: { _ in
155163
self.buttonNext.isHidden = true
156164
after()
157165
})
158166
}
159-
167+
160168
private func setProfileAndFadeIn(viewState: QuestionViewState) {
161169
labelQuestion.text = viewState.title
162170
button1.setTitle(viewState.button1Text, for: .normal)
163171
button2.setTitle(viewState.button2Text, for: .normal)
164172
button3.setTitle(viewState.button3Text, for: .normal)
165173
button4.setTitle(viewState.button4Text, for: .normal)
166-
profileImageView.downloaded(from: viewState.profileImageUrl)
167-
showButtons()
174+
profileImageView.downloaded(from: viewState.profileImageUrl, onComplete: { self.showButtons() })
168175
}
169-
176+
170177
private func celebrate() {
171178
confettiView!.startConfetti()
172179
}
173-
180+
174181
private func stopCelebration() {
175182
confettiView!.stopConfetti()
176183
}

0 commit comments

Comments
 (0)