diff --git a/Switches.xcodeproj/project.pbxproj b/Switches.xcodeproj/project.pbxproj index 61ae4f8..98c9b27 100644 --- a/Switches.xcodeproj/project.pbxproj +++ b/Switches.xcodeproj/project.pbxproj @@ -10,6 +10,38 @@ E30C48BB24FAE6930049D5C3 /* Switches.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E30C48B124FAE6930049D5C3 /* Switches.framework */; }; E30C48C024FAE6930049D5C3 /* SwitchesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48BF24FAE6930049D5C3 /* SwitchesTests.swift */; }; E30C48C224FAE6930049D5C3 /* Switches.h in Headers */ = {isa = PBXBuildFile; fileRef = E30C48B424FAE6930049D5C3 /* Switches.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E30C48D924FAE6BB0049D5C3 /* JDNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48CC24FAE6BB0049D5C3 /* JDNavigationController.swift */; }; + E30C48DA24FAE6BB0049D5C3 /* JDNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48CD24FAE6BB0049D5C3 /* JDNavigationBar.swift */; }; + E30C48DB24FAE6BB0049D5C3 /* Switcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48CF24FAE6BB0049D5C3 /* Switcher.swift */; }; + E30C48DC24FAE6BB0049D5C3 /* TKLiquidSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D024FAE6BB0049D5C3 /* TKLiquidSwitch.swift */; }; + E30C48DD24FAE6BB0049D5C3 /* JDSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D124FAE6BB0049D5C3 /* JDSwitch.swift */; }; + E30C48DE24FAE6BB0049D5C3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D224FAE6BB0049D5C3 /* UIImage+Extension.swift */; }; + E30C48DF24FAE6BB0049D5C3 /* TKBaseSwitcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D324FAE6BB0049D5C3 /* TKBaseSwitcher.swift */; }; + E30C48E024FAE6BB0049D5C3 /* SDSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D424FAE6BB0049D5C3 /* SDSwitch.swift */; }; + E30C48E124FAE6BB0049D5C3 /* YapSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D524FAE6BB0049D5C3 /* YapSwitch.swift */; }; + E30C48E224FAE6BB0049D5C3 /* BaseControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D624FAE6BB0049D5C3 /* BaseControl.swift */; }; + E30C48E324FAE6BB0049D5C3 /* TKSmileSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D724FAE6BB0049D5C3 /* TKSmileSwitch.swift */; }; + E30C48E424FAE6BB0049D5C3 /* CALayer+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C48D824FAE6BB0049D5C3 /* CALayer+Extension.swift */; }; + E30C490324FAE7420049D5C3 /* SwitchesDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C490224FAE7420049D5C3 /* SwitchesDemoTests.swift */; }; + E30C490E24FAE7420049D5C3 /* SwitchesDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C490D24FAE7420049D5C3 /* SwitchesDemoUITests.swift */; }; + E30C492F24FAE76F0049D5C3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C491A24FAE76F0049D5C3 /* AppDelegate.swift */; }; + E30C493024FAE76F0049D5C3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C491B24FAE76F0049D5C3 /* SceneDelegate.swift */; }; + E30C493124FAE76F0049D5C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E30C491D24FAE76F0049D5C3 /* LaunchScreen.storyboard */; }; + E30C493224FAE76F0049D5C3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E30C491F24FAE76F0049D5C3 /* Main.storyboard */; }; + E30C493324FAE76F0049D5C3 /* SmileyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492224FAE76F0049D5C3 /* SmileyViewController.swift */; }; + E30C493424FAE76F0049D5C3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492324FAE76F0049D5C3 /* ViewController.swift */; }; + E30C493524FAE76F0049D5C3 /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492524FAE76F0049D5C3 /* CollectionViewCell.swift */; }; + E30C493624FAE76F0049D5C3 /* ModeSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492624FAE76F0049D5C3 /* ModeSwitchesViewController.swift */; }; + E30C493724FAE76F0049D5C3 /* GradientSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492724FAE76F0049D5C3 /* GradientSwitchesViewController.swift */; }; + E30C493824FAE76F0049D5C3 /* RandomViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492824FAE76F0049D5C3 /* RandomViewController.swift */; }; + E30C493924FAE76F0049D5C3 /* ModeBSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492924FAE76F0049D5C3 /* ModeBSwitchesViewController.swift */; }; + E30C493A24FAE76F0049D5C3 /* SwiftyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492A24FAE76F0049D5C3 /* SwiftyViewController.swift */; }; + E30C493B24FAE76F0049D5C3 /* AnimatedSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492B24FAE76F0049D5C3 /* AnimatedSwitchesViewController.swift */; }; + E30C493C24FAE76F0049D5C3 /* ThumbImageSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492C24FAE76F0049D5C3 /* ThumbImageSwitchesViewController.swift */; }; + E30C493D24FAE76F0049D5C3 /* LoadingSwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492D24FAE76F0049D5C3 /* LoadingSwitchesViewController.swift */; }; + E30C493E24FAE76F0049D5C3 /* JellySwitchesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C492E24FAE76F0049D5C3 /* JellySwitchesViewController.swift */; }; + E30C494724FAE8350049D5C3 /* SwitchType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30C494624FAE8350049D5C3 /* SwitchType.swift */; }; + E30C494824FAEB5B0049D5C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E30C494224FAE7BC0049D5C3 /* Assets.xcassets */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -20,6 +52,20 @@ remoteGlobalIDString = E30C48B024FAE6930049D5C3; remoteInfo = Switches; }; + E30C48FF24FAE7420049D5C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E30C48A824FAE6930049D5C3 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E30C48E824FAE73F0049D5C3; + remoteInfo = SwitchesDemo; + }; + E30C490A24FAE7420049D5C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E30C48A824FAE6930049D5C3 /* Project object */; + proxyType = 1; + remoteGlobalIDString = E30C48E824FAE73F0049D5C3; + remoteInfo = SwitchesDemo; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -29,6 +75,44 @@ E30C48BA24FAE6930049D5C3 /* SwitchesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwitchesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E30C48BF24FAE6930049D5C3 /* SwitchesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchesTests.swift; sourceTree = ""; }; E30C48C124FAE6930049D5C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E30C48CC24FAE6BB0049D5C3 /* JDNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDNavigationController.swift; sourceTree = ""; }; + E30C48CD24FAE6BB0049D5C3 /* JDNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDNavigationBar.swift; sourceTree = ""; }; + E30C48CF24FAE6BB0049D5C3 /* Switcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switcher.swift; sourceTree = ""; }; + E30C48D024FAE6BB0049D5C3 /* TKLiquidSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TKLiquidSwitch.swift; sourceTree = ""; }; + E30C48D124FAE6BB0049D5C3 /* JDSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDSwitch.swift; sourceTree = ""; }; + E30C48D224FAE6BB0049D5C3 /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; + E30C48D324FAE6BB0049D5C3 /* TKBaseSwitcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TKBaseSwitcher.swift; sourceTree = ""; }; + E30C48D424FAE6BB0049D5C3 /* SDSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SDSwitch.swift; sourceTree = ""; }; + E30C48D524FAE6BB0049D5C3 /* YapSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YapSwitch.swift; sourceTree = ""; }; + E30C48D624FAE6BB0049D5C3 /* BaseControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseControl.swift; sourceTree = ""; }; + E30C48D724FAE6BB0049D5C3 /* TKSmileSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TKSmileSwitch.swift; sourceTree = ""; }; + E30C48D824FAE6BB0049D5C3 /* CALayer+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CALayer+Extension.swift"; sourceTree = ""; }; + E30C48E924FAE73F0049D5C3 /* SwitchesDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwitchesDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E30C48F924FAE7420049D5C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E30C48FE24FAE7420049D5C3 /* SwitchesDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwitchesDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E30C490224FAE7420049D5C3 /* SwitchesDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchesDemoTests.swift; sourceTree = ""; }; + E30C490424FAE7420049D5C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E30C490924FAE7420049D5C3 /* SwitchesDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwitchesDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E30C490D24FAE7420049D5C3 /* SwitchesDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchesDemoUITests.swift; sourceTree = ""; }; + E30C490F24FAE7420049D5C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E30C491A24FAE76F0049D5C3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E30C491B24FAE76F0049D5C3 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + E30C491E24FAE76F0049D5C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + E30C492024FAE76F0049D5C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + E30C492224FAE76F0049D5C3 /* SmileyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmileyViewController.swift; sourceTree = ""; }; + E30C492324FAE76F0049D5C3 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + E30C492524FAE76F0049D5C3 /* CollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; + E30C492624FAE76F0049D5C3 /* ModeSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModeSwitchesViewController.swift; sourceTree = ""; }; + E30C492724FAE76F0049D5C3 /* GradientSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientSwitchesViewController.swift; sourceTree = ""; }; + E30C492824FAE76F0049D5C3 /* RandomViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomViewController.swift; sourceTree = ""; }; + E30C492924FAE76F0049D5C3 /* ModeBSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModeBSwitchesViewController.swift; sourceTree = ""; }; + E30C492A24FAE76F0049D5C3 /* SwiftyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyViewController.swift; sourceTree = ""; }; + E30C492B24FAE76F0049D5C3 /* AnimatedSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedSwitchesViewController.swift; sourceTree = ""; }; + E30C492C24FAE76F0049D5C3 /* ThumbImageSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThumbImageSwitchesViewController.swift; sourceTree = ""; }; + E30C492D24FAE76F0049D5C3 /* LoadingSwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingSwitchesViewController.swift; sourceTree = ""; }; + E30C492E24FAE76F0049D5C3 /* JellySwitchesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JellySwitchesViewController.swift; sourceTree = ""; }; + E30C494224FAE7BC0049D5C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E30C494624FAE8350049D5C3 /* SwitchType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchType.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -47,6 +131,27 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E30C48E624FAE73F0049D5C3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C48FB24FAE7420049D5C3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C490624FAE7420049D5C3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -55,6 +160,9 @@ children = ( E30C48B324FAE6930049D5C3 /* Switches */, E30C48BE24FAE6930049D5C3 /* SwitchesTests */, + E30C48EA24FAE73F0049D5C3 /* SwitchesDemo */, + E30C490124FAE7420049D5C3 /* SwitchesDemoTests */, + E30C490C24FAE7420049D5C3 /* SwitchesDemoUITests */, E30C48B224FAE6930049D5C3 /* Products */, ); sourceTree = ""; @@ -64,6 +172,9 @@ children = ( E30C48B124FAE6930049D5C3 /* Switches.framework */, E30C48BA24FAE6930049D5C3 /* SwitchesTests.xctest */, + E30C48E924FAE73F0049D5C3 /* SwitchesDemo.app */, + E30C48FE24FAE7420049D5C3 /* SwitchesDemoTests.xctest */, + E30C490924FAE7420049D5C3 /* SwitchesDemoUITests.xctest */, ); name = Products; sourceTree = ""; @@ -72,6 +183,8 @@ isa = PBXGroup; children = ( E30C48B424FAE6930049D5C3 /* Switches.h */, + E30C48CB24FAE6BB0049D5C3 /* Navigation */, + E30C48CE24FAE6BB0049D5C3 /* Switches */, E30C48B524FAE6930049D5C3 /* Info.plist */, ); path = Switches; @@ -86,6 +199,124 @@ path = SwitchesTests; sourceTree = ""; }; + E30C48CB24FAE6BB0049D5C3 /* Navigation */ = { + isa = PBXGroup; + children = ( + E30C48CC24FAE6BB0049D5C3 /* JDNavigationController.swift */, + E30C48CD24FAE6BB0049D5C3 /* JDNavigationBar.swift */, + ); + path = Navigation; + sourceTree = ""; + }; + E30C48CE24FAE6BB0049D5C3 /* Switches */ = { + isa = PBXGroup; + children = ( + E30C48CF24FAE6BB0049D5C3 /* Switcher.swift */, + E30C48D024FAE6BB0049D5C3 /* TKLiquidSwitch.swift */, + E30C48D124FAE6BB0049D5C3 /* JDSwitch.swift */, + E30C48D224FAE6BB0049D5C3 /* UIImage+Extension.swift */, + E30C48D324FAE6BB0049D5C3 /* TKBaseSwitcher.swift */, + E30C48D424FAE6BB0049D5C3 /* SDSwitch.swift */, + E30C48D524FAE6BB0049D5C3 /* YapSwitch.swift */, + E30C48D624FAE6BB0049D5C3 /* BaseControl.swift */, + E30C48D724FAE6BB0049D5C3 /* TKSmileSwitch.swift */, + E30C48D824FAE6BB0049D5C3 /* CALayer+Extension.swift */, + ); + path = Switches; + sourceTree = ""; + }; + E30C48EA24FAE73F0049D5C3 /* SwitchesDemo */ = { + isa = PBXGroup; + children = ( + E30C494524FAE8350049D5C3 /* Model */, + E30C491924FAE76F0049D5C3 /* Application */, + E30C492124FAE76F0049D5C3 /* Controllers */, + E30C491C24FAE76F0049D5C3 /* Storyboard */, + E30C494124FAE7BC0049D5C3 /* Resources */, + ); + path = SwitchesDemo; + sourceTree = ""; + }; + E30C490124FAE7420049D5C3 /* SwitchesDemoTests */ = { + isa = PBXGroup; + children = ( + E30C490224FAE7420049D5C3 /* SwitchesDemoTests.swift */, + E30C490424FAE7420049D5C3 /* Info.plist */, + ); + path = SwitchesDemoTests; + sourceTree = ""; + }; + E30C490C24FAE7420049D5C3 /* SwitchesDemoUITests */ = { + isa = PBXGroup; + children = ( + E30C490D24FAE7420049D5C3 /* SwitchesDemoUITests.swift */, + E30C490F24FAE7420049D5C3 /* Info.plist */, + ); + path = SwitchesDemoUITests; + sourceTree = ""; + }; + E30C491924FAE76F0049D5C3 /* Application */ = { + isa = PBXGroup; + children = ( + E30C491A24FAE76F0049D5C3 /* AppDelegate.swift */, + E30C491B24FAE76F0049D5C3 /* SceneDelegate.swift */, + ); + path = Application; + sourceTree = ""; + }; + E30C491C24FAE76F0049D5C3 /* Storyboard */ = { + isa = PBXGroup; + children = ( + E30C491D24FAE76F0049D5C3 /* LaunchScreen.storyboard */, + E30C491F24FAE76F0049D5C3 /* Main.storyboard */, + ); + path = Storyboard; + sourceTree = ""; + }; + E30C492124FAE76F0049D5C3 /* Controllers */ = { + isa = PBXGroup; + children = ( + E30C492224FAE76F0049D5C3 /* SmileyViewController.swift */, + E30C492324FAE76F0049D5C3 /* ViewController.swift */, + E30C492424FAE76F0049D5C3 /* CollectionViewCell */, + E30C492624FAE76F0049D5C3 /* ModeSwitchesViewController.swift */, + E30C492724FAE76F0049D5C3 /* GradientSwitchesViewController.swift */, + E30C492824FAE76F0049D5C3 /* RandomViewController.swift */, + E30C492924FAE76F0049D5C3 /* ModeBSwitchesViewController.swift */, + E30C492A24FAE76F0049D5C3 /* SwiftyViewController.swift */, + E30C492B24FAE76F0049D5C3 /* AnimatedSwitchesViewController.swift */, + E30C492C24FAE76F0049D5C3 /* ThumbImageSwitchesViewController.swift */, + E30C492D24FAE76F0049D5C3 /* LoadingSwitchesViewController.swift */, + E30C492E24FAE76F0049D5C3 /* JellySwitchesViewController.swift */, + ); + path = Controllers; + sourceTree = ""; + }; + E30C492424FAE76F0049D5C3 /* CollectionViewCell */ = { + isa = PBXGroup; + children = ( + E30C492524FAE76F0049D5C3 /* CollectionViewCell.swift */, + ); + path = CollectionViewCell; + sourceTree = ""; + }; + E30C494124FAE7BC0049D5C3 /* Resources */ = { + isa = PBXGroup; + children = ( + E30C494224FAE7BC0049D5C3 /* Assets.xcassets */, + E30C48F924FAE7420049D5C3 /* Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + E30C494524FAE8350049D5C3 /* Model */ = { + isa = PBXGroup; + children = ( + E30C494624FAE8350049D5C3 /* SwitchType.swift */, + ); + path = Model; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -136,6 +367,59 @@ productReference = E30C48BA24FAE6930049D5C3 /* SwitchesTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + E30C48E824FAE73F0049D5C3 /* SwitchesDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = E30C491024FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemo" */; + buildPhases = ( + E30C48E524FAE73F0049D5C3 /* Sources */, + E30C48E624FAE73F0049D5C3 /* Frameworks */, + E30C48E724FAE73F0049D5C3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwitchesDemo; + productName = SwitchesDemo; + productReference = E30C48E924FAE73F0049D5C3 /* SwitchesDemo.app */; + productType = "com.apple.product-type.application"; + }; + E30C48FD24FAE7420049D5C3 /* SwitchesDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E30C491324FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemoTests" */; + buildPhases = ( + E30C48FA24FAE7420049D5C3 /* Sources */, + E30C48FB24FAE7420049D5C3 /* Frameworks */, + E30C48FC24FAE7420049D5C3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E30C490024FAE7420049D5C3 /* PBXTargetDependency */, + ); + name = SwitchesDemoTests; + productName = SwitchesDemoTests; + productReference = E30C48FE24FAE7420049D5C3 /* SwitchesDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + E30C490824FAE7420049D5C3 /* SwitchesDemoUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E30C491624FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemoUITests" */; + buildPhases = ( + E30C490524FAE7420049D5C3 /* Sources */, + E30C490624FAE7420049D5C3 /* Frameworks */, + E30C490724FAE7420049D5C3 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + E30C490B24FAE7420049D5C3 /* PBXTargetDependency */, + ); + name = SwitchesDemoUITests; + productName = SwitchesDemoUITests; + productReference = E30C490924FAE7420049D5C3 /* SwitchesDemoUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -152,6 +436,17 @@ E30C48B924FAE6930049D5C3 = { CreatedOnToolsVersion = 11.4.1; }; + E30C48E824FAE73F0049D5C3 = { + CreatedOnToolsVersion = 11.4.1; + }; + E30C48FD24FAE7420049D5C3 = { + CreatedOnToolsVersion = 11.4.1; + TestTargetID = E30C48E824FAE73F0049D5C3; + }; + E30C490824FAE7420049D5C3 = { + CreatedOnToolsVersion = 11.4.1; + TestTargetID = E30C48E824FAE73F0049D5C3; + }; }; }; buildConfigurationList = E30C48AB24FAE6930049D5C3 /* Build configuration list for PBXProject "Switches" */; @@ -169,6 +464,9 @@ targets = ( E30C48B024FAE6930049D5C3 /* Switches */, E30C48B924FAE6930049D5C3 /* SwitchesTests */, + E30C48E824FAE73F0049D5C3 /* SwitchesDemo */, + E30C48FD24FAE7420049D5C3 /* SwitchesDemoTests */, + E30C490824FAE7420049D5C3 /* SwitchesDemoUITests */, ); }; /* End PBXProject section */ @@ -188,6 +486,30 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E30C48E724FAE73F0049D5C3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E30C493224FAE76F0049D5C3 /* Main.storyboard in Resources */, + E30C494824FAEB5B0049D5C3 /* Assets.xcassets in Resources */, + E30C493124FAE76F0049D5C3 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C48FC24FAE7420049D5C3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C490724FAE7420049D5C3 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -195,6 +517,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E30C48DC24FAE6BB0049D5C3 /* TKLiquidSwitch.swift in Sources */, + E30C48D924FAE6BB0049D5C3 /* JDNavigationController.swift in Sources */, + E30C48E024FAE6BB0049D5C3 /* SDSwitch.swift in Sources */, + E30C48E124FAE6BB0049D5C3 /* YapSwitch.swift in Sources */, + E30C48E224FAE6BB0049D5C3 /* BaseControl.swift in Sources */, + E30C48DF24FAE6BB0049D5C3 /* TKBaseSwitcher.swift in Sources */, + E30C48DD24FAE6BB0049D5C3 /* JDSwitch.swift in Sources */, + E30C48DE24FAE6BB0049D5C3 /* UIImage+Extension.swift in Sources */, + E30C48DA24FAE6BB0049D5C3 /* JDNavigationBar.swift in Sources */, + E30C48E324FAE6BB0049D5C3 /* TKSmileSwitch.swift in Sources */, + E30C48DB24FAE6BB0049D5C3 /* Switcher.swift in Sources */, + E30C48E424FAE6BB0049D5C3 /* CALayer+Extension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -206,6 +540,44 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + E30C48E524FAE73F0049D5C3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E30C494724FAE8350049D5C3 /* SwitchType.swift in Sources */, + E30C493724FAE76F0049D5C3 /* GradientSwitchesViewController.swift in Sources */, + E30C493824FAE76F0049D5C3 /* RandomViewController.swift in Sources */, + E30C493A24FAE76F0049D5C3 /* SwiftyViewController.swift in Sources */, + E30C493E24FAE76F0049D5C3 /* JellySwitchesViewController.swift in Sources */, + E30C493C24FAE76F0049D5C3 /* ThumbImageSwitchesViewController.swift in Sources */, + E30C493024FAE76F0049D5C3 /* SceneDelegate.swift in Sources */, + E30C493324FAE76F0049D5C3 /* SmileyViewController.swift in Sources */, + E30C493B24FAE76F0049D5C3 /* AnimatedSwitchesViewController.swift in Sources */, + E30C493524FAE76F0049D5C3 /* CollectionViewCell.swift in Sources */, + E30C492F24FAE76F0049D5C3 /* AppDelegate.swift in Sources */, + E30C493624FAE76F0049D5C3 /* ModeSwitchesViewController.swift in Sources */, + E30C493924FAE76F0049D5C3 /* ModeBSwitchesViewController.swift in Sources */, + E30C493424FAE76F0049D5C3 /* ViewController.swift in Sources */, + E30C493D24FAE76F0049D5C3 /* LoadingSwitchesViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C48FA24FAE7420049D5C3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E30C490324FAE7420049D5C3 /* SwitchesDemoTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E30C490524FAE7420049D5C3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E30C490E24FAE7420049D5C3 /* SwitchesDemoUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -214,8 +586,37 @@ target = E30C48B024FAE6930049D5C3 /* Switches */; targetProxy = E30C48BC24FAE6930049D5C3 /* PBXContainerItemProxy */; }; + E30C490024FAE7420049D5C3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E30C48E824FAE73F0049D5C3 /* SwitchesDemo */; + targetProxy = E30C48FF24FAE7420049D5C3 /* PBXContainerItemProxy */; + }; + E30C490B24FAE7420049D5C3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E30C48E824FAE73F0049D5C3 /* SwitchesDemo */; + targetProxy = E30C490A24FAE7420049D5C3 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ +/* Begin PBXVariantGroup section */ + E30C491D24FAE76F0049D5C3 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + E30C491E24FAE76F0049D5C3 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + E30C491F24FAE76F0049D5C3 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + E30C492024FAE76F0049D5C3 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ E30C48C324FAE6930049D5C3 /* Debug */ = { isa = XCBuildConfiguration; @@ -388,6 +789,7 @@ E30C48C924FAE6930049D5C3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7VBQS7JDYT; INFOPLIST_FILE = SwitchesTests/Info.plist; @@ -406,6 +808,7 @@ E30C48CA24FAE6930049D5C3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7VBQS7JDYT; INFOPLIST_FILE = SwitchesTests/Info.plist; @@ -421,6 +824,126 @@ }; name = Release; }; + E30C491124FAE7420049D5C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemo/Resources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E30C491224FAE7420049D5C3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemo/Resources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + E30C491424FAE7420049D5C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemoTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwitchesDemo.app/SwitchesDemo"; + }; + name = Debug; + }; + E30C491524FAE7420049D5C3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemoTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwitchesDemo.app/SwitchesDemo"; + }; + name = Release; + }; + E30C491724FAE7420049D5C3 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemoUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemoUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = SwitchesDemo; + }; + name = Debug; + }; + E30C491824FAE7420049D5C3 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7VBQS7JDYT; + INFOPLIST_FILE = SwitchesDemoUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = XeroT.SwitchesDemoUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = SwitchesDemo; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -451,6 +974,33 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + E30C491024FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E30C491124FAE7420049D5C3 /* Debug */, + E30C491224FAE7420049D5C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E30C491324FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E30C491424FAE7420049D5C3 /* Debug */, + E30C491524FAE7420049D5C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E30C491624FAE7420049D5C3 /* Build configuration list for PBXNativeTarget "SwitchesDemoUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E30C491724FAE7420049D5C3 /* Debug */, + E30C491824FAE7420049D5C3 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = E30C48A824FAE6930049D5C3 /* Project object */; diff --git a/Switches.xcodeproj/xcuserdata/jawadali.xcuserdatad/xcschemes/xcschememanagement.plist b/Switches.xcodeproj/xcuserdata/jawadali.xcuserdatad/xcschemes/xcschememanagement.plist index 3706cc8..e2cba4a 100644 --- a/Switches.xcodeproj/xcuserdata/jawadali.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Switches.xcodeproj/xcuserdata/jawadali.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,11 @@ orderHint 0 + SwitchesDemo.xcscheme_^#shared#^_ + + orderHint + 1 + diff --git a/Switches/Navigation/JDNavigationBar.swift b/Switches/Navigation/JDNavigationBar.swift new file mode 100644 index 0000000..73050ed --- /dev/null +++ b/Switches/Navigation/JDNavigationBar.swift @@ -0,0 +1,236 @@ +// +// NavigationController.swift +// JDNavigationBar +// +// Created by Jawad Ali on 26/08/2020. +// Copyright © 2020 CocoaPods. All rights reserved. + +import UIKit + +// Availables Shapes +public enum ShapeMode: Int { + case zigzag = 0 + case wave + case folded + case square +} + +public class JDNavigationBar: UINavigationBar { + private var statusBar = UIView() + private var color: UIColor = #colorLiteral(red: 0.287330091, green: 0.7017020583, blue: 0.9429889321, alpha: 1) + public var cycles: Int = 3 { + didSet { + setNeedsDisplay() + } + } + + public var shape: ShapeMode = .wave { + didSet { + setNeedsDisplay() + } + } + + public var heightShape: CGFloat = 40 { + didSet { + self.heightShape = self.heightShape >= 0 ? self.heightShape : 0 + } + } + + private lazy var customHeight = self.bounds.height + self.heightShape + + let shadowLayer = CAShapeLayer() + + public override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + + func commonInit() { + + let shadow = NSShadow() + shadow.shadowColor = UIColor.black + shadow.shadowBlurRadius = 8 + shadow.shadowOffset = CGSize(width: 0, height: 3) + + self.titleTextAttributes = [.foregroundColor: UIColor.white, .font: UIFont(name:"AvenirNext-bold", size: 20)!, .shadow: shadow] + + barStyle = .black + isTranslucent = true + tintColor = .white + backgroundColor = .clear + changeColor(color) + shadowLayer.backgroundColor = UIColor.green.cgColor + DispatchQueue.main.async { + + if #available(iOS 13.0, *) { + + self.statusBar = UIView(frame: (UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.windowScene?.statusBarManager?.statusBarFrame) ?? CGRect.zero) + self.statusBar.backgroundColor = self.color + UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.addSubview(self.statusBar) + + } else { + // Apply color on status bar + if let getStatusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView { + self.statusBar = getStatusBar + if self.statusBar.responds(to: #selector(setter: UIView.backgroundColor)) { + self.statusBar.backgroundColor = self.color + } + } + } + } + } + + + public func changeColor(_ color : UIColor){ + self.color = color + shadowLayer.fillColor = self.color.cgColor + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + self.statusBar.backgroundColor = self.color + } + } + + override public func draw(_ rect: CGRect) { + + + switch shape { + case .folded: + shadowLayer.path = self.drawFolded() + case .wave: + shadowLayer.path = self.drawWave() + case .zigzag: + shadowLayer.path = self.drawZigzag() + case .square: + shadowLayer.path = self.drawSquare() + } + + self.layer.shadowColor = UIColor.black.cgColor + self.layer.shadowOpacity = 0.23 + self.layer.shadowRadius = 10 + self.layer.shadowOffset = CGSize(width: 0, height: 10) + self.layer.shouldRasterize = true + + + layer.insertSublayer(shadowLayer, below: self.topItem?.titleView?.layer) + } + +} + +//MARK:- Paths +extension JDNavigationBar { + + /* + Add a Zigzag shape to the navigation bar + */ + func drawZigzag()-> CGPath { + + let width = self.layer.frame.width + let height = self.layer.frame.height + + let bezierPath: UIBezierPath = UIBezierPath() + bezierPath.move(to: CGPoint(x: 0, y: 0)) + bezierPath.addLine(to: CGPoint(x: 0, y: height)) + + let cycleSizeHalf: CGFloat = (width / CGFloat(self.cycles)) / 2 + var x: CGFloat = 0 + for _ in 1...(self.cycles * 2) { + x = x + cycleSizeHalf + bezierPath.addLine(to: CGPoint(x: x, y: height + CGFloat(self.heightShape))) + x = x + cycleSizeHalf + bezierPath.addLine(to: CGPoint(x: x, y: height)) + } + bezierPath.addLine(to: CGPoint(x: width, y: 0)) + bezierPath.close() + return bezierPath.cgPath + } + + + + func drawFolded()-> CGPath { + let bezierPath: UIBezierPath = UIBezierPath() + let frame = CGRect(x: 0, y: 0, width: bounds.maxX, height: bounds.maxY + heightShape/2) + + bezierPath.append(UIBezierPath(roundedRect: frame, byRoundingCorners: [.bottomLeft ,.bottomRight], cornerRadii: CGSize(width: heightShape, height: heightShape))) + heightShape /= 2 + return bezierPath.cgPath + } + + /* + Add a Wave shape to the navigation bar + */ + + func drawWave()-> CGPath { + let width = self.layer.frame.width + let height = self.layer.frame.height + let bezierPath: UIBezierPath = UIBezierPath() + // Mandatory Odd number + if self.cycles % 2 == 0 { + self.cycles += 1 + } + + bezierPath.move(to: CGPoint(x: 0, y: 0)) + bezierPath.addLine(to: CGPoint(x: 0, y: height)) + + let cycleSize = width / CGFloat(self.cycles) + var x: CGFloat = 0 + let arcHeight = CGFloat(self.heightShape) / 2 + let y: CGFloat = height + arcHeight + + for i in 0.. CGPath { + let width = self.layer.frame.width + let height = self.layer.frame.height + let bezierPath: UIBezierPath = UIBezierPath() + bezierPath.move(to: CGPoint(x: 0, y: 0)) + bezierPath.addLine(to: CGPoint(x: 0, y: height)) + + let cycleSize: CGFloat = width / CGFloat(self.cycles * 2) + let xOffset = cycleSize / 2 + var x = xOffset + + bezierPath.addLine(to: CGPoint(x: xOffset, y: height)) + + for i in 0.. Void +open class BaseControl: UIControl { + + // MARK: - Property + open var valueChange: SDSwitchValueChange? + + open var isOn: Bool = false +} diff --git a/Switches/Switches/CALayer+Extension.swift b/Switches/Switches/CALayer+Extension.swift new file mode 100644 index 0000000..7d6d9c9 --- /dev/null +++ b/Switches/Switches/CALayer+Extension.swift @@ -0,0 +1,124 @@ +// +// CALayer+Extension.swift +// testi +// +// Created by Jawad Ali on 20/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +public extension CALayer { + + var areAnimationsEnabled: Bool { + get { delegate == nil } + set { delegate = newValue ? nil : CALayerAnimationsDisablingDelegate.shared } + } + + + private class CALayerAnimationsDisablingDelegate: NSObject, CALayerDelegate { + static let shared = CALayerAnimationsDisablingDelegate() + private let null = NSNull() + + func action(for layer: CALayer, forKey event: String) -> CAAction? { + null + } + } + + func bringToFront() { + guard let sLayer = superlayer else { + return + } + removeFromSuperlayer() + sLayer.insertSublayer(self, at: UInt32(sLayer.sublayers?.count ?? 0)) + } + + func sendToBack() { + guard let sLayer = superlayer else { + return + } + removeFromSuperlayer() + sLayer.insertSublayer(self, at: 0) + } + + + func animateGradientColors(from: [CGColor], to : [CGColor], duration: Double) { + let animation = CABasicAnimation(keyPath: "colors") + animation.fromValue = from + animation.toValue = to + animation.duration = duration + animation.fillMode = .forwards + animation.isRemovedOnCompletion = false + + // add the animation to the gradient + self.add(animation, forKey: nil) + + } + + func strokeAnimation(duration: Double) { + let animation = CABasicAnimation(keyPath: "strokeEnd") + animation.fromValue = 0 + animation.toValue = 1 + animation.duration = duration + animation.fillMode = .forwards + animation.isRemovedOnCompletion = false + self.add(animation, forKey: "line") + } + + func rotateAnimation(angal: CGFloat, duration: Double , repeatAnimation:Bool = false) { + + let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z") + rotationAnimation.fromValue = 0 + rotationAnimation.toValue = angal + rotationAnimation.duration = duration + rotationAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) + rotationAnimation.fillMode = .forwards + rotationAnimation.isRemovedOnCompletion = false + rotationAnimation.repeatCount = repeatAnimation ? .infinity : 0 + self.add(rotationAnimation, forKey: "rotation") + } + + func removeRotationAnimation() { + self.removeAnimation(forKey: "rotation") + } + + func animateShape(path: CGPath , duration: Double) { + + let animation = CABasicAnimation(keyPath: "path") + animation.duration = duration + animation.toValue = path + animation.timingFunction = CAMediaTimingFunction(name: .linear) + animation.isRemovedOnCompletion = false + animation.fillMode = .forwards + + self.add(animation, forKey: nil) + + } + + func doMask(by imageMask: UIImage) { + let maskLayer = CAShapeLayer() + maskLayer.bounds = CGRect(x: 0, y: 0, width: imageMask.size.width, height: imageMask.size.height) + bounds = maskLayer.bounds + maskLayer.contents = imageMask.cgImage + maskLayer.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height) + mask = maskLayer + } + + func toImage() -> UIImage? { + UIGraphicsBeginImageContextWithOptions(bounds.size, + isOpaque, + UIScreen.main.scale) + guard let context = UIGraphicsGetCurrentContext() else { + UIGraphicsEndImageContext() + return nil + } + render(in: context) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return image + } + + +} +extension BinaryInteger { + var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 } +} diff --git a/Switches/Switches/JDSwitch.swift b/Switches/Switches/JDSwitch.swift new file mode 100644 index 0000000..ada937f --- /dev/null +++ b/Switches/Switches/JDSwitch.swift @@ -0,0 +1,226 @@ +// +// JDSwitch.swift +// testi +// +// Created by Jawad Ali on 22/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +/// `Design by` : Oleg Frolov +// https://dribbble.com/shots/2346044-Switch-on-off + + +import UIKit +@IBDesignable public class JDSwitch: BaseControl { + + //MARK:- Views + private lazy var thumbLayer : CALayer = { + let layer = CALayer() + layer.shadowColor = UIColor.black.cgColor + layer.shadowRadius = 2 + layer.shadowOpacity = 0.4 + layer.shadowOffset = CGSize(width: 0.75, height: 2) + layer.contentsGravity = .resizeAspect + layer.backgroundColor = UIColor.white.cgColor + return layer + }() + + private lazy var trackLayer: CAShapeLayer = { + let shape = CAShapeLayer() + + shape.borderWidth = borderWidth + shape.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) + return shape + }() + + var changeThumbColor: Bool = false { + didSet { + setThumbColor() + } + } + + private var isTouchDown: Bool = false { + didSet { + layoutSublayers(of: layer) + changeThumbColor = true + } + } + //MARK:- Public Properties + + public var shape: shapeType = .rounded { + didSet{ + layoutSublayers(of: layer) + } + } + public var borderWidth: CGFloat = 0 { + didSet { + layoutSublayers(of: layer) + } + } + public var thumbRadiusPadding: CGFloat = 0 { + didSet { + layoutThumbLayer(for: layer.bounds) + } + } + public var thumbCornerRadius: CGFloat = 0 { + didSet { + layoutThumbLayer(for: layer.bounds) + } + } + public var thumbTintColor: UIColor? = nil { + didSet { setThumbColor() } + } + + public var onThumbTintColor: UIColor = #colorLiteral(red: 0.5438016653, green: 0.7640405893, blue: 0.291983664, alpha: 1) { + didSet { setThumbColor() } + } + + public var offThumbTintColor: UIColor = #colorLiteral(red: 0.864574194, green: 0.8753482103, blue: 0.848641932, alpha: 1) { + didSet { setThumbColor() } + } + + + //MARK:- initializers + convenience init() { + self.init(frame: .zero) + } + + override init(frame: CGRect) { + super.init(frame: frame) + controlDidLoad() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + controlDidLoad() + } + + //MARK:- Common Init + + private func controlDidLoad() { + layer.addSublayer(trackLayer) + layer.addSublayer(thumbLayer) + + layer.shadowOffset = .zero + layer.shadowOpacity = 0.3 + layer.shadowRadius = 5 + backgroundColor = .clear + + setThumbColor() + layoutSublayers(of: layer) + addTouchHandlers() + } + + final func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth + thumbRadiusPadding) + return CGSize(width: height, height: height) + } + + final func getThumbOrigin(for width: CGFloat) -> CGPoint { + + let inset = borderWidth + thumbRadiusPadding + if isTouchDown { + let x = (!isOn) ? bounds.width - width - inset : inset + return CGPoint(x: x, y: inset) + } else { + + let x = (isOn) ? bounds.width - width - inset : inset + return CGPoint(x: x, y: inset) + } + } + + private func getTackSize() -> CGSize { + isTouchDown ? CGSize(width: bounds.height, height: bounds.height) : bounds.size + } + + final func getTrackOrigin(for width: CGFloat) -> CGPoint { + let inset: CGFloat = 0.0 + let x = (!isOn) ? bounds.width - width : inset + return CGPoint(x: x, y: inset) + } + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + + layoutTrackLayer(for: layer.bounds) + layoutThumbLayer(for: layer.bounds) + } +} + +//MARK:- layout Layers +private extension JDSwitch { + + + func layoutTrackLayer(for bounds: CGRect) { + + let size = getTackSize() + let origin = getTrackOrigin(for: size.width) + trackLayer.frame = CGRect(origin: origin, size: size) + + shape == .rounded ? (trackLayer.cornerRadius = trackLayer.bounds.height / 2) : (trackLayer.cornerRadius = 5) + } + + func layoutThumbLayer(for bounds: CGRect) { + let size = getThumbSize() + let origin = getThumbOrigin(for: size.width) + thumbLayer.frame = CGRect(origin: origin, size: size) + + shape == .rounded ? (thumbLayer.cornerRadius = size.height / 2) : (thumbLayer.cornerRadius = thumbCornerRadius) + } +} + // MARK: - Touches +private extension JDSwitch { + + private func addTouchHandlers() { + addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter]) + addTarget(self, action: #selector(touchUp), for: [.touchUpInside]) + addTarget(self, action: #selector(touchEnded), for: [.touchDragExit, .touchCancel]) + + let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + leftSwipeGesture.direction = [.left] + addGestureRecognizer(leftSwipeGesture) + + let rightSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + rightSwipeGesture.direction = [.right] + addGestureRecognizer(rightSwipeGesture) + } + + @objc + func swipeLeftRight(_ gesture: UISwipeGestureRecognizer) { + let canLeftSwipe = isOn && gesture.direction == .left + let canRightSwipe = !isOn && gesture.direction == .right + guard canLeftSwipe || canRightSwipe else { return } + touchUp() + } + + @objc + func touchDown() { + isTouchDown = true + } + + @objc + func touchUp() { + isOn.toggle() + touchEnded() + } + + @objc + func touchEnded() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { + self.isTouchDown = false + } + + } +} + +//MARK:- color setting +extension JDSwitch { + private func setThumbColor(){ + if let thumbColor = thumbTintColor { + thumbLayer.backgroundColor = thumbColor.cgColor + } else { + thumbLayer.backgroundColor = (isOn ? onThumbTintColor : offThumbTintColor).cgColor + } + } + +} diff --git a/Switches/Switches/SDSwitch.swift b/Switches/Switches/SDSwitch.swift new file mode 100644 index 0000000..014848d --- /dev/null +++ b/Switches/Switches/SDSwitch.swift @@ -0,0 +1,536 @@ +// +// SDSwitch.swift +// testi +// +// Created by Jawad Ali on 22/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +//Crdit design by +///Mauricio Bucardo +//https://dribbble.com/shots/9841408-Loading-switch-interaction + + ///Alexis Doreau +//https://dribbble.com/shots/3545882-Switch-with-server-calls + +//// George Assan +//https://dribbble.com/shots/5192899-Simple-toggle + +import UIKit +enum LoadingResult { + case success + case failled +} + +public typealias SDSwitchLoadingStarted = () -> Void + +@IBDesignable public class SDSwitch: BaseControl { + + open var loadingStarted: SDSwitchLoadingStarted? + + //MARK:- Views + fileprivate lazy var thumbLayer : CALayer = { + let layer = CALayer() + layer.shadowColor = UIColor.black.cgColor + layer.shadowRadius = 2 + layer.shadowOpacity = 0.4 + layer.shadowOffset = CGSize(width: 0.75, height: 2) + layer.contentsGravity = .resizeAspect + layer.backgroundColor = UIColor.white.cgColor + return layer + }() + + fileprivate lazy var trackLayer: CALayer = { + let shape = CALayer() + shape.borderWidth = borderWidth + shape.borderColor = UIColor.blue.cgColor + + return shape + }() + private lazy var thumbLoadingCompleteLayer : CAShapeLayer = { + let shape = CAShapeLayer() + shape.lineWidth = thumbRadiusPadding + shape.strokeColor = loadingColor.cgColor + shape.fillColor = UIColor.clear.cgColor + shape.backgroundColor = UIColor.clear.cgColor + shape.lineCap = .round + return shape + }() + + private lazy var loadingLayer: CAShapeLayer = { + let shape = CAShapeLayer() + shape.lineWidth = thumbRadiusPadding + shape.strokeColor = loadingColor.cgColor + shape.fillColor = UIColor.clear.cgColor + shape.backgroundColor = UIColor.clear.cgColor + shape.lineCap = .round + return shape + }() + + var changeThumbColor: Bool = false { + didSet { + + setThumbColor() + } + } + + private var isLoadingCompleted = false + + private var loadingResult: LoadingResult = .success + + fileprivate var isTouchDown: Bool = false { + didSet { + layoutSublayers(of: layer) + changeThumbColor = true + stateDidChange() + } + } + //MARK:- Public Properties + + public var borderColor: UIColor? = nil { + didSet { setBorderColor() } + } + + public var onBorderColor: UIColor = .white { + didSet { setBorderColor() } + } + public var offBorderColor: UIColor = .white { + didSet { setBorderColor() } + } + + public var isLoadingEnabled: Bool = false + + public var shape: shapeType = .rounded { + didSet{ + layoutSublayers(of: layer) + } + } + public var borderWidth: CGFloat = 2 { + didSet { + trackLayer.borderWidth = borderWidth + layoutSublayers(of: layer) + } + } + public var thumbRadiusPadding: CGFloat = 4 { + didSet { + layoutSublayers(of: layer) + } + } + public var thumbCornerRadius: CGFloat = 0 { + didSet { + layoutThumbLayer(for: layer.bounds) + } + } + public var thumbTintColor: UIColor? = nil { + didSet { setThumbColor() } + } + + public var onThumbTintColor: UIColor = #colorLiteral(red: 0.9999018312, green: 1, blue: 0.9998798966, alpha: 1) { + didSet { setThumbColor() } + } + + public var offThumbTintColor: UIColor = #colorLiteral(red: 0.9999018312, green: 1, blue: 0.9998798966, alpha: 1) { + didSet { setThumbColor() } + } + + public var loadingColor: UIColor = #colorLiteral(red: 0.2855720818, green: 0.8943144679, blue: 0.6083024144, alpha: 1) { + didSet { loadingLayer.strokeColor = loadingColor.cgColor } + } + public var onTintColor: UIColor = #colorLiteral(red: 0.2855720818, green: 0.8943144679, blue: 0.6083024144, alpha: 1) { + didSet { + trackLayer.backgroundColor = getBackgroundColor() + + setNeedsLayout() + } + } + + public var offTintColor: UIColor = #colorLiteral(red: 0.823615551, green: 0.8911703229, blue: 0.9554550052, alpha: 1) { + didSet { + trackLayer.backgroundColor = getBackgroundColor() + setNeedsLayout() + } + } + + //MARK:- initializers + convenience init() { + self.init(frame: .zero) + } + + override init(frame: CGRect) { + super.init(frame: frame) + controlDidLoad() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + controlDidLoad() + } + + //MARK:- Common Init + + fileprivate func controlDidLoad() { + layer.addSublayer(trackLayer) + layer.addSublayer(thumbLayer) + + layer.shadowColor = UIColor.black.cgColor + layer.shadowOffset = .zero + layer.shadowOpacity = 0.3 + layer.shadowRadius = 10 + backgroundColor = .clear + + trackLayer.backgroundColor = getBackgroundColor() + setThumbColor() + layoutSublayers(of: layer) + addTouchHandlers() + } + + fileprivate func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth + thumbRadiusPadding) + return CGSize(width: height, height: height) + } + + final func getThumbOrigin(for width: CGFloat) -> CGPoint { + + let inset = borderWidth + thumbRadiusPadding + if isTouchDown { + + return CGPoint(x: bounds.midX - width/2, y: inset) + } else { + + + let x = (isOn) ? bounds.width - width - inset : inset + return CGPoint(x: x, y: inset) + } + } + + fileprivate func getTackSize() -> CGSize { + isTouchDown ? CGSize(width: bounds.height, height: bounds.height) : bounds.size + } + + final func getTrackOrigin(for width: CGFloat) -> CGPoint { + + if isTouchDown { + + return CGPoint(x: bounds.midX - width/2, y: 0) + } + + let inset: CGFloat = 0.0 + let x = (!isOn) ? bounds.width - width : inset + return CGPoint(x: x, y: inset) + } + + private func stateDidChange() { + + trackLayer.backgroundColor = getBackgroundColor() + } + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + + layoutTrackLayer(for: layer.bounds) + layoutThumbLayer(for: layer.bounds) + layoutLoadingLayer(for: layer.bounds) + + setBorderColor() + } + + + @objc final public func loadingCompleted(isSuccessFull: Bool) { + isLoadingCompleted = true + isSuccessFull ? (loadingResult = .success) : (loadingResult = .failled) + if !isSuccessFull { + isOn.toggle() + } + + loadingLayer.removeRotationAnimation() + loadingLayer.removeFromSuperlayer() + + + thumbLoadingCompleteLayer.path = (loadingResult == LoadingResult.success ) ? drawOnPath(thumbLayer.bounds) : drawOffPath(thumbLayer.bounds) + thumbLoadingCompleteLayer.lineWidth = thumbRadiusPadding/3 + thumbLoadingCompleteLayer.strokeColor = (isSuccessFull ? loadingColor : UIColor.red).cgColor + thumbLoadingCompleteLayer.strokeEnd = 0 + thumbLayer.addSublayer(thumbLoadingCompleteLayer) + + + CATransaction.setCompletionBlock { + print("completed") + self.isTouchDown = false + self.sendActions(for: .valueChanged) + self.valueChange?(self.isOn) + self.isUserInteractionEnabled = true + } + + CATransaction.begin() + thumbLoadingCompleteLayer.strokeAnimation(duration: 1) + CATransaction.commit() + } + +} + +//MARK:- layout Layers +private extension SDSwitch { + + func layoutTrackLayer(for bounds: CGRect) { + + let size = getTackSize() + let origin = getTrackOrigin(for: size.width) + trackLayer.frame = CGRect(origin: origin, size: size) + + shape == .rounded ? (trackLayer.cornerRadius = trackLayer.bounds.height / 2) : (trackLayer.cornerRadius = 5) + } + + func layoutThumbLayer(for bounds: CGRect) { + let size = getThumbSize() + let origin = getThumbOrigin(for: size.width) + thumbLayer.frame = CGRect(origin: origin, size: size) + + shape == .rounded ? (thumbLayer.cornerRadius = size.height / 2) : (thumbLayer.cornerRadius = thumbCornerRadius) + } + + func layoutLoadingLayer(for bounds: CGRect) { + loadingLayer.lineWidth = thumbRadiusPadding + + let loadingBounds = bounds.insetBy(dx: 0, dy: borderWidth + loadingLayer.lineWidth/2) + let center = CGPoint(x: bounds.midX, y: bounds.midY) + let bezierPath = UIBezierPath(arcCenter: center, radius:bounds.midY , startAngle: -110.degreesToRadians, endAngle: -60.degreesToRadians, clockwise: true) + loadingLayer.frame = loadingBounds + loadingLayer.path = bezierPath.cgPath + } + +} +// MARK: - Touches +private extension SDSwitch { + + private func addTouchHandlers() { + addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter]) + addTarget(self, action: #selector(touchUp), for: [.touchUpInside]) + addTarget(self, action: #selector(touchEnded), for: [.touchDragExit, .touchCancel]) + + let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + leftSwipeGesture.direction = [.left] + addGestureRecognizer(leftSwipeGesture) + + let rightSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + rightSwipeGesture.direction = [.right] + addGestureRecognizer(rightSwipeGesture) + } + + @objc + func swipeLeftRight(_ gesture: UISwipeGestureRecognizer) { + let canLeftSwipe = isOn && gesture.direction == .left + let canRightSwipe = !isOn && gesture.direction == .right + guard canLeftSwipe || canRightSwipe else { return } + touchUp() + } + + @objc + func touchDown() { + isLoadingCompleted = false + if thumbLayer.sublayers?.contains(thumbLoadingCompleteLayer) ?? false { + thumbLoadingCompleteLayer.removeFromSuperlayer() + } + + isTouchDown = true + + } + + @objc + func touchUp() { + isOn.toggle() + touchEnded() + } + + @objc + func touchEnded() { + if self.isLoadingEnabled && isOn { + performLoading() + + } else { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.isTouchDown = false + self.valueChange?(self.isOn) + } + } + + } + +} + +//MARK:- color setting +private extension SDSwitch { + func setThumbColor(){ + if let thumbColor = thumbTintColor { + thumbLayer.backgroundColor = thumbColor.cgColor + } else { + thumbLayer.backgroundColor = (isOn ? onThumbTintColor : offThumbTintColor).cgColor + } + } + func getBackgroundColor() -> CGColor { + return ((isOn && !isTouchDown) ? onTintColor : offTintColor).cgColor + } + func setBorderColor(){ + if let borderClor = borderColor { + trackLayer.borderColor = borderClor.cgColor + } else { + trackLayer.borderColor = (isOn ? onBorderColor : offBorderColor).cgColor + } + } + +} + +//MARK:- Loading Animation +private extension SDSwitch { + func performLoading() { + loadingStarted?() + layer.addSublayer(loadingLayer) + isUserInteractionEnabled = false + loadingLayer.rotateAnimation(angal: 360.degreesToRadians, duration: 1, repeatAnimation: true) + } +} + +private extension SDSwitch { + func drawOnPath(_ group:CGRect) -> CGPath { + + let bezierPath = UIBezierPath() + + let radius = group.maxX/5 + let center = CGPoint(x:group.midX,y:group.midY ) + + let x1 = center.x + (radius ) * cos(-45.degreesToRadians) + let y1 = center.y + (radius ) * sin(-45.degreesToRadians) + + let x2 = center.x + (radius ) * cos(135.degreesToRadians) + let y2 = center.y + (radius ) * sin(135.degreesToRadians) + + let x3 = center.x + (radius + radius * 0.5 ) * cos(-175.degreesToRadians) + let y3 = center.y + (radius + radius * 0.5 ) * sin(-175.degreesToRadians) + + bezierPath.move(to: CGPoint(x: x3, y: y3)) + bezierPath.addLine(to: CGPoint(x: x2, y: y2 )) + + bezierPath.addLine(to: CGPoint(x: x1, y: y1)) + + return bezierPath.cgPath + + } + private func drawOffPath(_ group:CGRect) -> CGPath { + + let bezierPath = UIBezierPath() + + let radius = group.maxX/5 + let center = CGPoint(x:group.midX,y:group.midY ) + + let x1 = center.x + (radius ) * cos(-45.degreesToRadians) + let y1 = center.y + (radius ) * sin(-45.degreesToRadians) + + + let x2 = center.x + (radius ) * cos(135.degreesToRadians) + let y2 = center.y + (radius ) * sin(135.degreesToRadians) + + + let x3 = center.x + (radius ) * cos(-135.degreesToRadians) + let y3 = center.y + (radius ) * sin(-135.degreesToRadians) + + let x4 = center.x + (radius ) * cos(45.degreesToRadians) + let y4 = center.y + (radius ) * sin(45.degreesToRadians) + + bezierPath.move(to: CGPoint(x: x3, y: y3)) + bezierPath.addLine(to: CGPoint(x: x4, y: y4)) + + bezierPath.move(to: CGPoint(x: x1, y: y1)) + bezierPath.addLine(to: CGPoint(x: x2, y: y2)) + + return bezierPath.cgPath + + } +} + +////`Crdit` :-Morph Switch +// https://dribbble.com/shots/2330566-Morph-Switch +@IBDesignable public class YapFullTextSwitch : SDSwitch { + + private lazy var contentsLayer: CATextLayer = CATextLayer() + + public var onText: String? { + didSet { + layoutTextLayerIfNeeded() + } + } + + public var offText: String? { + didSet { + layoutTextLayerIfNeeded() + } + } + public var onTextColor: UIColor = .white + + + public var offTextColor: UIColor = .white + + override func controlDidLoad() { + super.controlDidLoad() + + thumbLayer.addSublayer(contentsLayer) + thumbRadiusPadding = 0 + } + + override func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth ) + let width = (isTouchDown) ? bounds.width - 2 * (borderWidth ) : height + return CGSize(width: width, height: height) + } + + override func getTackSize() -> CGSize { + bounds.size + } + + override func touchEnded() { + if isOn { + contentsLayer.string = onText + contentsLayer.foregroundColor = onTextColor.cgColor + + } else { + contentsLayer.string = offText + contentsLayer.foregroundColor = offTextColor.cgColor + } + + setBorderColor() + trackLayer.backgroundColor = getBackgroundColor() + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.contentsLayer.string = nil + self.isTouchDown = false + self.valueChange?(self.isOn) + } + } + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + layoutContentLayer(for: bounds) + } + + + private func layoutContentLayer(for bounds: CGRect) { + let inset = 2 * (borderWidth ) + let y = bounds.maxY - inset + let leading = (borderWidth )/2 + let x = bounds.maxX - inset + let origin = CGPoint(x: leading, y: leading + bounds.midY/4) + + contentsLayer.frame = CGRect(origin: origin, size: CGSize(width: x, height: y)) + contentsLayer.contentsGravity = .center + contentsLayer.fontSize = bounds.height * 0.4 + + } + + // MARK: - Content Layers + private func layoutTextLayerIfNeeded() { + contentsLayer.alignmentMode = .center + contentsLayer.fontSize = bounds.height * 0.4 + contentsLayer.font = UIFont.systemFont(ofSize: 10, weight: .bold) + contentsLayer.contentsScale = UIScreen.main.scale + } + +} + diff --git a/Switches/Switches/Switcher.swift b/Switches/Switches/Switcher.swift new file mode 100644 index 0000000..69e6288 --- /dev/null +++ b/Switches/Switches/Switcher.swift @@ -0,0 +1,324 @@ +// +// Switcher.swift +// testi +// +// Created by Jawad Ali on 24/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +/// `Design by` : Oleg Frolov +// https://dribbble.com/shots/3844909-On-Off +//https://dribbble.com/shots/4148855-Switcher-XXXIII + + +@IBDesignable public class Switcher: BaseControl { + + //MARK:- Properties + @IBInspectable public var onTintColor: UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) { + didSet { + onThumbLayerColorChange() + } + } + + @IBInspectable public var offTintColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1) { + didSet { + offThumbLayerColorChange() + } + } + + //MARK:- Views + fileprivate lazy var thumbOnLayer : CALayer = { + let layer = CALayer() + layer.contentsGravity = .resizeAspect + layer.backgroundColor = onTintColor.cgColor + return layer + }() + + fileprivate lazy var thumbOffLayer : CALayer = { + let layer = CALayer() + + layer.contentsGravity = .resizeAspect + layer.backgroundColor = offTintColor.cgColor + return layer + }() + + private lazy var trackLayer: CAShapeLayer = { + let shape = CAShapeLayer() + shape.backgroundColor = UIColor.white.cgColor + return shape + }() + + fileprivate var thumbRadiusPadding: CGFloat = 10 + fileprivate var duration: Double = 1 + fileprivate var isTouchDown: Bool = false { + didSet { + layoutSublayers(of: layer) + } + } + + //MARK:- initializers + convenience init() { + self.init(frame: .zero) + } + + override init(frame: CGRect) { + super.init(frame: frame) + controlDidLoad() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + controlDidLoad() + } + + fileprivate func controlDidLoad() { + layer.addSublayer(trackLayer) + layer.addSublayer(thumbOffLayer) + layer.addSublayer(thumbOnLayer) + + layer.shadowOffset = .zero + layer.shadowOpacity = 0.3 + layer.shadowRadius = 5 + layer.masksToBounds = true + + self.isOn ? (self.trackLayer.backgroundColor = self.offTintColor.cgColor) : (self.trackLayer.backgroundColor = self.onTintColor.cgColor) + addTouchHandlers() + backgroundColor = .clear + } + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + layer.cornerRadius = bounds.midY + CATransaction.setAnimationDuration(duration) + CATransaction.begin() + + layoutLayers() + + CATransaction.commit() + } + + fileprivate func layoutLayers() { + layoutTrackLayer(for: layer.bounds) + layoutOnThumbLayer(for: layer.bounds) + layoutOffThumbLayer(for: layer.bounds) + } + + fileprivate func onThumbLayerColorChange() { + thumbOnLayer.backgroundColor = onTintColor.cgColor + self.isOn ? (self.trackLayer.backgroundColor = self.offTintColor.cgColor) : (self.trackLayer.backgroundColor = self.onTintColor.cgColor) + } + fileprivate func offThumbLayerColorChange(){ + thumbOffLayer.backgroundColor = offTintColor.cgColor + self.isOn ? (self.trackLayer.backgroundColor = self.offTintColor.cgColor) : (self.trackLayer.backgroundColor = self.onTintColor.cgColor) + } +} +//MARK:- layout Layers +fileprivate extension Switcher { + + func layoutTrackLayer(for bounds: CGRect) { + + trackLayer.frame = bounds + trackLayer.cornerRadius = trackLayer.bounds.midY + } + + @objc func layoutOnThumbLayer(for bounds: CGRect) { + let size = getOnThumbSize() + let origin = getOnThumbOrigin(for: size.width) + thumbOnLayer.frame = CGRect(origin: origin, size: size) + thumbOnLayer.cornerRadius = size.height/2 + } + @objc func layoutOffThumbLayer(for bounds: CGRect) { + let size = getOffThumbSize() + let origin = getOffThumbOrigin(for: size.width) + thumbOffLayer.frame = CGRect(origin: origin, size: size) + thumbOffLayer.cornerRadius = size.height/2 + } + + final func getOnThumbSize() -> CGSize { + let height = bounds.height - 2 * ( thumbRadiusPadding) + return ( isTouchDown && !isOn ) ? CGSize(width: bounds.maxX * 1.5, height: bounds.maxY * 2) : CGSize(width: height, height: height) + + } + final func getOffThumbSize() -> CGSize { + let height = bounds.height - 2 * ( thumbRadiusPadding) + return ( isTouchDown && isOn ) ? CGSize(width: bounds.maxX * 1.5, height: bounds.maxY * 2) : CGSize(width: height, height: height) + + } + + final func getOnThumbOrigin(for width: CGFloat) -> CGPoint { + + let inset = thumbRadiusPadding + return (isTouchDown && !isOn) ? CGPoint(x: -bounds.maxX/3, y: -bounds.midY * 0.8) : CGPoint( x: (bounds.width - width - inset),y: inset) + + } + final func getOffThumbOrigin(for width: CGFloat) -> CGPoint { + + let inset = thumbRadiusPadding + return (isTouchDown && isOn) ? CGPoint(x: -bounds.maxX/3, y: -bounds.midY * 0.8) : CGPoint( x: inset,y: inset) + + } +} +fileprivate extension Switcher { + + private func addTouchHandlers() { + addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter]) + addTarget(self, action: #selector(touchUp), for: [.touchUpInside]) + addTarget(self, action: #selector(touchEnded), for: [.touchDragExit, .touchCancel]) + + let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + leftSwipeGesture.direction = [.left] + addGestureRecognizer(leftSwipeGesture) + + let rightSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + rightSwipeGesture.direction = [.right] + addGestureRecognizer(rightSwipeGesture) + } + + @objc + func swipeLeftRight(_ gesture: UISwipeGestureRecognizer) { + let canLeftSwipe = isOn && gesture.direction == .left + let canRightSwipe = !isOn && gesture.direction == .right + guard canLeftSwipe || canRightSwipe else { return } + touchUp() + } + + @objc + func touchDown() { + + isUserInteractionEnabled = false + + UIView.animate(withDuration: 0.2, + animations: { + self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) + }) + } + + @objc + func touchUp() { + isOn.toggle() + touchEnded() + } + + @objc + func touchEnded() { + isTouchDown = true + + UIView.animate(withDuration: duration/3, + animations: { + self.transform = CGAffineTransform(scaleX: 1.05, y: 1.05) + }, + completion: { _ in + UIView.animate(withDuration: self.duration/3) { + self.transform = CGAffineTransform.identity + } + }) + + + DispatchQueue.main.asyncAfter(deadline: .now() + (duration)) { + self.isOn ? (self.trackLayer.backgroundColor = self.offTintColor.cgColor) : (self.trackLayer.backgroundColor = self.onTintColor.cgColor) + + self.isOn ? (self.thumbOffLayer.areAnimationsEnabled = false) : (self.thumbOnLayer.areAnimationsEnabled = false) + self.sendActions(for: .valueChanged) + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + + self.isUserInteractionEnabled = true + + self.isTouchDown = false + self.isOn ? self.thumbOffLayer.bringToFront() : self.thumbOnLayer.bringToFront() + self.isOn ? (self.thumbOffLayer.areAnimationsEnabled = true) : (self.thumbOnLayer.areAnimationsEnabled = true) + + } + } + } + +} +@IBDesignable public class SwitcherFullStrtech : Switcher { + + @IBInspectable public var thumbTintColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1) { + didSet { + ThumbLayerColorChange() + } + } + + private lazy var interactionLayer : CALayer = { + let shape = CALayer() + shape.backgroundColor = thumbTintColor.cgColor + return shape + + }() + + override func controlDidLoad() { + super.controlDidLoad() + layer.addSublayer(interactionLayer) + + thumbOnLayer.bringToFront() + thumbOffLayer.bringToFront() + duration = 0.5 + thumbRadiusPadding = 0 + + layer.masksToBounds = false + } + + override func layoutLayers() { + super.layoutLayers() + layoutInteractionLayerLayer(for: bounds) + } + + override func layoutOnThumbLayer(for bounds: CGRect) { + + let percent: CGFloat = bounds.maxY * 0.2 + + thumbOnLayer.frame = CGRect(x: bounds.midY - percent/2, y: bounds.midY - percent/2, width: percent, height: percent) + thumbOnLayer.cornerRadius = thumbOnLayer.bounds.midY + } + override func layoutOffThumbLayer(for bounds: CGRect) { + + let heightPercent: CGFloat = bounds.maxY * 0.4 + let widthPercent: CGFloat = bounds.maxY * 0.12 + + thumbOffLayer.frame = CGRect(x: bounds.maxX - bounds.midY - widthPercent/2 , y: bounds.midY - heightPercent/2, width: widthPercent, height: heightPercent) + thumbOffLayer.cornerRadius = thumbOffLayer.bounds.midX + } + + fileprivate override func onThumbLayerColorChange() { + thumbOnLayer.backgroundColor = onTintColor.cgColor + + } + + fileprivate override func offThumbLayerColorChange(){ + thumbOffLayer.backgroundColor = offTintColor.cgColor + + } + + override func touchEnded() { + isTouchDown = true + DispatchQueue.main.asyncAfter(deadline: .now() + (duration)) { + self.isTouchDown = false + self.isUserInteractionEnabled = true + + let onTint = self.onTintColor + self.onTintColor = self.offTintColor + self.offTintColor = onTint + + } + } + + func ThumbLayerColorChange(){ + interactionLayer.backgroundColor = thumbTintColor.cgColor + } +} + +extension SwitcherFullStrtech { + func layoutInteractionLayerLayer(for bounds: CGRect) { + interactionLayer.cornerRadius = bounds.midY + + isTouchDown ? ( interactionLayer.frame = bounds ) : (isOn ? (interactionLayer.frame = CGRect(x: bounds.maxX - bounds.maxY, y: 0, width: bounds.maxY, height: bounds.maxY)) : (interactionLayer.frame = CGRect(x: 0, y: 0, width: bounds.maxY, height: bounds.maxY))) + + } + + + +} + diff --git a/Switches/Switches/TKBaseSwitcher.swift b/Switches/Switches/TKBaseSwitcher.swift new file mode 100644 index 0000000..a611962 --- /dev/null +++ b/Switches/Switches/TKBaseSwitcher.swift @@ -0,0 +1,95 @@ +// +// TKBaseSwitcher.swift +// testi +// +// Created by Jawad Ali on 13/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +//// `Design by`: Oleg Frolov +// https://dribbble.com/shots/2028065-Switcher-lll?list=searches&tag=ui_animation&offset=2 + +import UIKit + +public typealias TKSwitchValueChangeHook = (_ value: Bool) -> Void + +// 自定义 Switch 基类 +@IBDesignable +open class TKBaseSwitch: BaseControl { + + // MARK: - Property + + @IBInspectable open var animateDuration: Double = 0.4 + + + internal var on: Bool = false + internal var sizeScale: CGFloat { + return min(self.bounds.width, self.bounds.height)/100.0 + } + + open override var frame: CGRect { + didSet { + guard frame.size != oldValue.size else { return } + resetView() + } + } + + open override var bounds: CGRect { + didSet { + guard frame.size != oldValue.size else { return } + resetView() + } + } + + // MARK: - Getter + + final public func setOn(_ on: Bool, animate: Bool = true) { + guard on != isOn else { return } + toggleValue() + } + + // MARK: - Init + convenience public init() { + self.init(frame: CGRect(x: 0, y: 0, width: 80, height: 40)) + } + + override public init(frame: CGRect) { + super.init(frame: frame) + setUpView() + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setUpView() + } + + // MARK: - Internal + + internal func resetView() { + gestureRecognizers?.forEach(self.removeGestureRecognizer) + layer.sublayers?.forEach({ $0.removeFromSuperlayer()}) + setUpView() + } + + internal func setUpView() { + let tap = UITapGestureRecognizer(target: self, action: #selector(TKBaseSwitch.toggleValue)) + self.addGestureRecognizer(tap) + + for view in self.subviews { + view.removeFromSuperview() + } + } + + @objc internal func toggleValue() { + + self.on.toggle() + self.isOn.toggle() + valueChange?(isOn) + sendActions(for: .valueChanged) + changeValueAnimate(isOn, duration: animateDuration) + } + + internal func changeValueAnimate(_ value: Bool, duration: Double) { + } + +} diff --git a/Switches/Switches/TKLiquidSwitch.swift b/Switches/Switches/TKLiquidSwitch.swift new file mode 100644 index 0000000..61bf92f --- /dev/null +++ b/Switches/Switches/TKLiquidSwitch.swift @@ -0,0 +1,146 @@ +// +// TKLiquidSwitch.swift +// testi +// +// Created by Jawad Ali on 13/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit + +// Dedign by Oleg Frolov +//https://dribbble.com/shots/2028065-Switcher-lll + +@IBDesignable +open class TKLiquidSwitch: TKBaseSwitch { + + private var bubbleLayer = CAShapeLayer() + private var lineLayer = CAShapeLayer() + @IBInspectable open var onColor = UIColor(red: 0.373, green: 0.843, blue: 0.596, alpha: 1) { + didSet { + resetView() + } + } + + @IBInspectable open var offColor = UIColor(red: 0.871, green: 0.871, blue: 0.871, alpha: 1) { + didSet { + resetView() + } + } + + override internal func setUpView() { + super.setUpView() + + self.clipsToBounds = true + + lineLayer.path = UIBezierPath(roundedRect: CGRect(x: 0, y: (self.bounds.height - 20 * sizeScale) / 2, width: self.bounds.width, height: 20 * sizeScale), cornerRadius: 10 * sizeScale).cgPath + lineLayer.fillColor = switchColor(isOn).cgColor + self.layer.addSublayer(lineLayer) + + bubbleLayer.frame = self.bounds + bubbleLayer.position = bubblePosition(isOn) + bubbleLayer.path = bubbleShapePath + bubbleLayer.fillColor = switchColor(isOn).cgColor + self.layer.addSublayer(bubbleLayer) + + } + + override func changeValueAnimate(_ value: Bool, duration: Double) { + let bubbleTransformAnim = CAKeyframeAnimation(keyPath: "transform") + bubbleTransformAnim.values = [NSValue(caTransform3D: CATransform3DIdentity), + NSValue(caTransform3D: CATransform3DMakeScale(1, 0.8, 1)), + NSValue(caTransform3D: CATransform3DMakeScale(0.8, 1, 1)), + NSValue(caTransform3D: CATransform3DIdentity)] + bubbleTransformAnim.keyTimes = [NSNumber(value: 0), NSNumber(value: 1.0 / 3.0), NSNumber(value: 2.0 / 3.0), NSNumber(value: 1)] + bubbleTransformAnim.duration = duration + + let bubblePositionAnim = CABasicAnimation(keyPath: "position") + bubblePositionAnim.fromValue = NSValue(cgPoint: bubblePosition(!isOn)) + bubblePositionAnim.toValue = NSValue(cgPoint: bubblePosition(isOn)) + bubblePositionAnim.duration = duration + + let bubbleGroupAnim = CAAnimationGroup() + bubbleGroupAnim.animations = [bubbleTransformAnim, bubblePositionAnim] + bubbleGroupAnim.isRemovedOnCompletion = false + bubbleGroupAnim.fillMode = CAMediaTimingFillMode.forwards + bubbleGroupAnim.duration = duration + + bubbleLayer.add(bubbleGroupAnim, forKey: "Bubble") + + let color = switchColor(value).cgColor + UIView.animate(withDuration: duration, animations: { () -> Void in + self.lineLayer.fillColor = color + self.bubbleLayer.fillColor = color + }) + + } +} + +// Getter +extension TKLiquidSwitch { + + var bubbleSize: CGSize { + let lineH = 20 * sizeScale + let w = lineH * 2 + bounds.height + let h = bounds.height + return CGSize(width: w, height: h) + } + + var bubbleShapePath: CGPath { + let bubblePath = UIBezierPath() + let size = bubbleSize + let sR = (size.width - size.height)/4 + let lR = size.height/2 + + let l1 = CGPoint(x: sR, y: lR - sR) + let l2 = CGPoint(x: sR, y: lR + sR) + + let c1 = CGPoint(x: sR * 2 + lR, y: 0) + let c2 = CGPoint(x: sR * 2 + lR, y: lR * 2) + + let r1 = CGPoint(x: sR * 3 + lR * 2, y: lR - sR) + let r2 = CGPoint(x: sR * 3 + lR * 2, y: lR + sR) + + let o1 = CGPoint(x: (lR + sR * 2)/4, y: lR - sR) + let o2 = CGPoint(x: (lR + sR * 2)/4, y: lR + sR) + let o3 = CGPoint(x: (lR * 2 + sR * 4) - (lR + sR * 2)/4, y: lR - sR) + let o4 = CGPoint(x: (lR * 2 + sR * 4) - (lR + sR * 2)/4, y: lR + sR) + + // let cL = CGPoint(x: sR, y: lR) + let cC = CGPoint(x: sR * 2 + lR, y: lR) + // let cR = CGPoint(x: sR * 3 + lR * 2, y: lR) + + bubblePath.move(to: l1) + bubblePath.addQuadCurve(to: c1, controlPoint: o1) + bubblePath.addArc(withCenter: cC, radius: lR, startAngle: -CGFloat.pi/2, endAngle: CGFloat.pi*3/2, clockwise: true) + bubblePath.addQuadCurve(to: r1, controlPoint: o3) + bubblePath.addLine(to: r2) + + bubblePath.addQuadCurve(to: c2, controlPoint: o4) + bubblePath.addQuadCurve(to: l2, controlPoint: o2) + bubblePath.addLine(to: l1) + bubblePath.close() + + return bubblePath.cgPath + } + + func switchColor(_ isOn: Bool) -> UIColor { + if isOn { + return onColor + } else { + return offColor + } + } + + func bubblePosition(_ isOn: Bool) -> CGPoint { + let h = self.bounds.height + let w = self.bounds.width + let bW = bubbleSize.width + + if isOn { + return CGPoint(x: bW * 0.8, y: h/2) + } else { + return CGPoint(x: w - bW*0.2, y: h/2) + } + } +} diff --git a/Switches/Switches/TKSmileSwitch.swift b/Switches/Switches/TKSmileSwitch.swift new file mode 100644 index 0000000..1617aa0 --- /dev/null +++ b/Switches/Switches/TKSmileSwitch.swift @@ -0,0 +1,171 @@ +// +// SmileSwitch.swift +// testi +// +// Created by Jawad Ali on 13/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit + +// Dedign by Oleg Frolov +//https://dribbble.com/shots/2011284-Switcher-ll + +open class TKSmileSwitch: TKBaseSwitch { + + // MARK: - Poperty + private var smileFace: TKSmileFaceView? + + // MARK: - Init + override internal func setUpView() { + super.setUpView() + backgroundColor = .clear + let frame = CGRect(x: self.bounds.width - self.bounds.height, y: 0, width: self.bounds.height, height: self.bounds.height) + smileFace = TKSmileFaceView(frame: frame) + addSubview(smileFace!) + + } + + override open func draw(_ rect: CGRect) { + let ctx = UIGraphicsGetCurrentContext() + let lineWidth = 10 * sizeScale + let path = UIBezierPath(roundedRect: rect.insetBy(dx: lineWidth, dy: lineWidth), cornerRadius: rect.width/2) + ctx?.setLineWidth(lineWidth*2) + ctx?.addPath(path.cgPath) + UIColor(white: 0.9, alpha: 1).setStroke() + ctx?.strokePath() + } + + override func changeValueAnimate(_ value: Bool, duration: Double) { + let x = value ? 0 : (bounds.width - bounds.height) + let frame = CGRect(x: x, y: 0, width: bounds.height, height: bounds.height) + self.smileFace!.faceType = value ? TKSmileFaceView.FaceType.happy : TKSmileFaceView.FaceType.sad + self.smileFace?.rotation(animateDuration, count: 2, clockwise: !isOn) + UIView.animate(withDuration: duration, animations: { () -> Void in + self.smileFace?.frame = frame + }, completion: { (complete) -> Void in + if complete { + self.smileFace?.eyeWinkAnimate(duration/2) + } + }) + + } +} + +// 脸 +private class TKSmileFaceView: UIView { + + enum FaceType { + case happy + case sad + func toColor() -> UIColor { + switch self { + case .happy: + return UIColor(red: 0.388, green: 0.839, blue: 0.608, alpha: 1.000) + case .sad: + return UIColor(red: 0.843, green: 0.369, blue: 0.373, alpha: 1) + } + } + } + + // MARK: - Property + let rightEye: CAShapeLayer = CAShapeLayer() + let leftEye: CAShapeLayer = CAShapeLayer() + let mouth: CAShapeLayer = CAShapeLayer() + let face: CAShapeLayer = CAShapeLayer() + + var faceType: FaceType = .sad { + didSet { + let position: CGFloat = isHappy ? 20 * sizeScale : 35 * sizeScale + mouth.path = mouthPath.cgPath + mouth.frame = CGRect(x: 0, y: position, width: 60 * sizeScale, height: 20 * sizeScale) + face.fillColor = faceType.toColor().cgColor + } + } + + // MARK: - Getter + var isHappy: Bool { + return (faceType == .happy) + } + + var sizeScale: CGFloat { + return min(self.bounds.width, self.bounds.height)/100.0 + } + + var mouthPath: UIBezierPath { + get { + let point: CGFloat = isHappy ? 70 * sizeScale : 10 + let path = UIBezierPath() + path.move(to: CGPoint(x: 30 * sizeScale, y: 40 * sizeScale)) + path.addCurve(to: CGPoint(x: 70 * sizeScale, y: 40 * sizeScale), controlPoint1: CGPoint(x: 30 * sizeScale, y: 40 * sizeScale), controlPoint2: CGPoint(x: 50 * sizeScale, y: point)) + path.lineCapStyle = .round + return path + } + } + + // MARK: - Init + override init(frame: CGRect) { + super.init(frame: frame) + self.setupLayers() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.setupLayers() + } + + // MARK: - Private Func + private func setupLayers() { + + let facePath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100 * sizeScale, height: 100 * sizeScale)) + let eyePath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 20 * sizeScale, height: 20 * sizeScale)) + + face.frame = CGRect(x: 0, y: 0, width: 100 * sizeScale, height: 100 * sizeScale) + face.path = facePath.cgPath + face.fillColor = faceType.toColor().cgColor + layer.addSublayer(face) + + leftEye.frame = CGRect(x: 20 * sizeScale, y: 28 * sizeScale, width: 10 * sizeScale, height: 10 * sizeScale) + leftEye.path = eyePath.cgPath + leftEye.fillColor = UIColor.white.cgColor + layer.addSublayer(leftEye) + + rightEye.frame = CGRect(x: 60 * sizeScale, y: 28 * sizeScale, width: 10 * sizeScale, height: 10 * sizeScale) + rightEye.path = eyePath.cgPath + rightEye.fillColor = UIColor.white.cgColor + layer.addSublayer(rightEye) + + mouth.path = mouthPath.cgPath + mouth.strokeColor = UIColor.white.cgColor + mouth.fillColor = UIColor.clear.cgColor + mouth.lineCap = .round + mouth.lineWidth = 10 * sizeScale + layer.addSublayer(mouth) + + faceType = .sad + + } + + // MARK: - Animate + func eyeWinkAnimate(_ duration: Double) { + let eyeleftTransformAnim = CAKeyframeAnimation(keyPath: "transform") + eyeleftTransformAnim.values = [NSValue(caTransform3D: CATransform3DIdentity), + NSValue(caTransform3D: CATransform3DMakeScale(1, 0.1, 1)), + NSValue(caTransform3D: CATransform3DIdentity) + ] + eyeleftTransformAnim.keyTimes = [0, 0.5, 1] + eyeleftTransformAnim.duration = duration + leftEye.add(eyeleftTransformAnim, forKey: "Wink") + rightEye.add(eyeleftTransformAnim, forKey: "Wink") + } + + func rotation(_ duration: Double, count: Int, clockwise: Bool) { + let rotationTransformAnim = CAKeyframeAnimation(keyPath: "transform.rotation.z") + rotationTransformAnim.values = [0, 180 * CGFloat.pi/180 * CGFloat(count) * (clockwise ? 1 : -1)] + rotationTransformAnim.keyTimes = [0, 1] + rotationTransformAnim.isRemovedOnCompletion = false + rotationTransformAnim.duration = duration + layer.add(rotationTransformAnim, forKey: "Rotation") + } + +} diff --git a/Switches/Switches/UIImage+Extension.swift b/Switches/Switches/UIImage+Extension.swift new file mode 100644 index 0000000..8b938c8 --- /dev/null +++ b/Switches/Switches/UIImage+Extension.swift @@ -0,0 +1,22 @@ +// +// UIImage+Extension.swift +// testi +// +// Created by Jawad Ali on 29/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +public extension UIImage { + + func maskWithColor(color: UIColor) -> UIImage? { + + let maskLayer = CALayer() + maskLayer.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height) + maskLayer.backgroundColor = color.cgColor + maskLayer.doMask(by: self) + let maskImage = maskLayer.toImage() + return maskImage + } + +} diff --git a/Switches/Switches/YapSwitch.swift b/Switches/Switches/YapSwitch.swift new file mode 100644 index 0000000..a5067ca --- /dev/null +++ b/Switches/Switches/YapSwitch.swift @@ -0,0 +1,943 @@ +// +// Switch.swift +// testi +// +// Created by Jawad Ali on 13/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +//// `Design by`: Anupam +//https://dribbble.com/shots/4908263-Switch-UI + +//// `Design by` : Maria Kovalevich +//https://dribbble.com/shots/4685786-Daily-UI-015-On-Off-Switch-clickable-prototype +import Foundation +import UIKit +public enum shapeType { + case square + case rounded +} + +@IBDesignable public class YapSwitch: BaseControl { + + //MARK:- Properties + + //// corner radius of thumbnail in case of square + //// It has no effect if shape is rounded + + public var thumbCornerRadius: CGFloat = 0 { + didSet { + layoutThumbLayer(for: layer.bounds) + } + } + + //// if stretch is enable .. on touch down thumbnail increase its width.... + public var isStretchEnable: Bool = true + + /// `shape` of your switch ... it can either be rounded or square .. you can set it accordingly + + public var shape: shapeType = .rounded { + didSet{ + layoutSublayers(of: layer) + } + } + + /// Width of the border... it can have any `float` value + public var borderWidth: CGFloat = 0 { + didSet { + trackLayer.borderWidth = borderWidth + layoutSublayers(of: layer) + } + } + + + public var borderColor: UIColor? = nil { + didSet { setBorderColor() } + } + + public var onBorderColor: UIColor = .white { + didSet { setBorderColor() } + } + public var offBorderColor: UIColor = .white { + didSet { setBorderColor() } + } + + public var textColor: UIColor? = nil { + didSet { + (offContentLayer as? CATextLayer)?.foregroundColor = textColor?.cgColor + (onContentLayer as? CATextLayer)?.foregroundColor = textColor?.cgColor + } + } + + public var onTextColor: UIColor = .white { + didSet { + + (onContentLayer as? CATextLayer)?.foregroundColor = onTextColor.cgColor + } + } + + public var offTextColor: UIColor = .white { + didSet { + (offContentLayer as? CATextLayer)?.foregroundColor = offTextColor.cgColor + + } + } + + public var trackTopBottomPadding: CGFloat = 0 { + didSet { + layoutSublayers(of: layer) + } + } + + public var contentLeadingTrailingPadding: CGFloat = 0 { + didSet { + layoutSublayers(of: layer) + } + } + + //// Distance of `thumb` from track layer + public var thumbRadiusPadding: CGFloat = 3.5 { + didSet { + layoutThumbLayer(for: layer.bounds) + } + } + + public var onTintColor: UIColor = UIColor(red: 0, green: 122/255, blue: 1, alpha: 1) { + didSet { + trackLayer.backgroundColor = getBackgroundColor() + + setNeedsLayout() + } + } + + public var offTintColor: UIColor = .white { + didSet { + trackLayer.backgroundColor = getBackgroundColor() + setNeedsLayout() + } + } + + public var thumbTintColor: UIColor? = nil { + didSet { setThumbColor() } + } + + public var onThumbTintColor: UIColor = .white { + didSet { setThumbColor() } + } + + public var offThumbTintColor: UIColor = .white { + didSet { setThumbColor() } + } + + public var onText: String? { + didSet { + addOnTextLayerIfNeeded() + (onContentLayer as? CATextLayer)?.string = onText + } + } + + public var offText: String? { + didSet { + addOffTextLayerIfNeeded() + (offContentLayer as? CATextLayer)?.string = offText + + } + } + + public var onThumbImage: UIImage? { + didSet { + thumbLayer.contents = onThumbImage?.cgImage + } + } + + public var offThumbImage: UIImage? { + didSet { + thumbLayer.contents = offThumbImage?.cgImage + } + } + + public var thumbImage: UIImage? { + didSet { + thumbLayer.contents = thumbImage?.cgImage + } + } + + + public var onImage: UIImage? { + didSet { + addOnImageLayerIfNeeded() + onContentLayer?.contents = onImage?.cgImage + + } + } + + public var offImage: UIImage? { + didSet { + addOffImageLayerIfNeeded() + offContentLayer?.contents = offImage?.cgImage + } + } + + public override var intrinsicContentSize: CGSize { + return CGSize(width: 52, height: 31) + } + + //MARK:- Layers + //// `trackLayer`:- is main track layer + //// `innerLayer`:- over track layer + ////`thumLayer` :- it is used for thumb + + fileprivate lazy var trackLayer = CALayer() + fileprivate lazy var innerLayer = CALayer() + fileprivate lazy var thumbLayer : CALayer = { + let layer = CALayer() + layer.shadowColor = UIColor.black.cgColor + layer.shadowRadius = 2 + layer.shadowOpacity = 0.4 + layer.shadowOffset = CGSize(width: 0.75, height: 2) + layer.contentsGravity = .resizeAspect + return layer + }() + private lazy var contentsLayer = CALayer() + + private var onContentLayer: CALayer? { + willSet { + onContentLayer?.removeFromSuperlayer() + } + didSet { + layoutOnContentLayer(for: layer.bounds) + } + } + + private var offContentLayer: CALayer? { + willSet { + offContentLayer?.removeFromSuperlayer() + } + didSet { + layoutOffContentLayer(for: layer.bounds) + } + } + + fileprivate var isTouchDown: Bool = false + + //MARK:- initializers + + convenience init() { + self.init(frame: .zero) + frame.size = intrinsicContentSize + } + + override init(frame: CGRect) { + super.init(frame: frame) + controlDidLoad() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + controlDidLoad() + } + + //MARK:- Common Init + + fileprivate func controlDidLoad() { + layer.shadowOffset = .zero + layer.shadowOpacity = 0.3 + layer.shadowRadius = 5 + + backgroundColor = .clear + + layer.addSublayer(trackLayer) + layer.addSublayer(innerLayer) + layer.addSublayer(contentsLayer) + layer.addSublayer(thumbLayer) + + trackLayer.backgroundColor = getBackgroundColor() + setBorderColor() + trackLayer.borderWidth = borderWidth + + innerLayer.backgroundColor = UIColor.white.cgColor + + contentsLayer.masksToBounds = true + + setThumbColor() + + addTouchHandlers() + + layoutSublayers(of: layer) + } + + //MARK:- layoutSubviews + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + + layoutTrackLayer(for: layer.bounds) + layoutThumbLayer(for: layer.bounds) + contentsLayer.frame = layer.bounds + layoutOffContentLayer(for: layer.bounds) + layoutOnContentLayer(for: layer.bounds) + + } + + public override func didMoveToSuperview() { + layoutSublayers(of: layer) + } + + fileprivate func layoutTrackLayer(for bounds: CGRect) { + trackLayer.frame = bounds.insetBy(dx: trackTopBottomPadding, dy: trackTopBottomPadding) + shape == .rounded ? (trackLayer.cornerRadius = trackLayer.bounds.height / 2) : (trackLayer.cornerRadius = bounds.height * 0.12) + } + + fileprivate func layoutInnerLayer(for bounds: CGRect) { + let inset = borderWidth + trackTopBottomPadding + let isInnerHidden = isOn || (isTouchDown && isStretchEnable) + + innerLayer.frame = isInnerHidden + ? CGRect(origin: trackLayer.position, size: .zero) + : bounds.insetBy(dx: inset, dy: inset) + + shape == .rounded ? (innerLayer.cornerRadius = isInnerHidden ? 0 : bounds.height / 2 - inset) : (innerLayer.cornerRadius = isInnerHidden ? 5 : 5) + } + + fileprivate func layoutThumbLayer(for bounds: CGRect) { + let size = getThumbSize() + let origin = getThumbOrigin(for: size.width) + thumbLayer.frame = CGRect(origin: origin, size: size) + + if let thumb = thumbImage { + onThumbImage = thumb + offThumbImage = thumb + } + + thumbLayer.contents = isOn ? onThumbImage?.cgImage : offThumbImage?.cgImage + + shape == .rounded ? (thumbLayer.cornerRadius = size.height / 2) : (thumbLayer.cornerRadius = thumbCornerRadius) + } + + private func layoutOffContentLayer(for bounds: CGRect) { + + let size = getContentLayerSize(for: offContentLayer) + let y = bounds.midY - size.height / 2 + let leading = (bounds.maxX - (contentLeadingTrailingPadding + borderWidth + getThumbSize().width))/2 - size.width/2 + let x = !isOn ? bounds.width - size.width - leading : bounds.width + let origin = CGPoint(x: x, y: y) + offContentLayer?.frame = CGRect(origin: origin, size: size) + bounds.height < 50 ? ((offContentLayer as? CATextLayer)?.fontSize = 12) : ((offContentLayer as? CATextLayer)?.fontSize = bounds.height * 0.2) + + } + + private func layoutOnContentLayer(for bounds: CGRect) { + let size = getContentLayerSize(for: onContentLayer) + let y = bounds.midY - size.height / 2 + let leading = (bounds.maxX - (contentLeadingTrailingPadding + borderWidth + getThumbSize().width))/2 - size.width/2 + let x = isOn ? leading : -bounds.width / 2 + let origin = CGPoint(x: x, y: y) + onContentLayer?.frame = CGRect(origin: origin, size: size) + onContentLayer?.contentsCenter = CGRect(origin: origin, size: size) + bounds.height < 50 ? ((onContentLayer as? CATextLayer)?.fontSize = 12) : ((onContentLayer as? CATextLayer)?.fontSize = bounds.height * 0.2) + } + + fileprivate func stateDidChange() { + trackLayer.backgroundColor = getBackgroundColor() + trackLayer.borderWidth = borderWidth + thumbLayer.contents = isOn ? onThumbImage?.cgImage : offThumbImage?.cgImage + setThumbColor() + sendActions(for: .valueChanged) + valueChange?(isOn) + } + + public func setOn(_ on: Bool, animated: Bool) { + CATransaction.begin() + CATransaction.setDisableActions(!animated) + isOn = on + layoutSublayers(of: layer) + sendActions(for: .valueChanged) + valueChange?(isOn) + CATransaction.commit() + } + + // MARK: - Touches + private func addTouchHandlers() { + addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter]) + addTarget(self, action: #selector(touchUp), for: [.touchUpInside]) + addTarget(self, action: #selector(touchEnded), for: [.touchDragExit, .touchCancel]) + + let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + leftSwipeGesture.direction = [.left] + addGestureRecognizer(leftSwipeGesture) + + let rightSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeftRight(_:))) + rightSwipeGesture.direction = [.right] + addGestureRecognizer(rightSwipeGesture) + } + + @objc + private func swipeLeftRight(_ gesture: UISwipeGestureRecognizer) { + let canLeftSwipe = isOn && gesture.direction == .left + let canRightSwipe = !isOn && gesture.direction == .right + guard canLeftSwipe || canRightSwipe else { return } + touchUp() + } + + @objc + fileprivate func touchDown() { + print("touch down") + isTouchDown = true + layoutSublayers(of: layer) + } + + @objc + fileprivate func touchUp() { + isOn.toggle() + stateDidChange() + touchEnded() + } + + @objc + fileprivate func touchEnded() { + isTouchDown = false + layoutSublayers(of: layer) + } + + // MARK: - Layout Helper + fileprivate func setBorderColor(){ + if let borderClor = borderColor { + trackLayer.borderColor = borderClor.cgColor + } else { + trackLayer.borderColor = (isOn ? onBorderColor : offBorderColor).cgColor + } + } + + private func setThumbColor(){ + if let thumbColor = thumbTintColor { + thumbLayer.backgroundColor = thumbColor.cgColor + } else { + thumbLayer.backgroundColor = (isOn ? onThumbTintColor : offThumbTintColor).cgColor + } + } + + final func getBackgroundColor() -> CGColor { + return (isOn ? onTintColor : offTintColor).cgColor + } + + fileprivate func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth + thumbRadiusPadding) + let width = (isTouchDown && isStretchEnable) ? height * 1.2 : height + return CGSize(width: width, height: height) + } + + final func getThumbOrigin(for width: CGFloat) -> CGPoint { + let inset = borderWidth + thumbRadiusPadding + let x = isOn ? bounds.width - width - inset : inset + return CGPoint(x: x, y: inset) + } + + final func getContentLayerSize(for layer: CALayer?) -> CGSize { + let inset = 2 * (borderWidth + trackTopBottomPadding) + let diameter = bounds.height - inset - getThumbSize().height/2 + if let textLayer = layer as? CATextLayer { + return textLayer.preferredFrameSize() + } + return CGSize(width: diameter, height: diameter) + } + + // MARK: - Content Layers + private func addOffTextLayerIfNeeded() { + guard offText != nil else { + offContentLayer = nil + return + } + let textLayer = CATextLayer() + textLayer.alignmentMode = .center + textLayer.fontSize = bounds.height * 0.2 + textLayer.font = UIFont.systemFont(ofSize: 10, weight: .bold) + + textLayer.foregroundColor = (textColor == nil) ? offTextColor.cgColor : textColor?.cgColor + textLayer.contentsScale = UIScreen.main.scale + contentsLayer.addSublayer(textLayer) + offContentLayer = textLayer + } + + private func addOnTextLayerIfNeeded() { + guard onText != nil else { + onContentLayer = nil + return + } + let textLayer = CATextLayer() + textLayer.alignmentMode = .center + textLayer.fontSize = bounds.height * 0.2 + textLayer.font = UIFont.systemFont(ofSize: 10, weight: .bold) + textLayer.foregroundColor = (textColor == nil) ? onTextColor.cgColor : textColor?.cgColor + textLayer.contentsScale = UIScreen.main.scale + contentsLayer.addSublayer(textLayer) + onContentLayer = textLayer + } + + private func addOnImageLayerIfNeeded() { + guard onImage != nil else { + onContentLayer = nil + return + } + let imageLayer = CALayer() + imageLayer.contentsGravity = .center + imageLayer.contentsScale = UIScreen.main.scale + contentsLayer.addSublayer(imageLayer) + onContentLayer = imageLayer + } + + private func addOffImageLayerIfNeeded() { + guard offImage != nil else { + offContentLayer = nil + return + } + let imageLayer = CALayer() + imageLayer.contentsGravity = .resizeAspect + imageLayer.contentsScale = UIScreen.main.scale + contentsLayer.addSublayer(imageLayer) + offContentLayer = imageLayer + } +} + +@IBDesignable public class YapSwitchSlim: YapSwitch { + + public var slimTrack: CGFloat = 0 { + didSet { + layoutSublayers(of: layer) + } + } + + override func layoutTrackLayer(for bounds: CGRect) { + trackLayer.frame = bounds.insetBy(dx: trackTopBottomPadding, dy: trackTopBottomPadding + slimTrack) + self.shape == .rounded ? (self.trackLayer.cornerRadius = self.trackLayer.bounds.height / 2) : (self.trackLayer.cornerRadius = bounds.height * 0.2) + } + + override func layoutInnerLayer(for bounds: CGRect) { + let inset = borderWidth + trackTopBottomPadding + let isInnerHidden = isOn || (isTouchDown && isStretchEnable) + + innerLayer.frame = isInnerHidden + ? CGRect(origin: trackLayer.position, size: .zero) + : trackLayer.frame.insetBy(dx: inset, dy: inset) + + shape == .rounded ? (innerLayer.cornerRadius = isInnerHidden ? 0 : innerLayer.bounds.height / 2 - inset) : (innerLayer.cornerRadius = isInnerHidden ? 5 : 5) + } + + +} + +//MARK:- YapGradientSwitch +public enum GradientPosition { + case vertical + case horizatal +} + +@IBDesignable public class YapGradientSwitch: YapSwitch { + + private lazy var onGradientLayer = CAGradientLayer() + private lazy var offGradientLayer = CAGradientLayer() + + public var gradientPosition: GradientPosition = .horizatal { + didSet { + setGradientPosition() + layoutSublayers(of: layer) + } + } + + public var onColors : [UIColor] = [UIColor.red, UIColor.yellow] { + didSet { + onGradientLayer.colors = onColors.map{$0.cgColor} + } + } + + public var offColors : [UIColor] = [UIColor.red, UIColor.yellow] { + didSet { + offGradientLayer.colors = offColors.map{$0.cgColor} + } + } + + func createGradientLayer() { + + trackLayer.addSublayer(onGradientLayer) + innerLayer.addSublayer(offGradientLayer) + setGradientPosition() + + } + + private func setGradientPosition() { + if gradientPosition == .horizatal { + onGradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + onGradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + + offGradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + offGradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + } else { + onGradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) + onGradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0) + + offGradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0) + offGradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0) + } + } + + override func controlDidLoad() { + super.controlDidLoad() + createGradientLayer() + } + + public override func layoutSublayers(of layer: CALayer) { + super.layoutSublayers(of: layer) + layoutInnerLayer(for: bounds) + + onGradientLayer.frame = trackLayer.bounds + offGradientLayer.frame = trackLayer.bounds + + innerLayer.masksToBounds = true + + onGradientLayer.cornerRadius = trackLayer.cornerRadius + offGradientLayer.cornerRadius = innerLayer.cornerRadius + } + + +} + +private protocol AnimationPath { + func drawOnPath(_ group:CGRect) -> CGPath + func drawOffPath(_ group:CGRect) -> CGPath +} + +//// `Credit Design` : Andrei Mironov +//https://dribbble.com/shots/2309834-Yet-another-toggle-animation + +//MARK:- YapAnimatedSwitch + +@IBDesignable public class YapAnimatedSwitch: YapSwitch { + + public var animationColor: UIColor? = nil { + didSet { setShapeColor() } + } + + public var onAnimationColor: UIColor = .white { + didSet { setShapeColor() } + } + + public var offAnimationColor: UIColor = .white { + didSet { setShapeColor() } + } + + public var animationWidth: CGFloat = 3 { + didSet { shapeLayer.lineWidth = animationWidth } + } + + private lazy var shapeLayer : CAShapeLayer = { + let shape = CAShapeLayer() + shape.fillColor = UIColor.clear.cgColor + shape.lineCap = .round + shape.lineWidth = animationWidth + return shape + }() + + public let duration:Double = 0.6 + + override func controlDidLoad() { + super.controlDidLoad() + + isStretchEnable = false + thumbLayer.addSublayer(shapeLayer) + setShapeColor() + DispatchQueue.main.async { + + self.layoutThumbLayer(for: self.bounds) + self.isOn ? (self.shapeLayer.path = self.drawOnPath(self.thumbLayer.bounds)) : (self.shapeLayer.path = self.drawOffPath(self.thumbLayer.bounds)) + } + + } + + private func setShapeColor() { + shapeLayer.strokeColor = (animationColor ?? (isOn ? onAnimationColor : offAnimationColor)).cgColor + } + + public override func layoutSublayers(of layer: CALayer) { + + CATransaction.setAnimationDuration(duration) + CATransaction.begin() + super.layoutSublayers(of: layer) + CATransaction.commit() + + shapeLayer.frame = thumbLayer.bounds + + } + + override func stateDidChange() { + + super.stateDidChange() + isOn ? shapeLayer.animateShape(path: drawOnPath(thumbLayer.bounds), duration: (duration - duration/2)) : shapeLayer.animateShape(path: drawOffPath(thumbLayer.bounds), duration: (duration - duration/2)) + isOn ? shapeLayer.rotateAnimation(angal: 0, duration: duration) : shapeLayer.rotateAnimation(angal: .pi/2, duration: duration ) + setShapeColor() + } + + +} + +extension YapAnimatedSwitch: AnimationPath { + + fileprivate func drawOnPath(_ group:CGRect) -> CGPath { + + let bezierPath = UIBezierPath() + + let radius = group.maxX/5 + let center = CGPoint(x:group.midX,y:group.midY ) + + let x1 = center.x + (radius ) * cos(-45.degreesToRadians) + let y1 = center.y + (radius ) * sin(-45.degreesToRadians) + + let x2 = center.x + (radius ) * cos(135.degreesToRadians) + let y2 = center.y + (radius ) * sin(135.degreesToRadians) + + bezierPath.move(to: CGPoint(x: x1, y: y1)) + bezierPath.addLine(to: CGPoint(x: x2, y: y2)) + + let x3 = center.x + (radius + radius * 0.5 ) * cos(-175.degreesToRadians) + let y3 = center.y + (radius + radius * 0.5 ) * sin(-175.degreesToRadians) + + bezierPath.move(to: CGPoint(x: x3, y: y3)) + bezierPath.addLine(to: CGPoint(x: x2, y: y2 )) + + return bezierPath.cgPath + + } + + fileprivate func drawOffPath(_ group:CGRect) -> CGPath { + + let bezierPath = UIBezierPath() + + let radius = group.maxX/5 + let center = CGPoint(x:group.midX,y:group.midY ) + + let x1 = center.x + (radius ) * cos(-45.degreesToRadians) + let y1 = center.y + (radius ) * sin(-45.degreesToRadians) + + + let x2 = center.x + (radius ) * cos(135.degreesToRadians) + let y2 = center.y + (radius ) * sin(135.degreesToRadians) + + + let x3 = center.x + (radius ) * cos(-135.degreesToRadians) + let y3 = center.y + (radius ) * sin(-135.degreesToRadians) + + let x4 = center.x + (radius ) * cos(45.degreesToRadians) + let y4 = center.y + (radius ) * sin(45.degreesToRadians) + + bezierPath.move(to: CGPoint(x: x4, y: y4)) + bezierPath.addLine(to: CGPoint(x: x3, y: y3)) + + bezierPath.move(to: CGPoint(x: x1, y: y1)) + bezierPath.addLine(to: CGPoint(x: x2, y: y2)) + + + return bezierPath.cgPath + + } +} + +/// `Design by` : tomatree +// https://dribbble.com/shots/2484722-Daily-Ui-Day-15-On-Off-Switch + +//MARK:- YapModeSwitch + +@IBDesignable public class YapModeSwitch: YapSwitch { + + private lazy var shapeLayer : CAShapeLayer = { + let shape = CAShapeLayer() + shape.strokeColor = UIColor.clear.cgColor + + return shape + }() + + private let duration:Double = 0.6 + + + public override func layoutSublayers(of layer: CALayer) { + + CATransaction.setAnimationDuration(duration) + CATransaction.begin() + super.layoutSublayers(of: layer) + CATransaction.commit() + + shapeLayer.fillColor = thumbTintColor?.cgColor + shapeLayer.frame = thumbLayer.bounds + thumbLayer.backgroundColor = UIColor.clear.cgColor + } + + override func controlDidLoad() { + super.controlDidLoad() + + isStretchEnable = false + thumbLayer.addSublayer(shapeLayer) + + DispatchQueue.main.async { + self.isOn ? (self.shapeLayer.path = self.drawOffPath(self.thumbLayer.bounds)) : (self.shapeLayer.path = self.drawOnPath(self.thumbLayer.bounds)) + } + + } + + override func stateDidChange() { + + super.stateDidChange() + isOn ? shapeLayer.animateShape(path:drawOffPath (thumbLayer.bounds), duration: duration - duration/1.5 ) : shapeLayer.animateShape(path: drawOnPath(thumbLayer.bounds), duration: duration - duration/1.5) + + } +} + +extension YapModeSwitch: AnimationPath { + fileprivate func drawOnPath(_ group: CGRect) -> CGPath { + let radius = group.maxX/2 + let center = CGPoint(x: group.midX, y: group.midY) + + let bezierPath = UIBezierPath() + bezierPath.addArc(withCenter: center, radius: radius, startAngle: 301.degreesToRadians, endAngle: 149.degreesToRadians, clockwise: true) + bezierPath.addArc(withCenter: center, radius: radius, startAngle: 149.degreesToRadians, endAngle: 301.degreesToRadians, clockwise: true) + bezierPath.close() + + return bezierPath.cgPath + } + + fileprivate func drawOffPath(_ group: CGRect) -> CGPath { + let radius: CGFloat = group.maxX/2 + + let centerA = CGPoint(x: group.midX, y: group.midY) + let offset = radius * 1.0 / 3.0 + let centerB = CGPoint(x: centerA.x - offset, y: centerA.y - offset) + + let bezierPath = UIBezierPath() + bezierPath.addArc(withCenter: centerA, radius: radius, startAngle: 301.degreesToRadians, endAngle: 149.degreesToRadians, clockwise: true) + bezierPath.addArc(withCenter: centerB, radius: radius, startAngle: 121.degreesToRadians, endAngle: 329.degreesToRadians, clockwise: false) + bezierPath.close() + + return bezierPath.cgPath + } +} + + +@IBDesignable public class YapDarkAndLightModeSwitch : YapSwitch { + + public let duration: Double = 0.6 + + private lazy var shapeLayer : CAShapeLayer = { + let shape = CAShapeLayer() + shape.strokeColor = UIColor.clear.cgColor + return shape + }() + + private lazy var maskLayer = CAShapeLayer() + + public override func layoutSublayers(of layer: CALayer) { + + CATransaction.setAnimationDuration(duration) + CATransaction.begin() + super.layoutSublayers(of: layer) + CATransaction.commit() + + maskLayer.frame = thumbLayer.bounds + + shapeLayer.frame = thumbLayer.bounds + shapeLayer.path = drawSunShape(thumbLayer.bounds) + shapeLayer.mask = maskLayer + thumbLayer.backgroundColor = thumbTintColor?.cgColor + + } + + override func controlDidLoad() { + super.controlDidLoad() + + isStretchEnable = false + thumbLayer.addSublayer(shapeLayer) + + DispatchQueue.main.async { + self.isOn ? (self.maskLayer.path = self.drawOnPath(self.thumbLayer.bounds)) : (self.maskLayer.path = self.drawOffPath(self.thumbLayer.bounds)) + } + thumbLayer.masksToBounds = true + } + + override func stateDidChange() { + + super.stateDidChange() + isOn ? maskLayer.animateShape(path:drawOnPath(thumbLayer.bounds), duration: duration ) : maskLayer.animateShape(path: drawOffPath(thumbLayer.bounds), duration: duration ) + + isOn ? thumbLayer.rotateAnimation(angal: 45.degreesToRadians, duration: duration) : thumbLayer.rotateAnimation(angal: 0, duration: duration) + + isOn ? animateFillColor(onTintColor) : animateFillColor(offTintColor) + + } + + private func animateFillColor(_ color: UIColor) { + CATransaction.begin() + CATransaction.setAnimationDuration(duration / 2) + self.shapeLayer.fillColor = color.cgColor + CATransaction.commit() + } + +} +extension YapDarkAndLightModeSwitch: AnimationPath { + + private func drawSunShape(_ group:CGRect) -> CGPath { + let bezierPath = UIBezierPath() + let radius = group.maxX/2 + let center = CGPoint(x: group.midX, y: group.midY) + bezierPath.addArc(withCenter:center, radius: radius, startAngle: -.pi/2, endAngle: 3 * .pi * 0.5 , clockwise: true) + return bezierPath.cgPath + } + + func setMask(isFullSize:Bool)-> CGPath { + + var radius = thumbLayer.bounds.maxY/2 + let center = CGPoint(x:thumbLayer.bounds.midX,y:thumbLayer.bounds.midY ) + + let x1 = center.x + radius * cos(180.degreesToRadians) + let y1 = center.y + radius * sin(180.degreesToRadians) + + let bezierPath = UIBezierPath() + + isFullSize ? (radius = 0) : (radius += 0 ) + + bezierPath.addArc(withCenter: CGPoint(x: x1, y: y1), radius: radius, startAngle: -90.degreesToRadians, endAngle: 90.degreesToRadians, clockwise: true) + + return bezierPath.cgPath + + } + + func drawOnPath(_ group: CGRect) -> CGPath { + return setMask(isFullSize: false) + } + + func drawOffPath(_ group: CGRect) -> CGPath { + return setMask(isFullSize: true) + } +} + +@IBDesignable public class YapFullStretchSwitch : YapSwitch { + override func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth + thumbRadiusPadding) + let width = (isTouchDown && isStretchEnable) ? bounds.width - 2 * (borderWidth + thumbRadiusPadding) : height + return CGSize(width: width, height: height) + } +} + +@IBDesignable public class YapHalfStretchSwitch : YapSwitch { + override func getThumbSize() -> CGSize { + let height = bounds.height - 2 * (borderWidth + thumbRadiusPadding) + let width = (isTouchDown && isStretchEnable) ? bounds.midX + bounds.midX/2 - 2 * (borderWidth + thumbRadiusPadding) : height + return CGSize(width: width, height: height) + } + + + public override func layoutSublayers(of layer: CALayer) { + + super.layoutSublayers(of: layer) + if shape == .square { + thumbLayer.cornerRadius = bounds.height * 0.1 + thumbLayer.shadowOffset = .zero + } + } +} + + diff --git a/SwitchesDemo/Application/AppDelegate.swift b/SwitchesDemo/Application/AppDelegate.swift new file mode 100644 index 0000000..7f71d30 --- /dev/null +++ b/SwitchesDemo/Application/AppDelegate.swift @@ -0,0 +1,37 @@ +// +// AppDelegate.swift +// testi +// +// Created by Jawad Ali on 11/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/SwitchesDemo/Application/SceneDelegate.swift b/SwitchesDemo/Application/SceneDelegate.swift new file mode 100644 index 0000000..c3a84a7 --- /dev/null +++ b/SwitchesDemo/Application/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// testi +// +// Created by Jawad Ali on 11/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/SwitchesDemo/Controllers/AnimatedSwitchesViewController.swift b/SwitchesDemo/Controllers/AnimatedSwitchesViewController.swift new file mode 100644 index 0000000..b250f60 --- /dev/null +++ b/SwitchesDemo/Controllers/AnimatedSwitchesViewController.swift @@ -0,0 +1,46 @@ +// +// AimatedSwitchedViewController.swift +// testi +// +// Created by Jawad Ali on 21/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class AnimatedSwitchesViewController: UIViewController { + + @IBOutlet weak var animatedStyleA: YapAnimatedSwitch! { + didSet { + animatedStyleA.thumbRadiusPadding = 6 + animatedStyleA.offThumbTintColor = #colorLiteral(red: 0.9540559649, green: 0.8972979188, blue: 0.8275271654, alpha: 1) + animatedStyleA.onThumbTintColor = #colorLiteral(red: 0.4935741425, green: 0.5258994699, blue: 0.9827957749, alpha: 1) + animatedStyleA.onTintColor = .white + animatedStyleA.offTintColor = .white + animatedStyleA.tintColor = .white + } + } + @IBOutlet weak var animatedStyleB: YapAnimatedSwitch! { + didSet { + animatedStyleB.thumbRadiusPadding = 6 + animatedStyleB.thumbTintColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) + animatedStyleB.animationWidth = 5 + animatedStyleB.onTintColor = #colorLiteral(red: 0.2841374278, green: 0.651584208, blue: 0.2687274218, alpha: 1) + animatedStyleB.isOn = true + animatedStyleB.offTintColor = #colorLiteral(red: 0.1686089635, green: 0.1686392426, blue: 0.1686022878, alpha: 1) + animatedStyleB.onAnimationColor = #colorLiteral(red: 0.2841374278, green: 0.651584208, blue: 0.2687274218, alpha: 1) + animatedStyleB.offAnimationColor = #colorLiteral(red: 0.1686089635, green: 0.1686392426, blue: 0.1686022878, alpha: 1) + } + } + override func viewDidLoad() { + + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.4935741425, green: 0.5258994699, blue: 0.9827957749, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.cycles = 15 + title = "Animated Switches" + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + +} diff --git a/SwitchesDemo/Controllers/CollectionViewCell/CollectionViewCell.swift b/SwitchesDemo/Controllers/CollectionViewCell/CollectionViewCell.swift new file mode 100644 index 0000000..5009074 --- /dev/null +++ b/SwitchesDemo/Controllers/CollectionViewCell/CollectionViewCell.swift @@ -0,0 +1,97 @@ +// +// CollectionViewCell.swift +// testi +// +// Created by Jawad Ali on 27/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class CollectionViewCell: UICollectionViewCell { + + private var switchv : BaseControl! { + didSet{ + switchv.translatesAutoresizingMaskIntoConstraints = false + } + } + + //MARK: binding with controller to perform segue + + var performSgue : ((_ segue:String)-> Void)? + + @IBOutlet weak var displaySwitch: UIView! { + didSet { + displaySwitch.layer.shadowOffset = .zero + displaySwitch.layer.shadowOpacity = 0.15 + displaySwitch.layer.shadowRadius = 7 + displaySwitch.layer.cornerRadius = 10 + } + } + + @IBOutlet weak var collectionName: UILabel! + @IBOutlet weak var viewAllButton: UIButton! + @IBOutlet weak var holdingView: UIView! { + didSet { + holdingView.layer.shadowOffset = .zero + holdingView.layer.shadowOpacity = 0.15 + holdingView.layer.shadowRadius = 7 + holdingView.layer.cornerRadius = 10 + } + } + + private var type : SwitchType! + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func layoutSubviews() { + super.layoutSubviews() + viewAllButton.layer.cornerRadius = viewAllButton.bounds.midY + } + + @IBAction func viewAllTapped(_ sender: UIButton) { + + performSgue?(type.rawValue) + + } + + + func config(type: SwitchType) { + self.type = type + collectionName.text = type.rawValue + + switchv = type.coverSwitch + displaySwitch.addSubview(switchv) + + if type == SwitchType.loading { + (self.switchv as? SDSwitch)?.loadingStarted = { + DispatchQueue.main.asyncAfter(deadline: .now() + 3) { + + (self.switchv as? SDSwitch)?.loadingCompleted(isSuccessFull: true) + } + } + + } + + switchv.topAnchor.constraint(equalTo: displaySwitch.topAnchor).isActive = true + switchv.bottomAnchor.constraint(equalTo: displaySwitch.bottomAnchor).isActive = true + switchv.leadingAnchor.constraint(equalTo: displaySwitch.leadingAnchor).isActive = true + switchv.trailingAnchor.constraint(equalTo: displaySwitch.trailingAnchor).isActive = true + + switchv.addTarget(self, action: #selector(changedSwitchVal), for: .valueChanged) + + } + + @objc func changedSwitchVal(_ sender: BaseControl) { + print(sender.isOn) + + } + + override func prepareForReuse() { + super.prepareForReuse() + + switchv.removeFromSuperview() + } +} diff --git a/SwitchesDemo/Controllers/GradientSwitchesViewController.swift b/SwitchesDemo/Controllers/GradientSwitchesViewController.swift new file mode 100644 index 0000000..79fe636 --- /dev/null +++ b/SwitchesDemo/Controllers/GradientSwitchesViewController.swift @@ -0,0 +1,85 @@ +// +// GradientSwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 23/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class GradientSwitchesViewController: UIViewController { + + private lazy var gradientLayerVertical = CAGradientLayer() + private lazy var gradientLayerHorizantal = CAGradientLayer() + + @IBOutlet weak var gradientSwitchHorizantal: YapGradientSwitch! { + didSet { + gradientSwitchHorizantal.gradientPosition = .horizatal + gradientSwitchHorizantal.onColors = [#colorLiteral(red: 0.2394029498, green: 0.8576775193, blue: 0.6665194631, alpha: 1),#colorLiteral(red: 0.04418379813, green: 0.5335158706, blue: 0.5292400718, alpha: 1)] + gradientSwitchHorizantal.offColors = [#colorLiteral(red: 0.1861540377, green: 0.2199867666, blue: 0.2542595267, alpha: 1),#colorLiteral(red: 0.1861540377, green: 0.2199867666, blue: 0.2542595267, alpha: 1)] + + gradientSwitchHorizantal.onText = "ON" + gradientSwitchHorizantal.offText = "OFF" + } + } + @IBOutlet weak var gradientSwitchVertical: YapGradientSwitch!{ + didSet { + gradientSwitchVertical.borderWidth = 2 + gradientSwitchVertical.gradientPosition = .vertical + gradientSwitchVertical.onColors = [#colorLiteral(red: 0.722638309, green: 0.1586903036, blue: 0.2223222256, alpha: 1),#colorLiteral(red: 0.1921568662, green: 0.007843137719, blue: 0.09019608051, alpha: 1)] + gradientSwitchVertical.offColors = [#colorLiteral(red: 0.1042157337, green: 0.4639918208, blue: 0.2866171598, alpha: 1),#colorLiteral(red: 0.1294117719, green: 0.1414276541, blue: 0.06666667014, alpha: 1)] + + gradientSwitchVertical.onText = "START" + gradientSwitchVertical.offText = "STOP" + } + } + override func viewDidLoad() { + super.viewDidLoad() + + gradientSwitchVertical.superview?.layer.insertSublayer(gradientLayerVertical, at: 0) + gradientLayerVertical.colors = gradientSwitchVertical.offColors.map{$0.withAlphaComponent(0.7).cgColor} + + gradientSwitchHorizantal.superview?.layer.insertSublayer(gradientLayerHorizantal, at: 0) + gradientLayerHorizantal.colors = gradientSwitchHorizantal.offColors.map{$0.withAlphaComponent(0.3).cgColor} + + gradientSwitchVertical.addTarget(self, action: #selector(switchVerticalToggle(_:)), for: .valueChanged) + gradientSwitchHorizantal.addTarget(self, action: #selector(switchHorizantalToggle(_:)), for: .valueChanged) + + title = "Gradient Switches" + + ( navigationController?.navigationBar as? JDNavigationBar)?.heightShape = 80 + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.1861540377, green: 0.2199867666, blue: 0.2542595267, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .folded + + + + + // Do any additional setup after loading the view. + } + + + + override func viewDidLayoutSubviews() { + gradientLayerVertical.frame = gradientSwitchVertical.superview?.bounds ?? .zero + gradientLayerHorizantal.frame = gradientSwitchHorizantal.superview?.bounds ?? .zero + } + + @objc func switchVerticalToggle(_ sender: YapDarkAndLightModeSwitch) { + + sender.isOn ? gradientLayerVertical.animateGradientColors(from: gradientSwitchVertical.offColors.map{$0.withAlphaComponent(0.7).cgColor}, to: gradientSwitchVertical.onColors.map{$0.withAlphaComponent(0.7).cgColor}, duration: 0.5) : gradientLayerVertical.animateGradientColors(from: gradientSwitchVertical.onColors.map{$0.withAlphaComponent(0.7).cgColor}, to: gradientSwitchVertical.offColors.map{$0.withAlphaComponent(0.7).cgColor}, duration: 0.5) + + + + } + @objc func switchHorizantalToggle(_ sender: YapDarkAndLightModeSwitch) { + + sender.isOn ? gradientLayerHorizantal.animateGradientColors(from: gradientSwitchHorizantal.offColors.map{$0.withAlphaComponent(0.3).cgColor}, to: gradientSwitchHorizantal.onColors.map{$0.withAlphaComponent(0.3).cgColor}, duration: 0.5) : gradientLayerHorizantal.animateGradientColors(from: gradientSwitchHorizantal.onColors.map{$0.withAlphaComponent(0.3).cgColor}, to: gradientSwitchHorizantal.offColors.map{$0.withAlphaComponent(0.3).cgColor}, duration: 0.5) + + + + } + + + +} diff --git a/SwitchesDemo/Controllers/JellySwitchesViewController.swift b/SwitchesDemo/Controllers/JellySwitchesViewController.swift new file mode 100644 index 0000000..7c69438 --- /dev/null +++ b/SwitchesDemo/Controllers/JellySwitchesViewController.swift @@ -0,0 +1,46 @@ +// +// JellySwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 24/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class JellySwitchesViewController: UIViewController { + + @IBOutlet weak var fullStretchSwitch: YapFullStretchSwitch! { + didSet { + fullStretchSwitch.onThumbImage = UIImage(named: "check") + fullStretchSwitch.thumbRadiusPadding = 0 + fullStretchSwitch.borderColor = #colorLiteral(red: 0.7999292612, green: 0.8000453115, blue: 0.7999040484, alpha: 1) + fullStretchSwitch.borderWidth = 3 + fullStretchSwitch.onTintColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1) + fullStretchSwitch.offTintColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1) + } + } + @IBOutlet weak var halfStretchSwitch: YapHalfStretchSwitch! { + didSet { + + halfStretchSwitch.shape = .square + halfStretchSwitch.thumbRadiusPadding = 4 + halfStretchSwitch.borderColor = #colorLiteral(red: 0.7999292612, green: 0.8000453115, blue: 0.7999040484, alpha: 1) + halfStretchSwitch.borderWidth = 2 + halfStretchSwitch.onTintColor = #colorLiteral(red: 0.999904573, green: 1, blue: 0.9998808503, alpha: 1) + halfStretchSwitch.offTintColor = #colorLiteral(red: 0.345902741, green: 0.7542000413, blue: 0.4488890171, alpha: 1) + + } + } + @IBOutlet weak var jellySwitch: TKLiquidSwitch! + + override func viewDidLoad() { + super.viewDidLoad() + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.3236978054, green: 0.1063579395, blue: 0.574860394, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .zigzag + ( navigationController?.navigationBar as? JDNavigationBar)?.heightShape = 30 + ( navigationController?.navigationBar as? JDNavigationBar)?.cycles = 5 + + title = "Jelly Switch" + } +} diff --git a/SwitchesDemo/Controllers/LoadingSwitchesViewController.swift b/SwitchesDemo/Controllers/LoadingSwitchesViewController.swift new file mode 100644 index 0000000..1e8a9fa --- /dev/null +++ b/SwitchesDemo/Controllers/LoadingSwitchesViewController.swift @@ -0,0 +1,65 @@ +// +// LoadingSwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 23/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class LoadingSwitchesViewController: UIViewController { + @IBOutlet weak var loadingSwitch: SDSwitch! { + didSet{ + loadingSwitch.isLoadingEnabled = true + loadingSwitch.thumbRadiusPadding = 10 + } + } + var count = 0 + @IBOutlet weak var followedMiddleSwitch: SDSwitch! { + didSet { + followedMiddleSwitch.offBorderColor = #colorLiteral(red: 0.3974077106, green: 0.6517546177, blue: 0.9074617624, alpha: 1) + followedMiddleSwitch.offThumbTintColor = #colorLiteral(red: 0.3974077106, green: 0.6517546177, blue: 0.9074617624, alpha: 1) + followedMiddleSwitch.borderWidth = 4 + followedMiddleSwitch.thumbRadiusPadding = 8 + followedMiddleSwitch.onThumbTintColor = #colorLiteral(red: 0.6347479224, green: 0.50891155, blue: 0.9531157613, alpha: 1) + followedMiddleSwitch.onBorderColor = #colorLiteral(red: 0.6347479224, green: 0.50891155, blue: 0.9531157613, alpha: 1) + followedMiddleSwitch.onTintColor = .white + followedMiddleSwitch.offTintColor = .white + } + } + @IBOutlet weak var followedLastSwitch: YapFullTextSwitch! { + didSet{ + followedLastSwitch.onTextColor = #colorLiteral(red: 0.2766842842, green: 0.8682026267, blue: 0.9832950234, alpha: 1) + followedLastSwitch.offTextColor = #colorLiteral(red: 0.7480503321, green: 0.7532240748, blue: 0.7486134171, alpha: 1) + followedLastSwitch.onText = "ON" + followedLastSwitch.offText = "OFF" + followedLastSwitch.onBorderColor = #colorLiteral(red: 0.2766842842, green: 0.8682026267, blue: 0.9832950234, alpha: 1) + followedLastSwitch.offBorderColor = #colorLiteral(red: 0.9433093667, green: 0.9533157945, blue: 0.9529805779, alpha: 1) + followedLastSwitch.onTintColor = #colorLiteral(red: 0.3614792228, green: 0.9322348237, blue: 0.9953452945, alpha: 1) + followedLastSwitch.offTintColor = #colorLiteral(red: 0.948936522, green: 0.9490728974, blue: 0.9489069581, alpha: 1) + followedLastSwitch.borderWidth = 5 + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Loading Switches" + + loadingSwitch.loadingStarted = { + DispatchQueue.main.asyncAfter(deadline: .now() + 4) { + (self.count % 2 == 0) ? self.loadingSwitch.loadingCompleted(isSuccessFull: true) : self.loadingSwitch.loadingCompleted(isSuccessFull: false) + self.count += 1 + } + } + + + + + ( navigationController?.navigationBar as? JDNavigationBar)?.cycles = 7 + } + + + +} diff --git a/SwitchesDemo/Controllers/ModeBSwitchesViewController.swift b/SwitchesDemo/Controllers/ModeBSwitchesViewController.swift new file mode 100644 index 0000000..a141a85 --- /dev/null +++ b/SwitchesDemo/Controllers/ModeBSwitchesViewController.swift @@ -0,0 +1,52 @@ +// +// ModeBSwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 22/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class ModeBSwitchesViewController: UIViewController { + + @IBOutlet weak var modeSwitchStyleA: YapModeSwitch! { + didSet { + modeSwitchStyleA.thumbRadiusPadding = 8 + modeSwitchStyleA.thumbTintColor = #colorLiteral(red: 0.9683158994, green: 0.501380682, blue: 0.4961987734, alpha: 1) + modeSwitchStyleA.offTintColor = .white + modeSwitchStyleA.onTintColor = #colorLiteral(red: 0.6057969332, green: 0.6360527277, blue: 0.9815277457, alpha: 1) + } + } + @IBOutlet weak var modeSwitchStyleB: YapModeSwitch! { + didSet { + modeSwitchStyleB.thumbRadiusPadding = 8 + modeSwitchStyleB.thumbTintColor = .white + modeSwitchStyleB.offTintColor = #colorLiteral(red: 0.2786044478, green: 0.5705410242, blue: 0.9243882298, alpha: 1) + modeSwitchStyleB.onTintColor = #colorLiteral(red: 0.3037858903, green: 0.1899323463, blue: 0.6803773642, alpha: 1) + } + } + override func viewDidLoad() { + + super.viewDidLoad() + modeSwitchStyleB.addTarget(self, action: #selector(switchBToggle(_:)), for: .valueChanged) + + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.9683158994, green: 0.501380682, blue: 0.4961987734, alpha: 1)) + + ( navigationController?.navigationBar as? JDNavigationBar)?.heightShape = 90 + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .folded + title = "Dark Light A Mode" + } + + + @objc func switchBToggle(_ sender: YapDarkAndLightModeSwitch) { + + let color = sender.isOn ? #colorLiteral(red: 0.5881829262, green: 0.4660730958, blue: 0.9921956658, alpha: 1) : .white + + UIView.animate(withDuration: sender.duration) { + self.modeSwitchStyleB.superview?.backgroundColor = color + } + + } + +} diff --git a/SwitchesDemo/Controllers/ModeSwitchesViewController.swift b/SwitchesDemo/Controllers/ModeSwitchesViewController.swift new file mode 100644 index 0000000..8ab6fed --- /dev/null +++ b/SwitchesDemo/Controllers/ModeSwitchesViewController.swift @@ -0,0 +1,56 @@ +// +// ModeSwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 22/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class ModeSwitchesViewController: UIViewController { + + @IBOutlet weak var modeSwitchStyleA: YapDarkAndLightModeSwitch! { + didSet { + modeSwitchStyleA.thumbRadiusPadding = 8 + modeSwitchStyleA.thumbTintColor = #colorLiteral(red: 0.9683158994, green: 0.501380682, blue: 0.4961987734, alpha: 1) + modeSwitchStyleA.offTintColor = .white + modeSwitchStyleA.onTintColor = #colorLiteral(red: 0.6057969332, green: 0.6360527277, blue: 0.9815277457, alpha: 1) + } + } + @IBOutlet weak var modeSwitchStyleB: YapDarkAndLightModeSwitch! { + didSet { + modeSwitchStyleB.thumbRadiusPadding = 8 + modeSwitchStyleB.thumbTintColor = .white + modeSwitchStyleB.offTintColor = #colorLiteral(red: 0.2786044478, green: 0.5705410242, blue: 0.9243882298, alpha: 1) + modeSwitchStyleB.onTintColor = #colorLiteral(red: 0.3037858903, green: 0.1899323463, blue: 0.6803773642, alpha: 1) + } + } + override func viewDidLoad() { + + super.viewDidLoad() + modeSwitchStyleB.addTarget(self, action: #selector(switchBToggle(_:)), for: .valueChanged) + + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.3037858903, green: 0.1899323463, blue: 0.6803773642, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.cycles = 5 + ( navigationController?.navigationBar as? JDNavigationBar)?.heightShape = 12 + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .square + + + + title = "Dark Light B Mode" + } + + + @objc func switchBToggle(_ sender: YapDarkAndLightModeSwitch) { + + let color = sender.isOn ? #colorLiteral(red: 0.5881829262, green: 0.4660730958, blue: 0.9921956658, alpha: 1) : .white + + UIView.animate(withDuration: sender.duration) { + self.modeSwitchStyleB.superview?.backgroundColor = color + } + + } + + +} diff --git a/SwitchesDemo/Controllers/RandomViewController.swift b/SwitchesDemo/Controllers/RandomViewController.swift new file mode 100644 index 0000000..e2cbefc --- /dev/null +++ b/SwitchesDemo/Controllers/RandomViewController.swift @@ -0,0 +1,113 @@ +// +// RandomViewController.swift +// testi +// +// Created by Jawad Ali on 25/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches + class RandomViewController: UIViewController { + @IBOutlet weak var randomA: YapSwitch! { + didSet { + randomA.onText = "ON" + randomA.offText = "OFF" + randomA.onTextColor = .white + randomA.offTextColor = #colorLiteral(red: 0.2125092149, green: 0.2516930103, blue: 0.2772026062, alpha: 1) + randomA.borderColor = #colorLiteral(red: 0.2125092149, green: 0.2516930103, blue: 0.2772026062, alpha: 1) + randomA.onTintColor = #colorLiteral(red: 0.2125092149, green: 0.2516930103, blue: 0.2772026062, alpha: 1) + + randomA.offTextColor = #colorLiteral(red: 0.2125092149, green: 0.2516930103, blue: 0.2772026062, alpha: 1) + randomA.offTintColor = .white + randomA.offThumbTintColor = #colorLiteral(red: 0.2125092149, green: 0.2516930103, blue: 0.2772026062, alpha: 1) + randomA.borderWidth = 2 + } + } + @IBOutlet weak var randomB: YapSwitchSlim! { + didSet { + randomB.onThumbTintColor = #colorLiteral(red: 0.0864540413, green: 0.5291488171, blue: 0.5380262733, alpha: 1) + randomB.onTintColor = #colorLiteral(red: 0.4112847149, green: 0.7173692584, blue: 0.7089804411, alpha: 1) + randomB.offTintColor = #colorLiteral(red: 0.5372059941, green: 0.5372863412, blue: 0.5371884108, alpha: 1) + randomB.slimTrack = 10 + randomB.thumbRadiusPadding = 0 + } + } + @IBOutlet weak var randomC: YapSwitch! { + didSet { + randomC.onThumbImage = UIImage(named: "check") + randomC.onTintColor = .purple + randomC.offTintColor = #colorLiteral(red: 0.8552142978, green: 0.8781172037, blue: 0.9388162494, alpha: 1) + } + } + + @IBOutlet weak var randomD: YapSwitch! { + didSet { + randomD.onThumbTintColor = #colorLiteral(red: 0.1970949173, green: 0.799264133, blue: 0.8020008206, alpha: 1) + randomD.onThumbImage = #imageLiteral(resourceName: "check").maskWithColor(color: .white) + randomD.offThumbImage = #imageLiteral(resourceName: "close").maskWithColor(color: #colorLiteral(red: 0.170032382, green: 0.2437844872, blue: 0.3120466471, alpha: 1)) + randomD.offThumbTintColor = #colorLiteral(red: 0.8940391541, green: 0.8941679597, blue: 0.8940110803, alpha: 1) + randomD.onTintColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) + randomD.offTintColor = #colorLiteral(red: 0.170032382, green: 0.2437844872, blue: 0.3120466471, alpha: 1) + } + } + @IBOutlet weak var randomE: YapSwitch! { + didSet { + randomE.onTextColor = #colorLiteral(red: 0.2311643958, green: 0.8008779883, blue: 0.6899323463, alpha: 1) + randomE.offTextColor = #colorLiteral(red: 0.9092465753, green: 0.8114833048, blue: 0.810734161, alpha: 1) + randomE.onThumbTintColor = #colorLiteral(red: 0.127592504, green: 0.7816838622, blue: 0.6617996693, alpha: 1) + randomE.offThumbTintColor = #colorLiteral(red: 0.9092465753, green: 0.8114833048, blue: 0.810734161, alpha: 1) + randomE.onText = "ON" + randomE.offText = "OFF" + randomE.onTintColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) + randomE.offTintColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) + } + } + + + @IBOutlet weak var randomG: YapSwitch! { + didSet { + randomG.thumbTintColor = .yellow + randomG.onText = "OFF" + randomG.offText = "ON" + + randomG.onTintColor = .black + randomG.borderWidth = 4 + randomG.textColor = .cyan + randomG.offTintColor = .black + randomG.onTextColor = .white + } + } + @IBOutlet weak var randomH: YapSwitch! { + didSet { + randomH.onImage = UIImage(named: "icon_check_primary_dark")?.maskWithColor(color: .black) + randomH.offImage = UIImage(named: "icon_close_dark_purple")?.maskWithColor(color: .red) + randomH.shape = .square + randomH.onTintColor = .yellow + randomH.borderWidth = 5 + randomH.thumbCornerRadius = 0 + randomH.offTintColor = .green + } + } + @IBOutlet weak var randomI: YapSwitch! { + didSet { + randomI.onThumbImage = UIImage(named: "check") + randomI.offThumbImage = UIImage(named: "close") + randomI.shape = .square + randomI.onTintColor = .purple + randomI.borderWidth = 2 + randomI.thumbCornerRadius = 0 + randomI.offTintColor = .red + } + } + + + override func viewDidLoad() { + super.viewDidLoad() + title = "Random Switches" + // Do any additional setup after loading the view. + } + + + +} diff --git a/SwitchesDemo/Controllers/SmileyViewController.swift b/SwitchesDemo/Controllers/SmileyViewController.swift new file mode 100644 index 0000000..3c753b0 --- /dev/null +++ b/SwitchesDemo/Controllers/SmileyViewController.swift @@ -0,0 +1,49 @@ +// +// SmileyViewController.swift +// testi +// +// Created by Jawad Ali on 25/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class SmileyViewController: UIViewController { + + @IBOutlet weak var randomA: YapSwitch! { + didSet { + randomA.thumbImage = UIImage(named: "thumb12") + randomA.onTintColor = #colorLiteral(red: 0.8426451087, green: 0.3289524913, blue: 0.2659203112, alpha: 1) + randomA.offTintColor = #colorLiteral(red: 0.7276904583, green: 0.7375378013, blue: 0.7416281104, alpha: 1) + randomA.thumbTintColor = .clear + randomA.onImage = #imageLiteral(resourceName: "check").maskWithColor(color: .white) + randomA.offImage = UIImage(named: "cross7") + randomA.shape = .square + randomA.frame = CGRect(x: 200, y: 650, width: 65, height: 36) + randomA.borderWidth = 2 + } + } + @IBOutlet weak var randomB: YapSwitch! { + didSet { + randomB.thumbImage = UIImage(named: "thumb1") + randomB.onTintColor = #colorLiteral(red: 0.5955576897, green: 0.7103857398, blue: 0.2235306501, alpha: 1) + randomB.layer.shadowOpacity = 0.6 + randomB.layer.shadowOffset = .zero + randomB.layer.shadowRadius = 5 + randomB.layer.shadowColor = UIColor.black.cgColor + randomB.onImage = #imageLiteral(resourceName: "check").maskWithColor(color: .white) + randomB.offImage = UIImage(named: "off2") + randomB.offTintColor = #colorLiteral(red: 0.7764018178, green: 0.7765145898, blue: 0.7763771415, alpha: 1) + randomB.borderWidth = 1 + } + } + override func viewDidLoad() { + super.viewDidLoad() + title = "Smiley Switch" + // Do any additional setup after loading the view. + } + + + + +} diff --git a/SwitchesDemo/Controllers/SwiftyViewController.swift b/SwitchesDemo/Controllers/SwiftyViewController.swift new file mode 100644 index 0000000..24babd0 --- /dev/null +++ b/SwitchesDemo/Controllers/SwiftyViewController.swift @@ -0,0 +1,45 @@ +// +// SwiftyViewController.swift +// testi +// +// Created by Jawad Ali on 24/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class SwiftyViewController: UIViewController { + + @IBOutlet weak var swiftyA: Switcher! { + didSet { + swiftyA.superview?.layer.shadowOffset = .zero + swiftyA.superview?.layer.shadowOpacity = 0.3 + swiftyA.superview?.layer.shadowRadius = 5 + } + } + @IBOutlet weak var swiftyB: Switcher! { + didSet { + swiftyB.superview?.layer.shadowOffset = .zero + swiftyB.superview?.layer.shadowOpacity = 0.3 + swiftyB.superview?.layer.shadowRadius = 5 + } + } + @IBOutlet weak var swiftyC: JDSwitch! { + didSet { + swiftyC.thumbRadiusPadding = 8 + } + } + override func viewDidLoad() { + + title = "Stretchy Switch" + super.viewDidLoad() + } + + override func viewWillAppear(_ animated: Bool) { + + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.1861540377, green: 0.2199867666, blue: 0.2542595267, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .wave + } + + +} diff --git a/SwitchesDemo/Controllers/ThumbImageSwitchesViewController.swift b/SwitchesDemo/Controllers/ThumbImageSwitchesViewController.swift new file mode 100644 index 0000000..b0500f8 --- /dev/null +++ b/SwitchesDemo/Controllers/ThumbImageSwitchesViewController.swift @@ -0,0 +1,85 @@ +// +// ThumbImageSwitchesViewController.swift +// testi +// +// Created by Jawad Ali on 24/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class ThumbImageSwitchesViewController: UIViewController { + + @IBOutlet weak var thumbImageSwitchD: YapSwitch! { + didSet { + thumbImageSwitchD.onThumbImage = UIImage(named: "go1") + thumbImageSwitchD.offThumbImage = UIImage(named: "go2") + thumbImageSwitchD.onTintColor = #colorLiteral(red: 0.6870710254, green: 0.2686487734, blue: 0.2165684998, alpha: 1) + thumbImageSwitchD.offTintColor = #colorLiteral(red: 0.3156668544, green: 0.4091051519, blue: 0.481534183, alpha: 1) + thumbImageSwitchD.thumbRadiusPadding = 8 + thumbImageSwitchD.isStretchEnable = false + } + } + @IBOutlet weak var thumbImageSwitchC: YapSwitch! { + didSet { + thumbImageSwitchC.onThumbImage = #imageLiteral(resourceName: "right") + thumbImageSwitchC.offThumbImage = #imageLiteral(resourceName: "left") + thumbImageSwitchC.onTintColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.onText = "OFF" + thumbImageSwitchC.offText = "ON" + thumbImageSwitchC.offTextColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.offBorderColor = #colorLiteral(red: 0.8901180029, green: 0.8902462125, blue: 0.8900898695, alpha: 1) + thumbImageSwitchC.onBorderColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.thumbRadiusPadding = 8 + thumbImageSwitchC.borderWidth = 3 + thumbImageSwitchC.offTintColor = #colorLiteral(red: 0.9568627451, green: 0.9587000478, blue: 0.9568627451, alpha: 1) + } + } + @IBOutlet weak var thumbImageSwitchB: YapSwitch! { + didSet { + thumbImageSwitchB.onTextColor = #colorLiteral(red: 0.3056051731, green: 0.4627509713, blue: 0.01093915664, alpha: 1) + thumbImageSwitchB.offTextColor = #colorLiteral(red: 0.5544068813, green: 0.08276418597, blue: 0.07942076772, alpha: 1) + thumbImageSwitchB.thumbImage = UIImage(named: "thumb7") + thumbImageSwitchB.thumbTintColor = .red + thumbImageSwitchB.onText = "ON" + thumbImageSwitchB.offText = "OFF" + thumbImageSwitchB.thumbRadiusPadding = 1 + thumbImageSwitchB.thumbTintColor = .clear + thumbImageSwitchB.borderWidth = 3 + thumbImageSwitchB.borderColor = #colorLiteral(red: 0.729346931, green: 0.7294533849, blue: 0.729323566, alpha: 1) + thumbImageSwitchB.onTintColor = #colorLiteral(red: 0.6511958838, green: 0.8345313668, blue: 0.2781367004, alpha: 1) + thumbImageSwitchB.offTintColor = #colorLiteral(red: 0.9100278616, green: 0.2768563628, blue: 0.2796021998, alpha: 1) + } + } + @IBOutlet weak var thumbImageSwitchA: YapSwitchSlim! { + didSet { + thumbImageSwitchA.thumbImage = UIImage(named: "thumb4") + thumbImageSwitchA.onText = "NO" + thumbImageSwitchA.offText = "YES" + thumbImageSwitchA.shape = .square + thumbImageSwitchA.thumbRadiusPadding = 6 + thumbImageSwitchA.slimTrack = 5 + thumbImageSwitchA.thumbTintColor = .clear + thumbImageSwitchA.borderWidth = 3 + thumbImageSwitchA.borderColor = #colorLiteral(red: 0.752874434, green: 0.7529839873, blue: 0.7528504729, alpha: 1) + thumbImageSwitchA.onTintColor = #colorLiteral(red: 0.8561109304, green: 0.2607076168, blue: 0.5694340467, alpha: 1) + thumbImageSwitchA.offTintColor = #colorLiteral(red: 0.09238574654, green: 0.4540643692, blue: 0.61872226, alpha: 1) + thumbImageSwitchA.superview?.layer.shadowOffset = .zero + thumbImageSwitchA.superview?.layer.shadowOpacity = 0.3 + thumbImageSwitchA.superview?.layer.shadowRadius = 5 + } + } + override func viewDidLoad() { + +// thumbImageSwitchA.valueChange = { [unowned self] isSuccess in +// isSuccess ? (self.thumbImageSwitchA.superview?.superview?.backgroundColor = self.thumbImageSwitchA.onTintColor.withAlphaComponent(0.5)) : (self.thumbImageSwitchA.superview?.superview?.backgroundColor = self.thumbImageSwitchA.offTintColor.withAlphaComponent(0.5)) +// } + title = "Thumb Image Switch" + + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + +} diff --git a/SwitchesDemo/Controllers/ViewController.swift b/SwitchesDemo/Controllers/ViewController.swift new file mode 100644 index 0000000..bc3dcec --- /dev/null +++ b/SwitchesDemo/Controllers/ViewController.swift @@ -0,0 +1,67 @@ +// +// ViewController.swift +// testi +// +// Created by Jawad Ali on 11/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +class ViewController: UIViewController { + @IBOutlet weak var collectionView: UICollectionView! + + override func viewDidLoad() { + super.viewDidLoad() + title = "JD Switches" + } + + override func viewWillAppear(_ animated: Bool) { + + ( navigationController?.navigationBar as? JDNavigationBar)?.changeColor(#colorLiteral(red: 0.2862745098, green: 0.7019607843, blue: 0.9411764706, alpha: 1)) + ( navigationController?.navigationBar as? JDNavigationBar)?.shape = .wave + ( navigationController?.navigationBar as? JDNavigationBar)?.heightShape = 40 + ( navigationController?.navigationBar as? JDNavigationBar)?.cycles = 3 + } +} + +//MARK:- CollectionView Delegate + +extension UIViewController : UICollectionViewDelegate , UICollectionViewDataSource { + public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return SwitchType.allCases.count + } + + public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + + if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as? CollectionViewCell { + + let getCase = SwitchType.allCases[indexPath.row] + cell.config(type: getCase) + + cell.performSgue = {[unowned self] identifier in + self.performSegue(withIdentifier: identifier, sender: nil) + } + return cell + } + + return UICollectionViewCell() + } +} + +//MARK:- Flow layout delegate +extension UIViewController: UICollectionViewDelegateFlowLayout { + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let width = (view.bounds.width) / 2 + let height = width * 1.15 + return CGSize(width: width, height: height) + } + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return 0 + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + return 0 + } +} diff --git a/SwitchesDemo/Model/SwitchType.swift b/SwitchesDemo/Model/SwitchType.swift new file mode 100644 index 0000000..164a2c6 --- /dev/null +++ b/SwitchesDemo/Model/SwitchType.swift @@ -0,0 +1,102 @@ +// +// SwitchType.swift +// testi +// +// Created by Jawad Ali on 29/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import UIKit +import Switches +enum SwitchType:String, CaseIterable { + + case transition = "Transition Switches" + case loading = "Loading Switches" + case jelly = "Jelly Switches" + case animated = "Animated Switches" + case modeA = "Mode Switches" + case modeB = "Cool Switches" + case gradient = "Gradient Switches" + case thumbImage = "Cover Switches" + case smiley = "Smiley Switches" + case ranndom = "Random Switches" +} +extension SwitchType { + + var coverSwitch: BaseControl { + switch self { + case .transition: + let display = Switcher() + display.superview?.layer.shadowOffset = .zero + display.superview?.layer.shadowOpacity = 0.3 + display.superview?.layer.shadowRadius = 5 + return display + case .loading: + let display = SDSwitch() + display.isLoadingEnabled = true + display.thumbRadiusPadding = 5 + return display + case .jelly: + return TKLiquidSwitch() + case .animated: + let animatedStyleA = YapAnimatedSwitch() + animatedStyleA.thumbRadiusPadding = 6 + animatedStyleA.offThumbTintColor = #colorLiteral(red: 0.9540559649, green: 0.8972979188, blue: 0.8275271654, alpha: 1) + animatedStyleA.onThumbTintColor = #colorLiteral(red: 0.4935741425, green: 0.5258994699, blue: 0.9827957749, alpha: 1) + animatedStyleA.onTintColor = .white + animatedStyleA.offTintColor = .white + animatedStyleA.tintColor = .white + return animatedStyleA + case .modeA: + let modeSwitchStyleA = YapDarkAndLightModeSwitch() + modeSwitchStyleA.thumbRadiusPadding = 8 + modeSwitchStyleA.thumbTintColor = #colorLiteral(red: 0.9683158994, green: 0.501380682, blue: 0.4961987734, alpha: 1) + modeSwitchStyleA.offTintColor = .white + modeSwitchStyleA.onTintColor = #colorLiteral(red: 0.6057969332, green: 0.6360527277, blue: 0.9815277457, alpha: 1) + return modeSwitchStyleA + case .modeB: + let modeSwitchStyleA = YapModeSwitch() + modeSwitchStyleA.thumbRadiusPadding = 8 + modeSwitchStyleA.thumbTintColor = #colorLiteral(red: 0.9683158994, green: 0.501380682, blue: 0.4961987734, alpha: 1) + modeSwitchStyleA.offTintColor = .white + modeSwitchStyleA.onTintColor = #colorLiteral(red: 0.6057969332, green: 0.6360527277, blue: 0.9815277457, alpha: 1) + return modeSwitchStyleA + case .gradient: + let gradientSwitchVertical = YapGradientSwitch() + gradientSwitchVertical.borderWidth = 2 + gradientSwitchVertical.gradientPosition = .vertical + gradientSwitchVertical.onColors = [#colorLiteral(red: 0.722638309, green: 0.1586903036, blue: 0.2223222256, alpha: 1),#colorLiteral(red: 0.1921568662, green: 0.007843137719, blue: 0.09019608051, alpha: 1)] + gradientSwitchVertical.offColors = [#colorLiteral(red: 0.1042157337, green: 0.4639918208, blue: 0.2866171598, alpha: 1),#colorLiteral(red: 0.1294117719, green: 0.1414276541, blue: 0.06666667014, alpha: 1)] + gradientSwitchVertical.onText = "START" + gradientSwitchVertical.offText = "STOP" + return gradientSwitchVertical + + case .smiley: + return TKSmileSwitch() + case .thumbImage: + let thumbImageSwitchC = YapSwitch() + thumbImageSwitchC.onThumbImage = #imageLiteral(resourceName: "right") + thumbImageSwitchC.offThumbImage = #imageLiteral(resourceName: "left") + thumbImageSwitchC.onTintColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.onText = "OFF" + thumbImageSwitchC.offText = "ON" + thumbImageSwitchC.offTextColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.offBorderColor = #colorLiteral(red: 0.8901180029, green: 0.8902462125, blue: 0.8900898695, alpha: 1) + thumbImageSwitchC.onBorderColor = #colorLiteral(red: 0.6210919023, green: 0.3142792583, blue: 0.6986252666, alpha: 1) + thumbImageSwitchC.thumbRadiusPadding = 8 + thumbImageSwitchC.borderWidth = 3 + thumbImageSwitchC.offTintColor = #colorLiteral(red: 0.9568627451, green: 0.9587000478, blue: 0.9568627451, alpha: 1) + return thumbImageSwitchC + case .ranndom: + let randomB = YapSwitchSlim() + + randomB.onThumbTintColor = #colorLiteral(red: 0.0864540413, green: 0.5291488171, blue: 0.5380262733, alpha: 1) + randomB.onTintColor = #colorLiteral(red: 0.4112847149, green: 0.7173692584, blue: 0.7089804411, alpha: 1) + randomB.offTintColor = #colorLiteral(red: 0.5372059941, green: 0.5372863412, blue: 0.5371884108, alpha: 1) + randomB.slimTrack = 10 + randomB.thumbRadiusPadding = 0 + return randomB + + } + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..99f7a0c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,128 @@ +{ + "images":[ + { + "idiom":"iphone", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"iphone", + "size":"20x20", + "scale":"3x", + "filename":"Icon-App-20x20@3x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"iphone", + "size":"29x29", + "scale":"3x", + "filename":"Icon-App-29x29@3x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"iphone", + "size":"40x40", + "scale":"3x", + "filename":"Icon-App-40x40@3x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"2x", + "filename":"Icon-App-60x60@2x.png" + }, + { + "idiom":"iphone", + "size":"60x60", + "scale":"3x", + "filename":"Icon-App-60x60@3x.png" + }, + { + "idiom":"iphone", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"1x", + "filename":"Icon-App-20x20@1x.png" + }, + { + "idiom":"ipad", + "size":"20x20", + "scale":"2x", + "filename":"Icon-App-20x20@2x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"1x", + "filename":"Icon-App-29x29@1x.png" + }, + { + "idiom":"ipad", + "size":"29x29", + "scale":"2x", + "filename":"Icon-App-29x29@2x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"1x", + "filename":"Icon-App-40x40@1x.png" + }, + { + "idiom":"ipad", + "size":"40x40", + "scale":"2x", + "filename":"Icon-App-40x40@2x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"1x", + "filename":"Icon-App-76x76@1x.png" + }, + { + "idiom":"ipad", + "size":"76x76", + "scale":"2x", + "filename":"Icon-App-76x76@2x.png" + }, + { + "idiom":"ipad", + "size":"83.5x83.5", + "scale":"2x", + "filename":"Icon-App-83.5x83.5@2x.png" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "scale" : "1x", + "filename" : "ItunesArtwork@2x.png" + } + ], + "info":{ + "version":1, + "author":"makeappicon" + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..6fda916 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..4de789e Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..56dacbe Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..3e3f879 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..d350ab6 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..97c16f5 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..4de789e Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..cfae7b5 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..526e180 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..526e180 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..3cee8e7 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..3f09509 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..05219e3 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..4ed78c3 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000..8d9d57b Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/check.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/check.imageset/Contents.json new file mode 100644 index 0000000..a3324a9 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/check.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "check@3x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/check.imageset/check@3x.png b/SwitchesDemo/Resources/Assets.xcassets/check.imageset/check@3x.png new file mode 100644 index 0000000..70e183c Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/check.imageset/check@3x.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/Contents.json new file mode 100644 index 0000000..6c3a466 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "check1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/check1.png b/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/check1.png new file mode 100644 index 0000000..a871fa1 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/check1.imageset/check1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/Contents.json new file mode 100644 index 0000000..dcb2ce9 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "check9.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/check9.png b/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/check9.png new file mode 100644 index 0000000..9b2854a Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/check9.imageset/check9.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/close.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/close.imageset/Contents.json new file mode 100644 index 0000000..f9c4569 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/close.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "close.pdf", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/close.imageset/close.pdf b/SwitchesDemo/Resources/Assets.xcassets/close.imageset/close.pdf new file mode 100644 index 0000000..864a14e Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/close.imageset/close.pdf differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/Contents.json new file mode 100644 index 0000000..6796ac5 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "cross1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/cross1.png b/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/cross1.png new file mode 100644 index 0000000..e48bdcf Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/cross1.imageset/cross1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/Contents.json new file mode 100644 index 0000000..14f243c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "cross24.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/cross24.png b/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/cross24.png new file mode 100644 index 0000000..ecbbecd Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/cross24.imageset/cross24.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/Contents.json new file mode 100644 index 0000000..7cdfd33 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "cross7.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/cross7.png b/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/cross7.png new file mode 100644 index 0000000..870287a Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/cross7.imageset/cross7.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/Contents.json new file mode 100644 index 0000000..b96e072 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "go1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/go1.png b/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/go1.png new file mode 100644 index 0000000..b6face9 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/go1.imageset/go1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/Contents.json new file mode 100644 index 0000000..ce2678c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "go2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/go2.png b/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/go2.png new file mode 100644 index 0000000..48a3ee9 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/go2.imageset/go2.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/Contents.json new file mode 100644 index 0000000..8c56795 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon_check_primary_dark.pdf", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/icon_check_primary_dark.pdf b/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/icon_check_primary_dark.pdf new file mode 100644 index 0000000..afd14a3 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/icon_check_primary_dark.imageset/icon_check_primary_dark.pdf differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/Contents.json new file mode 100644 index 0000000..36ce617 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon_close_dark_purple.pdf", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/icon_close_dark_purple.pdf b/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/icon_close_dark_purple.pdf new file mode 100644 index 0000000..d3d7329 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/icon_close_dark_purple.imageset/icon_close_dark_purple.pdf differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/left.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/left.imageset/Contents.json new file mode 100644 index 0000000..eb614f4 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/left.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "left.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/left.imageset/left.png b/SwitchesDemo/Resources/Assets.xcassets/left.imageset/left.png new file mode 100644 index 0000000..398b068 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/left.imageset/left.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/Contents.json new file mode 100644 index 0000000..e2cdd0c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "filename" : "off1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/off1.png b/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/off1.png new file mode 100644 index 0000000..92061de Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/off1.imageset/off1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/Contents.json new file mode 100644 index 0000000..310779c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "off2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/off2.png b/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/off2.png new file mode 100644 index 0000000..e2ff573 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/off2.imageset/off2.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/Contents.json new file mode 100644 index 0000000..7c93c8d --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "onTick.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/onTick.png b/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/onTick.png new file mode 100644 index 0000000..f5be558 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/onTick.imageset/onTick.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/Contents.json new file mode 100644 index 0000000..fbe962f --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "q1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/q1.png b/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/q1.png new file mode 100644 index 0000000..b3eb001 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/q1.imageset/q1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/right.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/right.imageset/Contents.json new file mode 100644 index 0000000..9d750f4 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/right.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "right.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/right.imageset/right.png b/SwitchesDemo/Resources/Assets.xcassets/right.imageset/right.png new file mode 100644 index 0000000..65fde24 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/right.imageset/right.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/Contents.json new file mode 100644 index 0000000..30665c5 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "switch-animation-post.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/switch-animation-post.jpg b/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/switch-animation-post.jpg new file mode 100644 index 0000000..d442602 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/switch-animation-post.imageset/switch-animation-post.jpg differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/Contents.json new file mode 100644 index 0000000..7acfec4 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "thumb.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/thumb.png b/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/thumb.png new file mode 100644 index 0000000..aec9669 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/thumb.imageset/thumb.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/Contents.json new file mode 100644 index 0000000..7ad0d3c --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "thumb1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/thumb1.png b/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/thumb1.png new file mode 100644 index 0000000..a51f3b3 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/thumb1.imageset/thumb1.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/Contents.json new file mode 100644 index 0000000..f663447 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "thumb12.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/thumb12.png b/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/thumb12.png new file mode 100644 index 0000000..328c7b1 Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/thumb12.imageset/thumb12.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/Contents.json new file mode 100644 index 0000000..ab81f65 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "thumb4.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/thumb4.png b/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/thumb4.png new file mode 100644 index 0000000..1a7238c Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/thumb4.imageset/thumb4.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/Contents.json new file mode 100644 index 0000000..39bbd98 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "thumb7.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/thumb7.png b/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/thumb7.png new file mode 100644 index 0000000..38307ae Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/thumb7.imageset/thumb7.png differ diff --git a/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/Contents.json b/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/Contents.json new file mode 100644 index 0000000..c3d2863 --- /dev/null +++ b/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "w1.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/w1.png b/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/w1.png new file mode 100644 index 0000000..65182cd Binary files /dev/null and b/SwitchesDemo/Resources/Assets.xcassets/w1.imageset/w1.png differ diff --git a/SwitchesDemo/Resources/Info.plist b/SwitchesDemo/Resources/Info.plist new file mode 100644 index 0000000..7dadcea --- /dev/null +++ b/SwitchesDemo/Resources/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Switches + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/SwitchesDemo/Storyboard/Base.lproj/LaunchScreen.storyboard b/SwitchesDemo/Storyboard/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..963c30f --- /dev/null +++ b/SwitchesDemo/Storyboard/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SwitchesDemo/Storyboard/Base.lproj/Main.storyboard b/SwitchesDemo/Storyboard/Base.lproj/Main.storyboard new file mode 100644 index 0000000..5368aa1 --- /dev/null +++ b/SwitchesDemo/Storyboard/Base.lproj/Main.storyboard @@ -0,0 +1,1322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SwitchesDemoTests/Info.plist b/SwitchesDemoTests/Info.plist new file mode 100644 index 0000000..64d65ca --- /dev/null +++ b/SwitchesDemoTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/SwitchesDemoTests/SwitchesDemoTests.swift b/SwitchesDemoTests/SwitchesDemoTests.swift new file mode 100644 index 0000000..6c15e3c --- /dev/null +++ b/SwitchesDemoTests/SwitchesDemoTests.swift @@ -0,0 +1,34 @@ +// +// SwitchesDemoTests.swift +// SwitchesDemoTests +// +// Created by Jawad Ali on 30/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import XCTest +@testable import SwitchesDemo + +class SwitchesDemoTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/SwitchesDemoUITests/Info.plist b/SwitchesDemoUITests/Info.plist new file mode 100644 index 0000000..64d65ca --- /dev/null +++ b/SwitchesDemoUITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/SwitchesDemoUITests/SwitchesDemoUITests.swift b/SwitchesDemoUITests/SwitchesDemoUITests.swift new file mode 100644 index 0000000..3bd5969 --- /dev/null +++ b/SwitchesDemoUITests/SwitchesDemoUITests.swift @@ -0,0 +1,43 @@ +// +// SwitchesDemoUITests.swift +// SwitchesDemoUITests +// +// Created by Jawad Ali on 30/08/2020. +// Copyright © 2020 Jawad Ali. All rights reserved. +// + +import XCTest + +class SwitchesDemoUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) { + XCUIApplication().launch() + } + } + } +}