Skip to content

Commit 68bacae

Browse files
committed
Added shimmer effect on skill listing
1 parent 500a0fb commit 68bacae

File tree

16 files changed

+1002
-71
lines changed

16 files changed

+1002
-71
lines changed

Susi.xcodeproj/project.pbxproj

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@
113113
94889CAE1F7CEAA80028B8C3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 94889CB01F7CEAA80028B8C3 /* Localizable.strings */; };
114114
A0DEC06E21E0F40300659A5B /* SelectLanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DEC06D21E0F40300659A5B /* SelectLanguageViewController.swift */; };
115115
A0DEC07021E0F41300659A5B /* LanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DEC06F21E0F41300659A5B /* LanguageModel.swift */; };
116+
A0E42B7321F0F2D8003F06AF /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = A0E42B6B21F0F2D8003F06AF /* LICENSE */; };
117+
A0E42B7421F0F2D8003F06AF /* FBShimmeringLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = A0E42B7021F0F2D8003F06AF /* FBShimmeringLayer.m */; };
118+
A0E42B7521F0F2D8003F06AF /* FBShimmeringView.m in Sources */ = {isa = PBXBuildFile; fileRef = A0E42B7121F0F2D8003F06AF /* FBShimmeringView.m */; };
119+
A0E42B7621F0F2D8003F06AF /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = A0E42B7221F0F2D8003F06AF /* README.md */; };
116120
F09A34A3B776419996088BB5 /* Pods_SusiUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5994B8E49F09387802A1EB7A /* Pods_SusiUITests.framework */; };
117121
/* End PBXBuildFile section */
118122

@@ -246,6 +250,13 @@
246250
A078553387742A62D98A8C3F /* Pods-Susi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Susi.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Susi/Pods-Susi.debug.xcconfig"; sourceTree = "<group>"; };
247251
A0DEC06D21E0F40300659A5B /* SelectLanguageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectLanguageViewController.swift; sourceTree = "<group>"; };
248252
A0DEC06F21E0F41300659A5B /* LanguageModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageModel.swift; sourceTree = "<group>"; };
253+
A0E42B6B21F0F2D8003F06AF /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
254+
A0E42B6D21F0F2D8003F06AF /* FBShimmering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmering.h; sourceTree = "<group>"; };
255+
A0E42B6E21F0F2D8003F06AF /* FBShimmeringLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmeringLayer.h; sourceTree = "<group>"; };
256+
A0E42B6F21F0F2D8003F06AF /* FBShimmeringView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBShimmeringView.h; sourceTree = "<group>"; };
257+
A0E42B7021F0F2D8003F06AF /* FBShimmeringLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBShimmeringLayer.m; sourceTree = "<group>"; };
258+
A0E42B7121F0F2D8003F06AF /* FBShimmeringView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBShimmeringView.m; sourceTree = "<group>"; };
259+
A0E42B7221F0F2D8003F06AF /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
249260
C564B012515FE5529232089A /* Pods_Susi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Susi.framework; sourceTree = BUILT_PRODUCTS_DIR; };
250261
C949F9C701CBA7B848521A51 /* Pods-SusiUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SusiUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SusiUITests/Pods-SusiUITests.release.xcconfig"; sourceTree = "<group>"; };
251262
/* End PBXFileReference section */
@@ -533,6 +544,7 @@
533544
6D4D9B521E768FF40067459C /* Helpers */,
534545
6DE44E121E76ACBA00215B85 /* Model */,
535546
6D35E4811EE70F4700188E1F /* Snowboy Files */,
547+
A0E42B6A21F0F2D8003F06AF /* Shimmer */,
536548
6DAF3AF41F0E0FF700929D86 /* Storyboards */,
537549
6D4D9B4F1E768F250067459C /* Supporting Files */,
538550
);
@@ -689,6 +701,28 @@
689701
path = SelectLanguageController;
690702
sourceTree = "<group>";
691703
};
704+
A0E42B6A21F0F2D8003F06AF /* Shimmer */ = {
705+
isa = PBXGroup;
706+
children = (
707+
A0E42B6B21F0F2D8003F06AF /* LICENSE */,
708+
A0E42B6C21F0F2D8003F06AF /* FBShimmering */,
709+
A0E42B7221F0F2D8003F06AF /* README.md */,
710+
);
711+
path = Shimmer;
712+
sourceTree = "<group>";
713+
};
714+
A0E42B6C21F0F2D8003F06AF /* FBShimmering */ = {
715+
isa = PBXGroup;
716+
children = (
717+
A0E42B6D21F0F2D8003F06AF /* FBShimmering.h */,
718+
A0E42B6E21F0F2D8003F06AF /* FBShimmeringLayer.h */,
719+
A0E42B6F21F0F2D8003F06AF /* FBShimmeringView.h */,
720+
A0E42B7021F0F2D8003F06AF /* FBShimmeringLayer.m */,
721+
A0E42B7121F0F2D8003F06AF /* FBShimmeringView.m */,
722+
);
723+
path = FBShimmering;
724+
sourceTree = "<group>";
725+
};
692726
BD5FA220F268315B61F71523 /* Frameworks */ = {
693727
isa = PBXGroup;
694728
children = (
@@ -804,9 +838,11 @@
804838
files = (
805839
6D4D9B451E768E190067459C /* LaunchScreen.storyboard in Resources */,
806840
6D4D9B421E768E190067459C /* Assets.xcassets in Resources */,
841+
A0E42B7321F0F2D8003F06AF /* LICENSE in Resources */,
807842
94889CAE1F7CEAA80028B8C3 /* Localizable.strings in Resources */,
808843
6DAF3AF61F0E101200929D86 /* Main.storyboard in Resources */,
809844
40801EE520F33BBB0071860E /* YTPlayer.html in Resources */,
845+
A0E42B7621F0F2D8003F06AF /* README.md in Resources */,
810846
6D28983A1F144E5C00B6151A /* common.res in Resources */,
811847
6D47585A1F5625740067B3A4 /* susi.pmdl in Resources */,
812848
);
@@ -990,6 +1026,7 @@
9901026
6D87A32E1EEE54CC00A6D763 /* WebsearchCollectionView.swift in Sources */,
9911027
40FB527520C037C6005D4ACD /* StopCell.swift in Sources */,
9921028
406F8BA020EE72CA00D9C6AC /* VideoPlayAction.swift in Sources */,
1029+
A0E42B7521F0F2D8003F06AF /* FBShimmeringView.m in Sources */,
9931030
6DFC75B91EE077E9002F92BA /* ForgotPasswordViewController.swift in Sources */,
9941031
A0DEC06E21E0F40300659A5B /* SelectLanguageViewController.swift in Sources */,
9951032
6DE44E111E76ACAF00215B85 /* Client.swift in Sources */,
@@ -1021,6 +1058,7 @@
10211058
6DCA90641F1F0B320058CABB /* TextFieldDelegate.swift in Sources */,
10221059
6DE44E191E76AF8100215B85 /* ChatViewController.swift in Sources */,
10231060
6D61B9B31EEBAB4000CD3536 /* TableAction.swift in Sources */,
1061+
A0E42B7421F0F2D8003F06AF /* FBShimmeringLayer.m in Sources */,
10241062
6D87A3321EEE86CC00A6D763 /* RSSCell.swift in Sources */,
10251063
4064830120FCF3220014EB47 /* PlayerViewController.swift in Sources */,
10261064
407ED1DB20BEC6C3007AEE34 /* DesignableView.swift in Sources */,

Susi/Controllers/SkillListingViewController/SkillListingVCMethods.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ extension SkillListingViewController {
2929
}
3030
//MARK: - Presents All Language VC
3131
@objc func getToAllLanguageVC() {
32+
tableView.reloadData()
3233
let vc = SelectLanguageViewController()
3334
weak var weakSelf = self
3435
vc.languageSelection = {
3536
languageModel in
3637
weakSelf?.count = 0
3738
weakSelf?.presentLangugage = languageModel
3839
weakSelf?.getAllGroups()
39-
weakSelf?.shouldAnimateIndicators(true)
40+
weakSelf?.shouldShowShimmerLoading = true
41+
weakSelf?.tableView.reloadData()
4042
}
4143
let nvc = AppNavigationController(rootViewController: vc)
4244
present(nvc, animated: true, completion: nil)

Susi/Controllers/SkillListingViewController/SkillListingViewController.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ class SkillListingViewController: UITableViewController {
5353
var groups: [String]?
5454

5555
var chatViewController: ChatViewController?
56-
56+
57+
var shouldShowShimmerLoading: Bool = true
5758
// stores how many group's data fetched
5859
var count = 0 {
5960
didSet {
6061
if count == groups?.count {
6162
shouldAnimateIndicators(false)
63+
shouldShowShimmerLoading = false
6264
tableView.reloadData()
6365
}
6466
}
@@ -77,15 +79,17 @@ class SkillListingViewController: UITableViewController {
7779

7880
var selectedSkill: Skill? {
7981
didSet {
80-
performSegue(withIdentifier: ControllerConstants.skillDetailControllerIdentifier, sender: self)
82+
if(selectedSkill != nil ) {
83+
performSegue(withIdentifier: ControllerConstants.skillDetailControllerIdentifier, sender: self)
84+
}
8185
}
8286
}
8387

8488
override func viewDidLoad() {
8589
super.viewDidLoad()
8690
prepareActivityIndicator()
87-
shouldAnimateIndicators(true)
8891
getAllGroups()
92+
self.tableView.reloadData()
8993
}
9094

9195
override func viewWillAppear(_ animated: Bool) {
@@ -107,15 +111,12 @@ class SkillListingViewController: UITableViewController {
107111

108112
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
109113
// return the number of rows
110-
return groups?.count ?? 0
114+
return groups?.count ?? (shouldShowShimmerLoading ? 4 : 0)
111115
}
112116

113117
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
114-
if let cell = tableView.dequeueReusableCell(withIdentifier: "skillListCell", for: indexPath) as? SkillListingTableCell,
115-
let group = groups?[indexPath.row] {
116-
cell.groupName = group
117-
cell.skillListController = self
118-
cell.skills = skills[group]
118+
if let cell = tableView.dequeueReusableCell(withIdentifier: "skillListCell", for: indexPath) as? SkillListingTableCell {
119+
cell.viewModel = SkillListingCellViewModel(skill: skills[groups?[indexPath.row] ?? ""], isLoading: shouldShowShimmerLoading, groupName: groups?[indexPath.row], skillListController: self)
119120
return cell
120121
}
121122
return UITableViewCell()
@@ -147,7 +148,7 @@ class SkillListingViewController: UITableViewController {
147148
return 224.0
148149
}
149150
}
150-
return 0.0
151+
return shouldShowShimmerLoading ? 224.0 : 0.0
151152
}
152153

153154
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

Susi/Custom Views/Skill Listing Cells/SkillCell.swift

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import Kingfisher
1111
import Material
1212

1313
class SkillCell: CollectionViewCell {
14-
14+
var isLoading: Bool = false {
15+
didSet {
16+
showShimmer( shouldShow: isLoading)
17+
}
18+
}
1519
var skill: Skill? {
1620
didSet {
1721
skillImage.image = ControllerConstants.Images.placeholder
@@ -40,6 +44,24 @@ class SkillCell: CollectionViewCell {
4044
@IBOutlet weak var skillDescription: UILabel!
4145
@IBOutlet weak var ratingsCard: RatingView!
4246
@IBOutlet weak var totalRatingsLabel: UILabel!
47+
48+
@IBOutlet weak var topShimmer: FBShimmeringView!
49+
@IBOutlet weak var topShimmerContainer: UIView!
50+
51+
@IBOutlet weak var middleShimmerView: FBShimmeringView!
52+
@IBOutlet weak var middleShimmerContainer: UIView!
53+
54+
@IBOutlet weak var bottomShimmerView: FBShimmeringView!
55+
@IBOutlet weak var bottomShimmerContainer: UIView!
56+
// @IBOutlet weak var iconTitleSV: FBShimmeringView!
57+
@IBOutlet weak var ratingShimmerContainer: UIView!
58+
@IBOutlet weak var ratingShimmerView: FBShimmeringView!
59+
//
60+
// @IBOutlet weak var exampleQueryLabelSV: FBShimmeringView!
61+
//
62+
// @IBOutlet weak var skillDescriptionSV: FBShimmeringView!
63+
// @IBOutlet weak var ratingsCardSV: FBShimmeringView!
64+
// @IBOutlet weak var totalRatingsSV: FBShimmeringView!
4365

4466
func configureShadow() {
4567
contentView.layer.cornerRadius = 16.0
@@ -54,7 +76,34 @@ class SkillCell: CollectionViewCell {
5476
layer.masksToBounds = false
5577
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius).cgPath
5678
}
57-
79+
80+
func showShimmer( shouldShow: Bool ) {
81+
iconTitleView.isHidden = shouldShow
82+
skillImage.isHidden = shouldShow
83+
exampleQueryLabel.isHidden = shouldShow
84+
skillName.isHidden = shouldShow
85+
skillDescription.isHidden = shouldShow
86+
ratingsCard.isHidden = shouldShow
87+
totalRatingsLabel.isHidden = shouldShow
88+
topShimmer.isHidden = !shouldShow
89+
bottomShimmerView.isHidden = !shouldShow
90+
bottomShimmerView.isHidden = !shouldShow
91+
ratingShimmerContainer.isHidden = !shouldShow
92+
bottomShimmerView.isHidden = !shouldShow
93+
middleShimmerContainer.isHidden = !shouldShow
94+
bottomShimmerContainer.isHidden = !shouldShow
95+
ratingShimmerView.isHidden = !shouldShow
96+
topShimmerContainer.isHidden = !shouldShow
97+
topShimmer.contentView = topShimmerContainer
98+
bottomShimmerView.contentView = bottomShimmerContainer
99+
middleShimmerView.contentView = middleShimmerContainer
100+
ratingShimmerView.contentView = ratingShimmerContainer
101+
bottomShimmerView.isShimmering = shouldShow
102+
middleShimmerView.isShimmering = shouldShow
103+
topShimmer.isShimmering = shouldShow
104+
ratingShimmerView.isShimmering = shouldShow
105+
}
106+
58107
func roundedCorner() {
59108
iconTitleView.layer.cornerRadius = 16.0
60109
skillImage.layer.cornerRadius = 0.5 * skillImage.frame.width

Susi/Custom Views/Skill Listing Cells/SkillListingCollectionView.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,21 @@ class SkillListingCollectionView: UICollectionView, UICollectionViewDelegateFlow
2020
self.reloadData()
2121
}
2222
}
23-
23+
24+
var isLoading: Bool = false
25+
2426
var skillListController: SkillListingViewController?
2527

2628
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
27-
return groupSkills?.count ?? 0
29+
return groupSkills?.count ?? (isLoading ? 3 : 0)
2830
}
2931

3032
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
3133
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? SkillCell {
3234
cell.skill = groupSkills?[indexPath.item]
3335
cell.backgroundColor = Color.grey.lighten4
3436
cell.depthPreset = .depth4
37+
cell.isLoading = isLoading
3538
return cell
3639
}
3740
return UICollectionViewCell()

Susi/Custom Views/Skill Listing Cells/SkillListingTableCell.swift

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,41 @@ import UIKit
1010
import Material
1111

1212
class SkillListingTableCell: UITableViewCell {
13-
14-
var skillListController: SkillListingViewController?
15-
16-
var groupName: String? {
17-
didSet {
18-
backgroundColor = Color.grey.lighten4
19-
groupNameLabel.text = groupName
20-
}
21-
}
22-
23-
var skills: [Skill]? {
13+
@IBOutlet weak var titleShimmerContainer: UIView!
14+
@IBOutlet weak var titleShimmerView: FBShimmeringView!
15+
@IBOutlet weak var groupNameLabel: UILabel!
16+
@IBOutlet weak var skillListingCollectionView: SkillListingCollectionView!
17+
18+
var viewModel: SkillListingCellViewModel? {
2419
didSet {
25-
// Sort skills in descending order of average ratings
26-
let sortedSkill = skills?.sorted(by: {$0.averageRating > $1.averageRating})
27-
skillListingCollectionView.skillListController = skillListController
28-
skillListingCollectionView.groupSkills = sortedSkill
20+
updateView()
2921
}
3022
}
31-
32-
@IBOutlet weak var groupNameLabel: UILabel!
33-
@IBOutlet weak var skillListingCollectionView: SkillListingCollectionView!
34-
23+
3524
override func awakeFromNib() {
3625
super.awakeFromNib()
26+
setUpDefautls()
27+
}
3728

29+
func setUpDefautls() {
3830
selectionStyle = .none
31+
backgroundColor = Color.grey.lighten4
3932
}
4033

34+
func updateView() {
35+
shouldShimmer(showShimmer: viewModel?.isLoading ?? false)
36+
groupNameLabel.text = viewModel?.groupName
37+
let sortedSkill = viewModel?.skill?.sorted(by: {$0.averageRating > $1.averageRating})
38+
skillListingCollectionView.skillListController = viewModel?.skillListController
39+
skillListingCollectionView.isLoading = viewModel?.isLoading ?? false
40+
skillListingCollectionView.groupSkills = sortedSkill
41+
}
42+
43+
func shouldShimmer(showShimmer: Bool) {
44+
titleShimmerView.contentView = titleShimmerContainer
45+
titleShimmerView.isShimmering = showShimmer
46+
groupNameLabel.isHidden = showShimmer
47+
titleShimmerContainer.isHidden = !showShimmer
48+
titleShimmerView.isHidden = !showShimmer
49+
}
4150
}

Susi/Model/Skill.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88

99
import UIKit
1010

11+
struct SkillListingCellViewModel {
12+
var skill: [Skill]?
13+
var groupName: String?
14+
var isLoading: Bool = false
15+
var skillListController: SkillListingViewController?
16+
let count = 3
17+
18+
init(skill: [Skill]?, isLoading: Bool, groupName: String?, skillListController: SkillListingViewController?) {
19+
self.skill = skill
20+
self.isLoading = isLoading
21+
self.groupName = groupName
22+
self.skillListController = skillListController
23+
}
24+
}
25+
1126
class Skill: NSObject {
1227

1328
var imagePath: String = ""

0 commit comments

Comments
 (0)