1、CHSwitch.h

//
// 文 件 名:CHSwitch.h
//
// 版权所有:Copyright © 2018 lelight. All rights reserved.
// 创 建 者:lelight
// 创建日期:2018/12/19.
// 文档说明:
// 修 改 人:
// 修改日期:
// #import <UIKit/UIKit.h> NS_ASSUME_NONNULL_BEGIN typedef enum {
CHSwitchShapeOval,
CHSwitchShapeRectangle,
CHSwitchShapeRectangleNoCorner
} CHSwitchShape; @interface CHSwitch : UIControl <UIGestureRecognizerDelegate> /** 开关状态读取与设置 */
@property (nonatomic, getter = isOn) BOOL on;
/** 开关形状枚举值:默认CHSwitchShapeOval */
@property (nonatomic, assign) CHSwitchShape shape;
/** 打开时的颜色 */
@property (nonatomic, strong) UIColor *onTintColor;
/** 关闭时的颜色 */
@property (nonatomic, strong) UIColor *tintColor;
/** 圆点颜色 */
@property (nonatomic, strong) UIColor *thumbTintColor;
/** 是否需要阴影效果 */
@property (nonatomic, assign) BOOL shadow;
/** 关闭时的阴影颜色 */
@property (nonatomic, strong) UIColor *tintBorderColor;
/** 打开时的阴影颜色 */
@property (nonatomic, strong) UIColor *onTintBorderColor; @end NS_ASSUME_NONNULL_END

2、CHSwitch.m

//
// 文 件 名:CHSwitch.m
//
// 版权所有:Copyright © 2018 lelight. All rights reserved.
// 创 建 者:lelight
// 创建日期:2018/12/19.
// 文档说明:
// 修 改 人:
// 修改日期:
// #import "CHSwitch.h"
#import <QuartzCore/QuartzCore.h> static const CGFloat kAnimateDuration = 0.3f;
static const CGFloat kHorizontalAdjustment = 3.0f;
static const CGFloat kRectShapeCornerRadius = 4.0f;
static const CGFloat kThumbShadowOpacity = 0.3f;
static const CGFloat kThumbShadowRadius = 0.5f;
static const CGFloat kSwitchBorderWidth = 1.75f; @interface CHSwitch () @property (nonatomic, strong) UIView *onBackgroundView;
@property (nonatomic, strong) UIView *offBackgroundView;
@property (nonatomic, strong) UIView *thumbView; @end @implementation CHSwitch @synthesize onBackgroundView = _onBackgroundView;
@synthesize offBackgroundView = _offBackgroundView;
@synthesize thumbView = _thumbView;
@synthesize on = _on;
@synthesize shape = _shape;
@synthesize onTintColor = _onTintColor;
@synthesize tintColor = _tintColor;
@synthesize thumbTintColor = _thumbTintColor;
@synthesize shadow = _shadow;
@synthesize onTintBorderColor = _onTintBorderColor;
@synthesize tintBorderColor = _tintBorderColor; #pragma mark - View
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupUI];
}
return self;
} - (void) awakeFromNib {
[super awakeFromNib]; [self setupUI];
} - (void)setupUI {
self.shape = CHSwitchShapeOval; [self setBackgroundColor:[UIColor clearColor]]; // Background view for ON
self.onBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[self.onBackgroundView setBackgroundColor:[UIColor colorWithRed:(19.0f/255.0f) green:(121.0f/255.0f) blue:(208.0f/255.0f) alpha:1.0f]];
[self.onBackgroundView.layer setCornerRadius:self.frame.size.height/2];
[self.onBackgroundView.layer setShouldRasterize:YES];
[self.onBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale];
[self addSubview:self.onBackgroundView]; // Background view for OFF
self.offBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[self.offBackgroundView setBackgroundColor:[UIColor whiteColor]];
[self.offBackgroundView.layer setCornerRadius:self.frame.size.height/2];
[self.offBackgroundView.layer setShouldRasterize:YES];
[self.offBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale];
[self addSubview:self.offBackgroundView]; // Round switch view
self.thumbView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.height-kHorizontalAdjustment, self.frame.size.height-kHorizontalAdjustment)];
[self.thumbView setBackgroundColor:[UIColor whiteColor]];
[self.thumbView setUserInteractionEnabled:YES];
[self.thumbView.layer setCornerRadius:(self.frame.size.height-kHorizontalAdjustment)/2];
[self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)];
[self.thumbView.layer setShouldRasterize:YES];
[self.thumbView.layer setShadowOpacity:kThumbShadowOpacity];
[self.thumbView.layer setRasterizationScale:[UIScreen mainScreen].scale];
[self addSubview:self.thumbView];
self.shadow = YES; // Default to OFF position
[self.thumbView setCenter:CGPointMake(self.thumbView.frame.size.width/2, self.frame.size.height/2)]; // Handle Thumb Tap Gesture
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleSwitchTap:)];
[tapGestureRecognizer setDelegate:self];
[self.thumbView addGestureRecognizer:tapGestureRecognizer]; // Handle Background Tap Gesture
UITapGestureRecognizer *tapBgGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBgTap:)];
[tapBgGestureRecognizer setDelegate:self];
[self addGestureRecognizer:tapBgGestureRecognizer]; // Handle Thumb Pan Gesture
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[panGestureRecognizer setDelegate:self];
[self.thumbView addGestureRecognizer:panGestureRecognizer]; [self setOn:NO];
} #pragma mark - Accessor
- (BOOL)isOn {
return _on;
} - (void)setOn:(BOOL)on {
if (_on != on)
_on = on; if (_on) {
[self.onBackgroundView setAlpha:1.0];
self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0); self.thumbView.center = CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width + kHorizontalAdjustment)/2, self.thumbView.center.y);
}
else {
[self.onBackgroundView setAlpha:0.0];
self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0); self.thumbView.center = CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y);
}
} - (void)setOnTintColor:(UIColor *)color
{
if (_onTintColor != color)
_onTintColor = color; [self.onBackgroundView setBackgroundColor:color];
} - (void)setOnTintBorderColor:(UIColor *)color
{
if (_onTintBorderColor != color)
_onTintBorderColor = color; [self.onBackgroundView.layer setBorderColor:color.CGColor]; if (color)
[self.onBackgroundView.layer setBorderWidth:kSwitchBorderWidth];
else
[self.onBackgroundView.layer setBorderWidth:0.0];
} - (void)setTintColor:(UIColor *)color
{
if (_tintColor != color)
_tintColor = color; [self.offBackgroundView setBackgroundColor:color];
} - (void)setTintBorderColor:(UIColor *)color
{
if (_tintBorderColor != color)
_tintBorderColor = color; [self.offBackgroundView.layer setBorderColor:color.CGColor]; if (color)
[self.offBackgroundView.layer setBorderWidth:kSwitchBorderWidth];
else
[self.offBackgroundView.layer setBorderWidth:0.0];
} - (void)setThumbTintColor:(UIColor *)color
{
if (_thumbTintColor != color)
_thumbTintColor = color; [self.thumbView setBackgroundColor:color];
} - (void)setShape:(CHSwitchShape)newShape
{
if (_shape != newShape)
_shape = newShape; if (newShape == CHSwitchShapeOval)
{
[self.onBackgroundView.layer setCornerRadius:self.frame.size.height/2];
[self.offBackgroundView.layer setCornerRadius:self.frame.size.height/2];
[self.thumbView.layer setCornerRadius:(self.frame.size.height-kHorizontalAdjustment)/2];
}
else if (newShape == CHSwitchShapeRectangle)
{
[self.onBackgroundView.layer setCornerRadius:kRectShapeCornerRadius];
[self.offBackgroundView.layer setCornerRadius:kRectShapeCornerRadius];
[self.thumbView.layer setCornerRadius:kRectShapeCornerRadius];
}
else if (newShape == CHSwitchShapeRectangleNoCorner)
{
[self.onBackgroundView.layer setCornerRadius:0];
[self.offBackgroundView.layer setCornerRadius:0];
[self.thumbView.layer setCornerRadius:0];
}
} - (void)setShadow:(BOOL)showShadow
{
if (_shadow != showShadow)
_shadow = showShadow; if (showShadow)
{
[self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)];
[self.thumbView.layer setShadowRadius:kThumbShadowRadius];
[self.thumbView.layer setShadowOpacity:kThumbShadowOpacity];
}
else
{
[self.thumbView.layer setShadowRadius:0.0];
[self.thumbView.layer setShadowOpacity:0.0];
}
} #pragma mark - Animation
- (void)animateToDestination:(CGPoint)centerPoint withDuration:(CGFloat)duration switch:(BOOL)on
{
[UIView animateWithDuration:duration
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.thumbView.center = centerPoint; if (on)
{
[self.onBackgroundView setAlpha:1.0];
}
else
{
[self.onBackgroundView setAlpha:0.0];
} }
completion:^(BOOL finished) {
if (finished)
{
[self updateSwitch:on];
} }]; [UIView animateWithDuration:duration
delay:0.075f
options:UIViewAnimationOptionCurveEaseOut
animations:^{
if (on)
{
self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0);
}
else
{
self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0);
} }
completion:^(BOOL finished) {
}];
} #pragma mark - Gesture Recognizers
- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.thumbView]; // Check the new center to see if within the boud
CGPoint newCenter = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y);
if (newCenter.x < (recognizer.view.frame.size.width+kHorizontalAdjustment)/2 || newCenter.x > self.onBackgroundView.frame.size.width-(recognizer.view.frame.size.width+kHorizontalAdjustment)/2)
{
// New center is Out of bound. Animate to left or right position
if(recognizer.state == UIGestureRecognizerStateBegan ||
recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint velocity = [recognizer velocityInView:self.thumbView]; if (velocity.x >= 0)
{
// Animate move to right
[self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
}
else
{
// Animate move to left
[self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
} } return;
} // Only allow vertical pan
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.thumbView]; CGPoint velocity = [recognizer velocityInView:self.thumbView]; if(recognizer.state == UIGestureRecognizerStateEnded)
{
if (velocity.x >= 0)
{
if (recognizer.view.center.x < self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2)
{
// Animate move to right
[self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
}
}
else
{
// Animate move to left
[self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
}
}
} - (void)handleSwitchTap:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded)
{
if (self.isOn)
{
// Animate move to left
[self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
}
else
{
// Animate move to right
[self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
}
}
} - (void)handleBgTap:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded)
{
if (self.isOn)
{
// Animate move to left
[self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:NO];
}
else
{
// Animate move to right
[self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:YES];
}
}
} #pragma mark -
- (void)updateSwitch:(BOOL)on
{
if (_on != on)
_on = on; [self sendActionsForControlEvents:UIControlEventValueChanged];
} @end

最新文章

  1. android 帧动画,补间动画,属性动画的简单总结
  2. vsftp linux
  3. Mybatis错误(一)org.apache.ibatis.exceptions.PersistenceException
  4. eclipse luna maven失效的原因
  5. OpenCV实现KNN算法
  6. 51nod1022 石子归并 V2
  7. Java线程监听,意外退出线程后自动重启
  8. KMP和扩展KMP【转】
  9. C#中将图片文件转化为二进制数组-用于数据库存储
  10. Longest Consecutive Sequence 解答
  11. opnet的simple_source模块学习 分类: opnet 2014-05-18 09:50 170人阅读 评论(0) 收藏
  12. tornado之子模板
  13. zoj 3981 Balloon Robot
  14. Android Gradle 自定义Task 详解
  15. 菜鸟学IT之python网页爬取初体验
  16. docker pull centos慢问题的解决方案
  17. 2018.06.27Going Home(二分图匹配)
  18. MVC技术的面试问题
  19. 2018NOIP爆0记第一弹
  20. 搭建github博客,hexo主题

热门文章

  1. Py修行路 python基础 (九)作用域 函数嵌套 闭包
  2. STM32用有源蜂鸣器实现闹钟的声响
  3. Android开发笔记 TableLayout常用的属性介绍
  4. MySQL MVCC原理
  5. React 常用面试题目与分析
  6. Java多线程-线程的交互
  7. consul watch
  8. Location - BOM对象
  9. linux下rsync命令详细整理
  10. java就业指南 zookeeper分布式系统 zookeeper实现分布式锁 有用