diff --git a/.travis.yml b/.travis.yml index 4340e4a..ba1065e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,11 @@ -osx_image: xcode7.1 +osx_image: xcode8.1 language: objective-c env: global: - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 before_install: - - brew update || brew update - - brew outdated xctool || brew upgrade xctool - - gem install cocoapods + - gem install cocoapods --pre - xcrun simctl list install: echo "<3" env: @@ -18,4 +16,4 @@ script: ./build.sh $MODE # whitelist branches: only: - - master + - master \ No newline at end of file diff --git a/README.md b/README.md index 7cf1f2a..b0b9de4 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,16 @@ You can customize the parallax intensity of your TVButton. Default value is 1.0 tvButton.parallaxIntensity = 1.3 ``` +If you want to keep the image proportions +```swift + tvButton.saveAspect= true +``` + +For custom specular image set UIImage to +```swift + tvButton.customSpecularImage +``` + ![TVButton in action](http://i.giphy.com/l0O9zc8b49oDi209y.gif) Enjoy! diff --git a/TVButton.podspec b/TVButton.podspec index 8a2e68a..e9108f3 100644 --- a/TVButton.podspec +++ b/TVButton.podspec @@ -1,38 +1,21 @@ -# -# Be sure to run `pod lib lint TVButton.podspec' to ensure this is a -# valid spec before submitting. -# -# Any lines starting with a # are optional, but their use is encouraged -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# - Pod::Spec.new do |s| - s.name = "TVButton" - s.version = "0.1.5" - s.summary = "Apple TV style parallax icons as iOS UIButtons" +s.name = 'TVButton' +s.version = '0.1.8' +s.summary = 'Apple TV style parallax icons as iOS UIButtons' -# This description is used to generate tags and improve search results. -# * Think: What does it do? Why did you write it? What is the focus? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! - s.description = <<-DESC - Recreating the cool parallax icons from Apple TV as iOS UIButtons (in Swift). - DESC +s.description = <<-DESC +Recreating the cool parallax icons from Apple TV as iOS UIButtons (in Swift). +DESC - s.homepage = "https://github.com/marmelroy/TVButton" - # s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2" - s.license = 'MIT' - s.author = { "Roy Marmelstein" => "marmelroy@gmail.com" } - s.source = { :git => "https://github.com/marmelroy/TVButton.git", :tag => s.version.to_s } - s.social_media_url = "http://twitter.com/marmelroy" +s.homepage = 'https://github.com/marmelroy/TVButton' +s.license = 'MIT' +s.author = { 'Roy Marmelstein' => 'marmelroy@gmail.com' } +s.source = { :git => 'https://github.com/BOOMik/TVButton.git', :tag => s.version.to_s } +s.social_media_url = "http://twitter.com/marmelroy" - s.platform = :ios, '8.0' - s.requires_arc = true +s.platform = :ios,'8.0' - s.source_files = "TVButton" - s.resources = "TVButton/Specular.png" +s.source_files = "TVButton" +s.resources = "TVButton/Specular.png" - # s.public_header_files = 'Pod/Classes/**/*.h' - # s.dependency 'AFNetworking', '~> 2.3' -end +end diff --git a/TVButton.xcodeproj/project.pbxproj b/TVButton.xcodeproj/project.pbxproj index 7db8493..2eda685 100644 --- a/TVButton.xcodeproj/project.pbxproj +++ b/TVButton.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 342AA0901BEEBE6F00B1A7D9 /* TVButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 342AA08F1BEEBE6F00B1A7D9 /* TVButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 342AA0971BEEBE6F00B1A7D9 /* TVButton.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342AA08C1BEEBE6F00B1A7D9 /* TVButton.framework */; }; - 342AA09C1BEEBE6F00B1A7D9 /* TVButtonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342AA09B1BEEBE6F00B1A7D9 /* TVButtonTests.swift */; }; 342AA0A71BEEBF6E00B1A7D9 /* TVButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 342AA0A61BEEBF6E00B1A7D9 /* TVButton.swift */; }; 342AA0A91BEEBF7500B1A7D9 /* Specular.png in Resources */ = {isa = PBXBuildFile; fileRef = 342AA0A81BEEBF7500B1A7D9 /* Specular.png */; }; 34F374BE1BF1B0890085BE13 /* TVButtonAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F374BD1BF1B0890085BE13 /* TVButtonAnimation.swift */; }; @@ -31,8 +30,6 @@ 342AA08F1BEEBE6F00B1A7D9 /* TVButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TVButton.h; sourceTree = ""; }; 342AA0911BEEBE6F00B1A7D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 342AA0961BEEBE6F00B1A7D9 /* TVButtonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TVButtonTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 342AA09B1BEEBE6F00B1A7D9 /* TVButtonTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVButtonTests.swift; sourceTree = ""; }; - 342AA09D1BEEBE6F00B1A7D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 342AA0A61BEEBF6E00B1A7D9 /* TVButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TVButton.swift; sourceTree = ""; }; 342AA0A81BEEBF7500B1A7D9 /* Specular.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Specular.png; sourceTree = ""; }; 34F374BD1BF1B0890085BE13 /* TVButtonAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TVButtonAnimation.swift; sourceTree = ""; }; @@ -62,7 +59,6 @@ isa = PBXGroup; children = ( 342AA08E1BEEBE6F00B1A7D9 /* TVButton */, - 342AA09A1BEEBE6F00B1A7D9 /* TVButtonTests */, 342AA08D1BEEBE6F00B1A7D9 /* Products */, ); sourceTree = ""; @@ -87,15 +83,6 @@ path = TVButton; sourceTree = ""; }; - 342AA09A1BEEBE6F00B1A7D9 /* TVButtonTests */ = { - isa = PBXGroup; - children = ( - 342AA09B1BEEBE6F00B1A7D9 /* TVButtonTests.swift */, - 342AA09D1BEEBE6F00B1A7D9 /* Info.plist */, - ); - path = TVButtonTests; - sourceTree = ""; - }; 34F374CE1BF1B7EE0085BE13 /* Sources */ = { isa = PBXGroup; children = ( @@ -176,9 +163,11 @@ TargetAttributes = { 342AA08B1BEEBE6F00B1A7D9 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0820; }; 342AA0951BEEBE6F00B1A7D9 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0820; }; }; }; @@ -233,7 +222,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 342AA09C1BEEBE6F00B1A7D9 /* TVButtonTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,7 +273,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -327,7 +315,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 10.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -347,12 +335,13 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = TVButton/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.TVButton; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -366,11 +355,12 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = TVButton/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.TVButton; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -381,6 +371,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.TVButtonTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -391,6 +382,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.roymarmelstein.TVButtonTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/TVButton/Info.plist b/TVButton/Info.plist index 2429c6d..567c44f 100644 --- a/TVButton/Info.plist +++ b/TVButton/Info.plist @@ -15,12 +15,14 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.1.5 + 1.0.0 CFBundleSignature ???? CFBundleVersion - 7 + 17 NSPrincipalClass + MinimumOSVersion + 8.0 diff --git a/TVButton/TVButton.swift b/TVButton/TVButton.swift index d92690b..53db18a 100644 --- a/TVButton/TVButton.swift +++ b/TVButton/TVButton.swift @@ -29,7 +29,7 @@ public extension TVButtonLayer { /** TVButton Object */ -public class TVButton: UIButton, UIGestureRecognizerDelegate { +open class TVButton: UIButton, UIGestureRecognizerDelegate { // MARK: Internal variables internal var containerView = UIView() @@ -43,35 +43,51 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { // MARK: Public variables /// Stack of TVButtonLayers inside the button - public var layers: [TVButtonLayer]? { + open var layers: [TVButtonLayer]? { didSet { // Remove existing parallax layer views for subview in containerView.subviews { subview.removeFromSuperview() } + + // Instantiate an imageview with corners for every layer - for layer in layers! { - let imageView = UIImageView(image: layer.internalImage) - imageView.layer.cornerRadius = cornerRadius - imageView.clipsToBounds = true - imageView.layer.needsDisplayOnBoundsChange = true - containerView.addSubview(imageView) + if (layers != nil && layers!.count > 0) { + for layer in layers! { + let imageView = UIImageView(image: layer.internalImage) + imageView.layer.cornerRadius = cornerRadius + imageView.clipsToBounds = true + imageView.layer.needsDisplayOnBoundsChange = true + if saveAspect { + imageView.contentMode = .scaleAspectFill + } + containerView.addSubview(imageView) + } + // Add specular shine effect + if let specularImage = customSpecularImage { + specularView.image = specularImage + } else { + let frameworkBundle = Bundle(for: TVButton.self) + let specularViewPath = frameworkBundle.path(forResource: "Specular", ofType: "png") + specularView.image = UIImage(contentsOfFile: specularViewPath!) + } + updateFrame() + self.containerView.addSubview(specularView) } - // Add specular shine effect - let frameworkBundle = NSBundle(forClass: TVButton.self) - let specularViewPath = frameworkBundle.pathForResource("Specular", ofType: "png") - specularView.image = UIImage(contentsOfFile:specularViewPath!) - self.containerView.addSubview(specularView) } } + /// True if need save image aspect + open var customSpecularImage: UIImage? + /// True if need save image aspect + open var saveAspect: Bool = defaultSaveAspect /// Determines the intensity of the parallax depth effect. Default is 1.0. - public var parallaxIntensity: CGFloat = defaultParallaxIntensity + open var parallaxIntensity: CGFloat = defaultParallaxIntensity /// Shadow color for the TVButton. Default is black. - public var shadowColor: UIColor = UIColor.blackColor() { + open var shadowColor: UIColor = UIColor.black { didSet { - self.layer.shadowColor = shadowColor.CGColor + self.layer.shadowColor = shadowColor.cgColor } } @@ -96,13 +112,16 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { /** Lays out subviews. */ - override public func layoutSubviews() { + override open func layoutSubviews() { super.layoutSubviews() containerView.frame = self.bounds self.layer.masksToBounds = false; - let shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: cornerRadius) - self.layer.shadowPath = shadowPath.CGPath - + if (containerView.subviews.count > 0) { + let shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: cornerRadius) + self.layer.shadowPath = shadowPath.cgPath + } else { + self.layer.shadowPath = nil + } // Stop here if animation is on if let animation = tvButtonAnimation { if animation.highlightMode == true { @@ -113,27 +132,28 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { // Adjust size for every subview for subview in containerView.subviews { if subview == specularView { - subview.frame = CGRect(origin: subview.frame.origin, size: CGSizeMake(specularScale * containerView.frame.size.width, specularScale * containerView.frame.size.height)) + subview.frame = CGRect(origin: subview.frame.origin, size: CGSize(width: specularScale * containerView.frame.size.width, height: specularScale * containerView.frame.size.height)) } else { subview.frame = CGRect(origin: subview.frame.origin, size: containerView.frame.size) } } + updateFrame() } /** Button setup. Conducted on init. */ func setup() { - containerView.userInteractionEnabled = false + containerView.isUserInteractionEnabled = false self.addSubview(containerView) containerView.clipsToBounds = true containerView.layer.cornerRadius = cornerRadius self.clipsToBounds = true specularView.alpha = 0.0 - specularView.contentMode = UIViewContentMode.ScaleAspectFill + specularView.contentMode = UIViewContentMode.scaleAspectFill self.layer.shadowRadius = self.bounds.size.height/(2*shadowFactor) - self.layer.shadowOffset = CGSizeMake(0.0, shadowFactor/3) + self.layer.shadowOffset = CGSize(width: 0.0, height: shadowFactor/3) self.layer.shadowOpacity = 0.5; tvButtonAnimation = TVButtonAnimation(button: self) self.addGestureRecognizers() @@ -146,12 +166,12 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { Adds the gesture recognizers to the button. */ func addGestureRecognizers(){ - panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:") + panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(TVButton.handlePan(_:))) panGestureRecognizer?.delegate = self self.addGestureRecognizer(panGestureRecognizer!) - tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTap:") + tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(TVButton.handleTap(_:))) self.addGestureRecognizer(tapGestureRecognizer!) - longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:") + longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(TVButton.handleLongPress(_:))) longPressGestureRecognizer?.delegate = self self.addGestureRecognizer(longPressGestureRecognizer!) } @@ -160,7 +180,7 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { Pan gesture recognizer handler. - Parameter gestureRecognizer: TVButton's UIPanGestureRecognizer. */ - func handlePan(gestureRecognizer: UIGestureRecognizer) { + func handlePan(_ gestureRecognizer: UIGestureRecognizer) { self.gestureRecognizerDidUpdate(gestureRecognizer) } @@ -168,7 +188,7 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { Long press gesture recognizer handler. - Parameter gestureRecognizer: TVButton's UILongPressGestureRecognizer. */ - func handleLongPress(gestureRecognizer: UIGestureRecognizer) { + func handleLongPress(_ gestureRecognizer: UIGestureRecognizer) { self.gestureRecognizerDidUpdate(gestureRecognizer) } @@ -176,29 +196,29 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { Tap gesture recognizer handler. Sends TouchUpInside to super. - Parameter gestureRecognizer: TVButton's UITapGestureRecognizer. */ - func handleTap(gestureRecognizer: UIGestureRecognizer) { - super.sendActionsForControlEvents(UIControlEvents.TouchUpInside) + func handleTap(_ gestureRecognizer: UIGestureRecognizer) { + super.sendActions(for: UIControlEvents.touchUpInside) } /** Determines button's reaction to gesturerecognizer. - Parameter gestureRecognizer: either UITapGestureRecognizer or UILongPressGestureRecognizer. */ - func gestureRecognizerDidUpdate(gestureRecognizer: UIGestureRecognizer){ + func gestureRecognizerDidUpdate(_ gestureRecognizer: UIGestureRecognizer){ if layers == nil { return } - let point = gestureRecognizer.locationInView(self) + let point = gestureRecognizer.location(in: self) if let animation = tvButtonAnimation { - if gestureRecognizer.state == .Began { + if gestureRecognizer.state == .began { animation.enterMovement() animation.processMovement(point) } - else if gestureRecognizer.state == .Changed { + else if gestureRecognizer.state == .changed { animation.processMovement(point) } else { - if gestureRecognizer.state == .Began || gestureRecognizer.state == .Changed { + if gestureRecognizer.state == .began || gestureRecognizer.state == .changed { return } animation.exitMovement() @@ -213,8 +233,53 @@ public class TVButton: UIButton, UIGestureRecognizerDelegate { - Parameter gestureRecognizer: First gestureRecognizer. - Parameter otherGestureRecognizer: Second gestureRecognizer. */ - public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { + open func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } - -} \ No newline at end of file + + + func getScaledSizeOfImage(_ image: UIImage, toSize: CGSize) -> CGSize + { + let widthRatio = toSize.width/image.size.width + let heightRatio = toSize.height/image.size.height + let scale = min(widthRatio, heightRatio) + let imageWidth = scale*image.size.width + let imageHeight = scale*image.size.height + return CGSize(width: imageWidth, height: imageHeight) + } + + + + open func updateFrame() { + if (saveAspect && layers != nil && layers!.count > 0) { + var newSize:CGSize = getScaledSizeOfImage(layers![0].internalImage!, toSize: self.frame.size) + + var frame = self.frame + + if let sv = self.superview { + if (sv.frame.width != 0 && sv.frame.height != 0 ) { + newSize = getScaledSizeOfImage(layers![0].internalImage!, toSize: sv.frame.size) + frame = sv.frame + } + } + + + var svframe = specularView.frame; + svframe.size = newSize + specularView.frame = svframe; + + + let x = (frame.width - newSize.width) / 2 + let y = (frame.height - newSize.height) / 2 + + frame.origin.x = x + frame.origin.y = y + + frame.size = newSize + self.frame = frame; + self.layoutIfNeeded() + } + } + + +} diff --git a/TVButton/TVButtonAnimation.swift b/TVButton/TVButtonAnimation.swift index dc8bf0a..21a7125 100644 --- a/TVButton/TVButtonAnimation.swift +++ b/TVButton/TVButtonAnimation.swift @@ -31,33 +31,33 @@ internal class TVButtonAnimation { } if let tvButton = button { self.highlightMode = true - let targetShadowOffset = CGSizeMake(0.0, tvButton.bounds.size.height/shadowFactor) + let targetShadowOffset = CGSize(width: 0.0, height: tvButton.bounds.size.height/shadowFactor) tvButton.layer.removeAllAnimations() CATransaction.begin() CATransaction.setCompletionBlock({ () -> Void in tvButton.layer.shadowOffset = targetShadowOffset }) let shaowOffsetAnimation = CABasicAnimation(keyPath: "shadowOffset") - shaowOffsetAnimation.toValue = NSValue(CGSize: targetShadowOffset) + shaowOffsetAnimation.toValue = NSValue(cgSize: targetShadowOffset) shaowOffsetAnimation.duration = animationDuration - shaowOffsetAnimation.removedOnCompletion = false + shaowOffsetAnimation.isRemovedOnCompletion = false shaowOffsetAnimation.fillMode = kCAFillModeForwards shaowOffsetAnimation.timingFunction = CAMediaTimingFunction(name: "easeOut") - tvButton.layer.addAnimation(shaowOffsetAnimation, forKey: "shadowOffset") + tvButton.layer.add(shaowOffsetAnimation, forKey: "shadowOffset") CATransaction.commit() let shadowOpacityAnimation = CABasicAnimation(keyPath: "shadowOpacity") shadowOpacityAnimation.toValue = 0.6 shadowOpacityAnimation.duration = animationDuration - shadowOpacityAnimation.removedOnCompletion = false + shadowOpacityAnimation.isRemovedOnCompletion = false shadowOpacityAnimation.fillMode = kCAFillModeForwards shadowOpacityAnimation.timingFunction = CAMediaTimingFunction(name: "easeOut") - tvButton.layer.addAnimation(shadowOpacityAnimation, forKey: "shadowOpacityAnimation") + tvButton.layer.add(shadowOpacityAnimation, forKey: "shadowOpacityAnimation") CATransaction.commit() } } // Movement continues - func processMovement(point: CGPoint){ + func processMovement(_ point: CGPoint){ if (highlightMode == false) { return } @@ -84,28 +84,32 @@ internal class TVButtonAnimation { let targetScaleTransform = CATransform3DMakeScale(highlightedScale, highlightedScale, highlightedScale) let combinedTransform = CATransform3DConcat(combinedRotateTranslateTransform, targetScaleTransform) - UIView.animateWithDuration(animationDuration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in + UIView.animate(withDuration: animationDuration, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { () -> Void in tvButton.layer.transform = combinedTransform tvButton.specularView.alpha = specularAlpha tvButton.specularView.center = point - for var i = 1; i < tvButton.containerView.subviews.count ; i++ { - let adjusted = i/2 - let scale = 1 + maxScaleDelta*CGFloat(adjusted/tvButton.containerView.subviews.count) - let subview = tvButton.containerView.subviews[i] - if subview != tvButton.specularView { - subview.contentMode = UIViewContentMode.Redraw - subview.frame.size = CGSizeMake(tvButton.bounds.size.width*scale, tvButton.bounds.size.height*scale) + if (tvButton.containerView.subviews.count > 0) { + for i in 1 ..< tvButton.containerView.subviews.count { + let adjusted = i/2 + let scale = 1 + maxScaleDelta*CGFloat(adjusted/tvButton.containerView.subviews.count) + let subview = tvButton.containerView.subviews[i] + if subview != tvButton.specularView { + subview.contentMode = UIViewContentMode.redraw + subview.frame.size = CGSize(width: tvButton.bounds.size.width*scale, height: tvButton.bounds. size.height*scale) + } } } }, completion: nil) - UIView.animateWithDuration(0.16, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in - for var i = 1; i < tvButton.containerView.subviews.count ; i++ { - let subview = tvButton.containerView.subviews[i] - let xParallax = tvButton.parallaxIntensity*parallaxIntensityXFactor - let yParallax = tvButton.parallaxIntensity*parallaxIntensityYFactor - if subview != tvButton.specularView { - subview.center = CGPointMake(tvButton.bounds.size.width/2 + xTranslation*CGFloat(i)*xParallax, tvButton.bounds.size.height/2 + yTranslation*CGFloat(i)*0.3*yParallax) + UIView.animate(withDuration: 0.16, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { () -> Void in + if (tvButton.containerView.subviews.count > 0) { + for i in 1 ..< tvButton.containerView.subviews.count { + let subview = tvButton.containerView.subviews[i] + let xParallax = tvButton.parallaxIntensity*parallaxIntensityXFactor + let yParallax = tvButton.parallaxIntensity*parallaxIntensityYFactor + if subview != tvButton.specularView { + subview.center = CGPoint(x: tvButton.bounds.size.width/2 + xTranslation*CGFloat(i)*xParallax, y: tvButton.bounds.size.height/2 + yTranslation*CGFloat(i)*0.3*yParallax) + } } } }, completion: nil) @@ -119,7 +123,7 @@ internal class TVButtonAnimation { return } if let tvButton = button { - let targetShadowOffset = CGSizeMake(0.0, shadowFactor/3) + let targetShadowOffset = CGSize(width: 0.0, height: shadowFactor/3) let targetScaleTransform = CATransform3DMakeScale(1.0, 1.0, 1.0) tvButton.specularView.layer.removeAllAnimations() CATransaction.begin() @@ -129,27 +133,29 @@ internal class TVButtonAnimation { self.highlightMode = false }) let shaowOffsetAnimation = CABasicAnimation(keyPath: "shadowOffset") - shaowOffsetAnimation.toValue = NSValue(CGSize: targetShadowOffset) + shaowOffsetAnimation.toValue = NSValue(cgSize: targetShadowOffset) shaowOffsetAnimation.duration = animationDuration shaowOffsetAnimation.fillMode = kCAFillModeForwards - shaowOffsetAnimation.removedOnCompletion = false + shaowOffsetAnimation.isRemovedOnCompletion = false shaowOffsetAnimation.timingFunction = CAMediaTimingFunction(name: "easeOut") - tvButton.layer.addAnimation(shaowOffsetAnimation, forKey: "shadowOffset") + tvButton.layer.add(shaowOffsetAnimation, forKey: "shadowOffset") let scaleAnimation = CABasicAnimation(keyPath: "transform") - scaleAnimation.toValue = NSValue(CATransform3D: targetScaleTransform) + scaleAnimation.toValue = NSValue(caTransform3D: targetScaleTransform) scaleAnimation.duration = animationDuration - scaleAnimation.removedOnCompletion = false + scaleAnimation.isRemovedOnCompletion = false scaleAnimation.fillMode = kCAFillModeForwards scaleAnimation.timingFunction = CAMediaTimingFunction(name: "easeOut") - tvButton.layer.addAnimation(scaleAnimation, forKey: "scaleAnimation") + tvButton.layer.add(scaleAnimation, forKey: "scaleAnimation") CATransaction.commit() - UIView.animateWithDuration(animationDuration, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: { () -> Void in - tvButton.transform = CGAffineTransformIdentity + UIView.animate(withDuration: animationDuration, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { () -> Void in + tvButton.transform = CGAffineTransform.identity tvButton.specularView.alpha = 0.0 - for var i = 0; i < tvButton.containerView.subviews.count ; i++ { - let subview = tvButton.containerView.subviews[i] - subview.frame.size = CGSizeMake(tvButton.bounds.size.width, tvButton.bounds.size.height) - subview.center = CGPointMake(tvButton.bounds.size.width/2, tvButton.bounds.size.height/2) + if (tvButton.containerView.subviews.count > 0) { + for i in 0 ..< tvButton.containerView.subviews.count { + let subview = tvButton.containerView.subviews[i] + subview.frame.size = CGSize(width: tvButton.bounds.size.width, height: tvButton.bounds.size.height) + subview.center = CGPoint(x: tvButton.bounds.size.width/2, y: tvButton.bounds.size.height/2) + } } }, completion:nil) } @@ -157,8 +163,8 @@ internal class TVButtonAnimation { // MARK: Convenience - func degreesToRadians(value:CGFloat) -> CGFloat { + func degreesToRadians(_ value:CGFloat) -> CGFloat { return value * CGFloat(M_PI) / 180.0 } -} \ No newline at end of file +} diff --git a/TVButton/TVButtonConstants.swift b/TVButton/TVButtonConstants.swift index b0d8d8a..05734bc 100644 --- a/TVButton/TVButtonConstants.swift +++ b/TVButton/TVButtonConstants.swift @@ -51,4 +51,7 @@ let shadowFactor: CGFloat = 10 let specularScale: CGFloat = 2.0 // The scale of the specular shine -let specularAlpha: CGFloat = 0.25 \ No newline at end of file +let specularAlpha: CGFloat = 0.25 + +// If need save aspect +let defaultSaveAspect : Bool = false diff --git a/TVButtonTests/Info.plist b/TVButtonTests/Info.plist deleted file mode 100644 index 3b4743b..0000000 --- a/TVButtonTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 0.1.5 - CFBundleSignature - ???? - CFBundleVersion - 7 - - diff --git a/TVButtonTests/TVButtonTests.swift b/TVButtonTests/TVButtonTests.swift deleted file mode 100644 index b7645bc..0000000 --- a/TVButtonTests/TVButtonTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// TVButtonTests.swift -// TVButtonTests -// -// Created by Roy Marmelstein on 08/11/2015. -// Copyright © 2015 Roy Marmelstein. All rights reserved. -// - -import XCTest -@testable import TVButton - -class TVButtonTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measureBlock { - // Put the code you want to measure the time of here. - } - } - -}