:: Add NotchGradientLoadingBar

This commit is contained in:
Felix Mau
2020-06-11 18:02:13 +02:00
parent bbbba8f788
commit d4d7728c19
6 changed files with 170 additions and 40 deletions
@@ -12,7 +12,7 @@ import GradientLoadingBar
class SafeAreaExampleViewController: UIViewController {
// MARK: - Private properties
private let safeAreaGradientLoadingBar = GradientLoadingBar(isRelativeToSafeArea: false)
private let safeAreaGradientLoadingBar = NotchGradientLoadingBar(height: 6)
// MARK: - Public methods
+18 -17
View File
@@ -15,6 +15,7 @@
dependencies = (
);
name = SwiftFormat;
productName = SwiftFormat;
};
52B60EC2A583F24ACBB69C113F5488B9 /* SwiftLint */ = {
isa = PBXAggregateTarget;
@@ -24,6 +25,7 @@
dependencies = (
);
name = SwiftLint;
productName = SwiftLint;
};
/* End PBXAggregateTarget section */
@@ -80,6 +82,7 @@
CE8387F85FA7B1C55704E5BDD58C9F17 /* GradientLoadingBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D40940A239793530B056F5C6D42CBC /* GradientLoadingBarViewModel.swift */; };
D56563764E24224FB95BC77EC18F7D9E /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FE4FE8F00C724C9593C6DEFB4CE2286 /* String.swift */; };
D6A43851802E3E81CF23D65CA9A81E4E /* SnapshotTesting-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D1B84171C66B510644D7EFFDC5B3E475 /* SnapshotTesting-dummy.m */; };
DC190F5724925D170069E2B0 /* NotchGradientLoadingBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC190F5624925D170069E2B0 /* NotchGradientLoadingBarController.swift */; };
DC82754FF0AA19CEEF707C55CBB24008 /* GradientActivityIndicatorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 288446056D0E6A131D9245C47AC68D44 /* GradientActivityIndicatorViewModel.swift */; };
E8945D07A466F2FA6A965D3AA13F41EF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E59CE2F9522AE21F97AA29799051F00E /* Foundation.framework */; };
E964CE43D2624DD003460825556D1101 /* LightweightObservable-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE49E78400E3A6E986194452C2A1611 /* LightweightObservable-dummy.m */; };
@@ -154,9 +157,9 @@
0965FCF94C6751E5F873995C0CC05032 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
108AACC96F7DBC089B0840E09F19C698 /* Pods-GradientLoadingBar_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Example.release.xcconfig"; sourceTree = "<group>"; };
132C18988D60EF85736C043D43C19E57 /* Pods-GradientLoadingBar_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Tests-umbrella.h"; sourceTree = "<group>"; };
13520AB8B3790CE3CEDCBBEEE1EF237A /* Pods_GradientLoadingBar_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_SnapshotTests.framework; path = "Pods-GradientLoadingBar_SnapshotTests.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
13520AB8B3790CE3CEDCBBEEE1EF237A /* Pods_GradientLoadingBar_SnapshotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_SnapshotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1679A4CF92D4ADFB15F8200201EC3AE5 /* Pods-GradientLoadingBar_SnapshotTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-GradientLoadingBar_SnapshotTests-frameworks.sh"; sourceTree = "<group>"; };
1711FC18263D47D46851F0433A93F110 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_Tests.framework; path = "Pods-GradientLoadingBar_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
1711FC18263D47D46851F0433A93F110 /* Pods_GradientLoadingBar_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
172DF8516EF6D5757C3FBEF1C0CB52DC /* Pods-GradientLoadingBar_SnapshotTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GradientLoadingBar_SnapshotTests-dummy.m"; sourceTree = "<group>"; };
1A9107CAA27BA0679345F24910903133 /* Pods-GradientLoadingBar_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-GradientLoadingBar_Tests-dummy.m"; sourceTree = "<group>"; };
1B664F0A7F5E59140F761C16069995E9 /* Pods-GradientLoadingBar_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Tests.release.xcconfig"; sourceTree = "<group>"; };
@@ -170,13 +173,13 @@
382426057DD9B8AC16E9C8CBC1B1DE3E /* GradientActivityIndicatorView+AnimateIsHidden.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "GradientActivityIndicatorView+AnimateIsHidden.swift"; sourceTree = "<group>"; };
3A900E1CFF1D76CF61DDF7358F5C8863 /* Pods-GradientLoadingBar_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_Example-umbrella.h"; sourceTree = "<group>"; };
3B644D77B6DA2AE767C93222955C0195 /* SnapshotTesting.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapshotTesting.release.xcconfig; sourceTree = "<group>"; };
3C6A379C135C84644F189B8056CCBA04 /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_GradientLoadingBar_Example.framework; path = "Pods-GradientLoadingBar_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
3C6A379C135C84644F189B8056CCBA04 /* Pods_GradientLoadingBar_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GradientLoadingBar_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3CE49E78400E3A6E986194452C2A1611 /* LightweightObservable-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "LightweightObservable-dummy.m"; sourceTree = "<group>"; };
4371A74F9A6D74628527A30E755EFF25 /* Pods-GradientLoadingBar_SnapshotTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-GradientLoadingBar_SnapshotTests-umbrella.h"; sourceTree = "<group>"; };
4748F84A87672B2B8A2332EBFAB30E20 /* UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UIImage.swift; path = Sources/SnapshotTesting/Snapshotting/UIImage.swift; sourceTree = "<group>"; };
47AF808C977A1F54C41301EE10EFED69 /* SwiftFormat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftFormat.release.xcconfig; sourceTree = "<group>"; };
485FFC9380094A5DB42D7366AEBF4780 /* Diffing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Diffing.swift; path = Sources/SnapshotTesting/Diffing.swift; sourceTree = "<group>"; };
509A0CDAB5E258F92F9E7FA978AA781F /* readme.md */ = {isa = PBXFileReference; includeInIndex = 1; path = readme.md; sourceTree = "<group>"; };
509A0CDAB5E258F92F9E7FA978AA781F /* readme.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = readme.md; sourceTree = "<group>"; };
51265E01B15BDF30B0C2CBDF6A151BC4 /* LightweightObservable.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LightweightObservable.debug.xcconfig; sourceTree = "<group>"; };
5E0ED20F03F3062DB47BF2E306FF9049 /* LightweightObservable-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "LightweightObservable-Info.plist"; sourceTree = "<group>"; };
607A4044C0C5EAADEE148DC31AF9667B /* GradientLoadingBar-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-prefix.pch"; sourceTree = "<group>"; };
@@ -187,7 +190,7 @@
655D196DB461A65E1D8D6C38F3ACF62D /* URLRequest.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = URLRequest.swift; path = Sources/SnapshotTesting/Snapshotting/URLRequest.swift; sourceTree = "<group>"; };
66278BB4526795EDC4B59B5F6E94042F /* GradientLoadingBar-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GradientLoadingBar-Info.plist"; sourceTree = "<group>"; };
66C7044ABF6219E06138EBA038827408 /* Description.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Description.swift; path = Sources/SnapshotTesting/Snapshotting/Description.swift; sourceTree = "<group>"; };
67873E92210DD4E777C49C6E8AEDC108 /* GradientLoadingBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GradientLoadingBar.framework; path = GradientLoadingBar.framework; sourceTree = BUILT_PRODUCTS_DIR; };
67873E92210DD4E777C49C6E8AEDC108 /* GradientLoadingBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GradientLoadingBar.framework; sourceTree = BUILT_PRODUCTS_DIR; };
69838A921E83418B945E72EB342809F5 /* Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_SnapshotTests.debug.xcconfig"; sourceTree = "<group>"; };
6A0AC5F9D0359F62D9B6CFA7E28C270C /* Snapshotting.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Snapshotting.swift; path = Sources/SnapshotTesting/Snapshotting.swift; sourceTree = "<group>"; };
6A285D3D7A75E50B304EC4E2967172F4 /* GradientLoadingBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GradientLoadingBarController.swift; path = GradientLoadingBar/Classes/GradientLoadingBarController.swift; sourceTree = "<group>"; };
@@ -203,12 +206,12 @@
8907BBB8111B9A50687EB4B5E9E41A95 /* GradientLoadingBar-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GradientLoadingBar-umbrella.h"; sourceTree = "<group>"; };
93233819B16746A4C1D1A32DFCEC1752 /* LightweightObservable-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-prefix.pch"; sourceTree = "<group>"; };
934AB585A2B4F9B908F37869A81F2EEC /* GradientLoadingBar.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GradientLoadingBar.modulemap; sourceTree = "<group>"; };
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
9DD32929B122D2561D1E99468EECDBF7 /* Pods-GradientLoadingBar_SnapshotTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_SnapshotTests.release.xcconfig"; sourceTree = "<group>"; };
9E46234BCB7A6CF5AE3ECC8C30C3786B /* AssertSnapshot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssertSnapshot.swift; path = Sources/SnapshotTesting/AssertSnapshot.swift; sourceTree = "<group>"; };
9EFE8B971DF98A48094E8121DA5F22BE /* LightweightObservable.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = LightweightObservable.release.xcconfig; sourceTree = "<group>"; };
9FAFAFBF669302034A4D6BEDD683F06D /* CALayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CALayer.swift; path = Sources/SnapshotTesting/Snapshotting/CALayer.swift; sourceTree = "<group>"; };
A037DBBCCACBFACB5C39A80B1C273043 /* SnapshotTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = SnapshotTesting.framework; path = SnapshotTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A037DBBCCACBFACB5C39A80B1C273043 /* SnapshotTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SnapshotTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A1224C54074A146D75B2762DEE7B60CE /* SnapshotTestCase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SnapshotTestCase.swift; path = Sources/SnapshotTesting/SnapshotTestCase.swift; sourceTree = "<group>"; };
A2BEFE77478CF65195FEA6A6C36027C2 /* SwiftLint.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.release.xcconfig; sourceTree = "<group>"; };
A652F20CE7EE44E64565C2120B651665 /* Pods-GradientLoadingBar_SnapshotTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_SnapshotTests.modulemap"; sourceTree = "<group>"; };
@@ -228,11 +231,12 @@
C478F41E1D29E73C340C46510C963758 /* SnapshotTesting.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = SnapshotTesting.modulemap; sourceTree = "<group>"; };
C4D40940A239793530B056F5C6D42CBC /* GradientLoadingBarViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientLoadingBarViewModel.swift; sourceTree = "<group>"; };
CC084E9470B1610C5C104460C3E9672F /* GradientActivityIndicatorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GradientActivityIndicatorView.swift; sourceTree = "<group>"; };
CC8524E3DB1DECB19CE8E799B2372568 /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = GradientLoadingBar.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
CC8524E3DB1DECB19CE8E799B2372568 /* GradientLoadingBar.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = GradientLoadingBar.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
CEE3F100C4CDD54473EA2C6C753CE3F8 /* Observable+KeyPath.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Observable+KeyPath.swift"; path = "LightweightObservable/Classes/Extensions/Observable+KeyPath.swift"; sourceTree = "<group>"; };
D1B84171C66B510644D7EFFDC5B3E475 /* SnapshotTesting-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SnapshotTesting-dummy.m"; sourceTree = "<group>"; };
D20C54CBF964A3FE43CE7FE20719F6AD /* SwiftLint.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftLint.debug.xcconfig; sourceTree = "<group>"; };
D5B2A1C4D6360C6D91F1483048511530 /* LightweightObservable-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "LightweightObservable-umbrella.h"; sourceTree = "<group>"; };
DC190F5624925D170069E2B0 /* NotchGradientLoadingBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotchGradientLoadingBarController.swift; sourceTree = "<group>"; };
DC1FD5A53165BF4293473D170AD9995E /* View.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = View.swift; path = Sources/SnapshotTesting/Common/View.swift; sourceTree = "<group>"; };
E06A1816AB01D090FDC9EEC02261A14E /* SnapshotTesting-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "SnapshotTesting-Info.plist"; sourceTree = "<group>"; };
E0D90990792D653F523A884442305989 /* Pods-GradientLoadingBar_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-GradientLoadingBar_Example.modulemap"; sourceTree = "<group>"; };
@@ -243,13 +247,13 @@
E5F5BFF05569BBDD6EF0224F0E21090A /* CaseIterable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CaseIterable.swift; path = Sources/SnapshotTesting/Snapshotting/CaseIterable.swift; sourceTree = "<group>"; };
E9C3128EB6965EA592CD63B38170D57B /* Async.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Async.swift; path = Sources/SnapshotTesting/Async.swift; sourceTree = "<group>"; };
ED80020D57E60A2BDBE6BE1EB9333D0A /* SwiftFormat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftFormat.debug.xcconfig; sourceTree = "<group>"; };
F196AAA163469B17170E99B82C7C4C0A /* LightweightObservable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = LightweightObservable.framework; path = LightweightObservable.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F196AAA163469B17170E99B82C7C4C0A /* LightweightObservable.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LightweightObservable.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F2B4FFBC82EA6CAE84B65AE1835AF25A /* SnapshotTesting.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SnapshotTesting.debug.xcconfig; sourceTree = "<group>"; };
F2D95A77154276FCFD49025721CF9191 /* Observable+Equatable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Observable+Equatable.swift"; path = "LightweightObservable/Classes/Extensions/Observable+Equatable.swift"; sourceTree = "<group>"; };
F7B1750DE470F045803DE2094D5F7264 /* Pods-GradientLoadingBar_SnapshotTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-GradientLoadingBar_SnapshotTests-Info.plist"; sourceTree = "<group>"; };
F7FAEB3ACD1AD90617D11C22CECBCFF2 /* GradientLoadingBar.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GradientLoadingBar.release.xcconfig; sourceTree = "<group>"; };
F952B84395F604678559569DA34F74D2 /* Wait.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Wait.swift; path = Sources/SnapshotTesting/Extensions/Wait.swift; sourceTree = "<group>"; };
FB13F66A7D40AC5D9D870CB621D9D898 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = "<group>"; };
FB13F66A7D40AC5D9D870CB621D9D898 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
FBAEAE91BB9B77006558E537894C33C5 /* Pods-GradientLoadingBar_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-GradientLoadingBar_Tests.debug.xcconfig"; sourceTree = "<group>"; };
FF135E1D23F08BE7F1D7FFC86260EF9B /* Pods-GradientLoadingBar_SnapshotTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-GradientLoadingBar_SnapshotTests-acknowledgements.markdown"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -371,7 +375,6 @@
CEE3F100C4CDD54473EA2C6C753CE3F8 /* Observable+KeyPath.swift */,
7A7C6C3CD90BB6F1A79FCFA9E9F6C9F5 /* Support Files */,
);
name = LightweightObservable;
path = LightweightObservable;
sourceTree = "<group>";
};
@@ -380,7 +383,6 @@
children = (
E2CCD1A55C9A485E976F71F7C7CF3366 /* Support Files */,
);
name = SwiftLint;
path = SwiftLint;
sourceTree = "<group>";
};
@@ -504,7 +506,6 @@
A6C45FD2B6DBF67E9CA08571D980F9C7 /* XCTAttachment.swift */,
434289011F6712E755970F1074781EA5 /* Support Files */,
);
name = SnapshotTesting;
path = SnapshotTesting;
sourceTree = "<group>";
};
@@ -520,12 +521,13 @@
C30CBA6370532ED04361FF0E39E0D799 /* GradientLoadingBar */ = {
isa = PBXGroup;
children = (
6A285D3D7A75E50B304EC4E2967172F4 /* GradientLoadingBarController.swift */,
B40EF345738F3DA667C21CF3F0DF5538 /* Misc */,
A5CCEF189421647B1B00BB017CF80F7D /* Pod */,
C9A709FCBCBFE549177C810EAFC278F3 /* Support Files */,
B25194A474F7FB1B19DF392B63D633A0 /* ViewModel */,
C8FA2FFE987E4CAE66EF6455DF3F969C /* Views */,
6A285D3D7A75E50B304EC4E2967172F4 /* GradientLoadingBarController.swift */,
DC190F5624925D170069E2B0 /* NotchGradientLoadingBarController.swift */,
);
name = GradientLoadingBar;
path = ../..;
@@ -583,7 +585,6 @@
children = (
2CE89AADFFFE95E8003FB250177B1CD1 /* Support Files */,
);
name = SwiftFormat;
path = SwiftFormat;
sourceTree = "<group>";
};
@@ -902,6 +903,7 @@
72E7D09F895BFB276F79212661207A3E /* Constants.swift in Sources */,
1AB5DB926319ED83D108A7029C3CE863 /* GradientActivityIndicatorView+AnimateIsHidden.swift in Sources */,
845E53EF69DD891F41769CBFAD775C5C /* GradientActivityIndicatorView.swift in Sources */,
DC190F5724925D170069E2B0 /* NotchGradientLoadingBarController.swift in Sources */,
DC82754FF0AA19CEEF707C55CBB24008 /* GradientActivityIndicatorViewModel.swift in Sources */,
9BF500319938CCD42F882041380B4A4E /* GradientLoadingBar-dummy.m in Sources */,
EA1F3BF177FD4A38CBE9B67849F9DAC4 /* GradientLoadingBarController.swift in Sources */,
@@ -1133,8 +1135,7 @@
MTL_FAST_MATH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 5.0;
SYMROOT = "${SRCROOT}/../build";
};
@@ -17,33 +17,35 @@ open class GradientLoadingBarController {
// MARK: - Public properties
/// The height of the gradient bar.
///
/// - Note: Has to be public to allow overwriting `setupConstraints()`
public let height: CGFloat
/// Flag whether the top layout constraint should respect `safeAreaLayoutGuide`.
///
/// - Note: Has to be public to allow overwriting `setupConstraints()`
public let isRelativeToSafeArea: Bool
/// View containing the gradient layer.
public let gradientView = GradientActivityIndicatorView()
public let gradientActivityIndicatorView = GradientActivityIndicatorView()
/// Colors used for the gradient.
public var gradientColors: [UIColor] {
get {
gradientView.gradientColors
gradientActivityIndicatorView.gradientColors
}
set {
gradientView.gradientColors = newValue
gradientActivityIndicatorView.gradientColors = newValue
}
}
/// Duration for the progress animation.
public var progressAnimationDuration: TimeInterval {
get {
gradientView.progressAnimationDuration
gradientActivityIndicatorView.progressAnimationDuration
}
set {
gradientView.progressAnimationDuration = newValue
gradientActivityIndicatorView.progressAnimationDuration = newValue
}
}
@@ -73,7 +75,7 @@ open class GradientLoadingBarController {
self.isRelativeToSafeArea = isRelativeToSafeArea
// We don't want the view to be visible initially.
gradientView.fadeOut(duration: 0)
gradientActivityIndicatorView.fadeOut(duration: 0)
bindViewModelToView()
}
@@ -90,24 +92,24 @@ open class GradientLoadingBarController {
}
NSLayoutConstraint.activate([
gradientView.topAnchor.constraint(equalTo: superViewTopAnchor),
gradientView.heightAnchor.constraint(equalToConstant: height),
gradientActivityIndicatorView.topAnchor.constraint(equalTo: superViewTopAnchor),
gradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: height),
gradientView.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
gradientView.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
gradientActivityIndicatorView.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
gradientActivityIndicatorView.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
])
}
/// Fades in the gradient loading bar.
public func fadeIn(duration: TimeInterval = TimeInterval.GradientLoadingBar.fadeInDuration, completion: ((Bool) -> Void)? = nil) {
gradientView.fadeIn(duration: duration,
completion: completion)
gradientActivityIndicatorView.fadeIn(duration: duration,
completion: completion)
}
/// Fades out the gradient loading bar.
public func fadeOut(duration: TimeInterval = TimeInterval.GradientLoadingBar.fadeOutDuration, completion: ((Bool) -> Void)? = nil) {
gradientView.fadeOut(duration: duration,
completion: completion)
gradientActivityIndicatorView.fadeOut(duration: duration,
completion: completion)
}
// MARK: - Private methods
@@ -120,11 +122,11 @@ open class GradientLoadingBarController {
private func updateSuperview(_ superview: UIView?) {
// If the views superview is not nil, the superview releases the view.
gradientView.removeFromSuperview()
gradientActivityIndicatorView.removeFromSuperview()
if let superview = superview {
gradientView.translatesAutoresizingMaskIntoConstraints = false
superview.addSubview(gradientView)
gradientActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
superview.addSubview(gradientActivityIndicatorView)
setupConstraints(superview: superview)
}
@@ -10,7 +10,7 @@ import UIKit
extension UIColor {
/// Default colors for components.
public struct GradientLoadingBar {
public enum GradientLoadingBar {
/// The default color palette for the gradient colors.
///
/// - SeeAlso: https://codepen.io/marcobiedermann/pen/LExXWW
@@ -22,7 +22,7 @@ extension UIColor {
extension TimeInterval {
/// Numeric default values.
public struct GradientLoadingBar {
public enum GradientLoadingBar {
/// The default duration for fading-in the loading bar, measured in seconds.
public static let fadeInDuration = 0.33
@@ -14,7 +14,9 @@ open class GradientActivityIndicatorView: UIView {
// MARK: - Config
/// Animation-Key for the progress animation.
private static let progressAnimationKey = "GradientActivityIndicatorView--progressAnimation"
private enum Config {
static let progressAnimationKey = "GradientActivityIndicatorView--progressAnimation"
}
// MARK: - Public properties
@@ -120,9 +122,9 @@ open class GradientActivityIndicatorView: UIView {
private func updateAnimation(isAnimating: Bool) {
if isAnimating {
gradientLayer?.add(progressAnimation, forKey: GradientActivityIndicatorView.progressAnimationKey)
gradientLayer?.add(progressAnimation, forKey: Config.progressAnimationKey)
} else {
gradientLayer?.removeAnimation(forKey: GradientActivityIndicatorView.progressAnimationKey)
gradientLayer?.removeAnimation(forKey: Config.progressAnimationKey)
}
}
}
+125
View File
@@ -0,0 +1,125 @@
//
// NotchGradientLoadingBarController.swift
// GradientLoadingBar
//
// Created by Felix Mau on 11.06.20.
//
import UIKit
///
@available(iOS 11.0, *)
public typealias NotchGradientLoadingBar = NotchGradientLoadingBarController
@available(iOS 11.0, *)
open class NotchGradientLoadingBarController: GradientLoadingBarController {
// MARK: - Config
/// Values are based on
/// <https://www.paintcodeapp.com/news/iphone-x-screen-demystified>
private enum Config {
/// The width of the iPhone notch (a little bit larger than mentioned in the docs).
static let notchWidth: CGFloat = 211
/// The radius of the small circle on the outside of the notch.
static let smallCircleRadius: CGFloat = 6
/// The radius of the small circle on the inside of the notch.
static let largeCircleRadius: CGFloat = 20
}
// MARK: - Public methods
override open func setupConstraints(superview: UIView) {
//
let height = 2 * Config.smallCircleRadius + Config.largeCircleRadius + self.height
NSLayoutConstraint.activate([
gradientActivityIndicatorView.topAnchor.constraint(equalTo: superview.topAnchor),
gradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: height),
gradientActivityIndicatorView.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
gradientActivityIndicatorView.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
])
applyNotchMask()
}
// MARK: - Private methods
private func applyNotchMask() {
// We draw the mask of the notch in the center of the screen.
// As we currently only support portrait mode, we can safely use `UIScreen.main.bounds` here.
let screenWidth = UIScreen.main.bounds.size.width
let leftNotchPoint = (screenWidth - Config.notchWidth) / 2
let rightNotchPoint = (screenWidth + Config.notchWidth) / 2
let smallCircleDiameter: CGFloat = 2 * Config.smallCircleRadius
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 0, y: 0))
// Draw line to small-circle left to `leftNotchPoint`.
bezierPath.addLineTo(x: leftNotchPoint - Config.smallCircleRadius,
y: 0)
bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint - Config.smallCircleRadius, y: Config.smallCircleRadius),
radius: Config.smallCircleRadius,
startAngle: -CGFloat.pi / 2,
endAngle: 0,
clockwise: true)
// Draw the large-circle.
// Moving it up by two points looked way better.
let verticalOffsetForLargeCenterPoint: CGFloat = 2
bezierPath.addArc(withCenter: CGPoint(x: leftNotchPoint + Config.largeCircleRadius,
y: smallCircleDiameter - verticalOffsetForLargeCenterPoint),
radius: Config.largeCircleRadius,
startAngle: -CGFloat.pi,
endAngle: CGFloat.pi / 2,
clockwise: false)
// Draw line to large-circle underneath and left to `rightNotchPoint`.
bezierPath.addLineTo(x: rightNotchPoint - Config.largeCircleRadius,
y: smallCircleDiameter + Config.largeCircleRadius - verticalOffsetForLargeCenterPoint)
// Draw the large-circle.
// Moving it up by two points looked way better.
bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint - Config.largeCircleRadius,
y: smallCircleDiameter - verticalOffsetForLargeCenterPoint),
radius: Config.largeCircleRadius,
startAngle: CGFloat.pi / 2,
endAngle: 0,
clockwise: false)
bezierPath.addArc(withCenter: CGPoint(x: rightNotchPoint + Config.smallCircleRadius, y: Config.smallCircleRadius),
radius: Config.smallCircleRadius,
startAngle: CGFloat.pi,
endAngle: CGFloat.pi + CGFloat.pi / 2,
clockwise: true)
// Draw line to the end of the screen.
bezierPath.addLineTo(x: screenWidth, y: 0)
bezierPath.close()
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.strokeColor = UIColor.white.cgColor
shapeLayer.path = bezierPath.cgPath
// As the stroke lays outside of our bezier-path and only one-half of the stroke is visible (the other part is hidden behind the frame
// of the smartphone), we have to multiply it by two.
shapeLayer.lineWidth = 2 * height
gradientActivityIndicatorView.layer.mask = shapeLayer
}
}
// MARK: - Helpers
private extension UIBezierPath {
// swiftlint:disable:next identifier_name
func addLineTo(x: CGFloat, y: CGFloat) {
addLine(to: CGPoint(x: x, y: y))
}
}