-
Notifications
You must be signed in to change notification settings - Fork 232
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Oleg Oleynichenko
committed
Nov 26, 2014
1 parent
e74d659
commit 83df39f
Showing
23 changed files
with
1,181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#RAMViralSwitch | ||
|
||
Swift subclass of the UISwitch which paints over the parent view with the `onTintColor` when the switch is turned on. Implemented concept from [this Dribble](https://dribbble.com/shots/1749645-Contact-Sync) by [Ramotion](https://dribbble.com/teams/Ramotion). | ||
|
||
|
||
#Screenshot | ||
![ViralSwitch](https://d13yacurqjgara.cloudfront.net/users/25514/screenshots/1749645/contact-sync-chat-iphone-app-ui-ramotion.gif) | ||
|
||
|
||
## Requirements | ||
|
||
- iOS 7.0+ | ||
- Xcode 6.1 | ||
|
||
|
||
#Installation | ||
|
||
Just add the `RAMViralSwitch` folder to your project. | ||
|
||
|
||
#Usage | ||
RAMViralSwitch is a drop-in replacement of UISwitch. You just need to set the `onTintColor` property of the switch, and it will automatically _paint over_ its superview with the selected color. | ||
You have ability to set duration of animation instead of default value. | ||
|
||
1. Create a new UISwitch in your storyboard or nib. | ||
|
||
2. Set the class of the UISwitch to RAMViralSwitch in your Storyboard or nib. | ||
|
||
3. Set `onTintColor` for the switch | ||
|
||
4. Set `duration` propery programmatically if You want to change animation duration. | ||
|
||
5. Add animation for other views near the switch if need. | ||
|
||
|
||
#Animate views | ||
You can animate other views near the switch. For example, you can change color to views or labels that are inside the same superview. Duration of animation can be gotten from the RAMViralSwitch's property `duration`. You can animate CoreAnimation properties like this: | ||
|
||
``` swift | ||
self.viralSwitch.didAnimationStartClosure = {(onAnimation: Bool) in | ||
UIView.transitionWithView(self.label, duration: self.viralSwitch.duration, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: { | ||
self.label.textColor = onAnimation ? UIColor.whiteColor() : UIColor.blueColor() | ||
}, completion:nil) | ||
} | ||
``` | ||
|
||
## About Us | ||
|
||
[Ramotion](http://Ramotion.com) is an iPhone app design and development company. We are ready for new interesting iOS app development projects. | ||
|
||
Follow us on [twitter](http://twitter.com/ramotion). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// | ||
// RAContactSyncSwitch.swift | ||
// ContactSyncSwitchDemo | ||
// | ||
// Created by Oleg Oleynichenko on 20/11/14. | ||
// Copyright (c) 2014 Oleg Oleynichenko. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
|
||
class RAMViralSwitch: UISwitch { | ||
|
||
var didAnimationStartClosure = {(onAnimation: Bool) -> Void in } | ||
var didAnimationStopClosure = {(onAnimation: Bool, finished: Bool) -> Void in } | ||
|
||
var duration: CFTimeInterval = 0.35 | ||
|
||
|
||
private var shape: CAShapeLayer! = CAShapeLayer() | ||
private var radius: CGFloat = 0.0 | ||
|
||
|
||
override func setOn(on: Bool, animated: Bool) { | ||
var changed:Bool = on != self.on | ||
|
||
super.setOn(on, animated: animated) | ||
|
||
if changed { | ||
if animated { | ||
self.switchChanged(self) | ||
} else { | ||
self.showShape(on) | ||
} | ||
} | ||
} | ||
|
||
|
||
override func layoutSubviews() { | ||
let x:CGFloat = max(CGRectGetMidX(self.frame), self.superview!.frame.size.width - CGRectGetMidX(self.frame)); | ||
let y:CGFloat = max(CGRectGetMidY(self.frame), self.superview!.frame.size.height - CGRectGetMidY(self.frame)); | ||
self.radius = sqrt(x*x + y*y); | ||
|
||
self.shape.frame = CGRectMake(CGRectGetMidX(self.frame) - self.radius, CGRectGetMidY(self.frame) - self.radius, self.radius * 2, self.radius * 2) | ||
self.shape.anchorPoint = CGPointMake(0.5, 0.5); | ||
self.shape.path = UIBezierPath(ovalInRect: CGRectMake(0, 0, self.radius * 2, self.radius * 2)).CGPath | ||
} | ||
|
||
|
||
override func awakeFromNib() { | ||
var onTintColor:UIColor? = self.onTintColor | ||
if onTintColor == nil { | ||
onTintColor = UIColor.greenColor() | ||
} | ||
|
||
self.layer.borderWidth = 0.5 | ||
self.layer.borderColor = UIColor.whiteColor().CGColor; | ||
self.layer.cornerRadius = self.frame.size.height / 2; | ||
|
||
self.shape.fillColor = onTintColor?.CGColor | ||
self.shape.masksToBounds = true | ||
|
||
self.superview?.layer.insertSublayer(self.shape, atIndex: 0) | ||
self.superview?.layer.masksToBounds = true | ||
|
||
self.showShape(self.on) | ||
|
||
self.addTarget(self, action: "switchChanged:", forControlEvents: UIControlEvents.ValueChanged) | ||
} | ||
|
||
|
||
private func showShape(show: Bool) { | ||
self.shape.transform = show ? CATransform3DMakeScale(1.0, 1.0, 1.0) : CATransform3DMakeScale(0.0001, 0.0001, 0.0001) | ||
} | ||
|
||
|
||
internal func switchChanged(sender: UISwitch){ | ||
|
||
if sender.on { | ||
CATransaction.begin() | ||
|
||
self.shape.removeAnimationForKey("scaleDown") | ||
|
||
var scaleAnimation:CABasicAnimation = self.animateKeyPath("transform", | ||
fromValue: NSValue(CATransform3D: CATransform3DMakeScale(0.0001, 0.0001, 0.0001)), | ||
toValue:NSValue(CATransform3D: CATransform3DMakeScale(1.0, 1.0, 1.0)), | ||
timing:kCAMediaTimingFunctionEaseIn); | ||
|
||
self.shape.addAnimation(scaleAnimation, forKey: "scaleUp") | ||
|
||
CATransaction.commit(); | ||
} | ||
else { | ||
CATransaction.begin() | ||
self.shape.removeAnimationForKey("scaleUp") | ||
|
||
var scaleAnimation:CABasicAnimation = self.animateKeyPath("transform", | ||
fromValue: NSValue(CATransform3D: CATransform3DMakeScale(1.0, 1.0, 1.0)), | ||
toValue:NSValue(CATransform3D: CATransform3DMakeScale(0.0001, 0.0001, 0.0001)), | ||
timing:kCAMediaTimingFunctionEaseOut); | ||
|
||
self.shape.addAnimation(scaleAnimation, forKey: "scaleDown") | ||
|
||
CATransaction.commit(); | ||
} | ||
} | ||
|
||
|
||
private func animateKeyPath(keyPath: String, fromValue from: AnyObject, toValue to: AnyObject, timing timingFunction: String) -> CABasicAnimation { | ||
|
||
let animation:CABasicAnimation = CABasicAnimation(keyPath: keyPath) | ||
|
||
animation.fromValue = from | ||
animation.toValue = to | ||
animation.repeatCount = 1 | ||
animation.timingFunction = CAMediaTimingFunction(name: timingFunction) | ||
animation.removedOnCompletion = false | ||
animation.fillMode = kCAFillModeForwards | ||
animation.duration = self.duration; | ||
animation.delegate = self | ||
|
||
return animation; | ||
} | ||
|
||
|
||
//CAAnimation delegate | ||
|
||
|
||
override func animationDidStart(anim: CAAnimation!){ | ||
self.didAnimationStartClosure(self.on) | ||
} | ||
|
||
|
||
override func animationDidStop(anim: CAAnimation!, finished flag: Bool){ | ||
self.didAnimationStopClosure(self.on, flag) | ||
} | ||
} |
Oops, something went wrong.