1、CHSwitch.h

  1. //
  2. // 文 件 名:CHSwitch.h
  3. //
  4. // 版权所有:Copyright © 2018 lelight. All rights reserved.
  5. // 创 建 者:lelight
  6. // 创建日期:2018/12/19.
  7. // 文档说明:
  8. // 修 改 人:
  9. // 修改日期:
  10. //
  11. #import <UIKit/UIKit.h>
  12. NS_ASSUME_NONNULL_BEGIN
  13. typedef enum {
  14. CHSwitchShapeOval,
  15. CHSwitchShapeRectangle,
  16. CHSwitchShapeRectangleNoCorner
  17. } CHSwitchShape;
  18. @interface CHSwitch : UIControl <UIGestureRecognizerDelegate>
  19. /** 开关状态读取与设置 */
  20. @property (nonatomic, getter = isOn) BOOL on;
  21. /** 开关形状枚举值:默认CHSwitchShapeOval */
  22. @property (nonatomic, assign) CHSwitchShape shape;
  23. /** 打开时的颜色 */
  24. @property (nonatomic, strong) UIColor *onTintColor;
  25. /** 关闭时的颜色 */
  26. @property (nonatomic, strong) UIColor *tintColor;
  27. /** 圆点颜色 */
  28. @property (nonatomic, strong) UIColor *thumbTintColor;
  29. /** 是否需要阴影效果 */
  30. @property (nonatomic, assign) BOOL shadow;
  31. /** 关闭时的阴影颜色 */
  32. @property (nonatomic, strong) UIColor *tintBorderColor;
  33. /** 打开时的阴影颜色 */
  34. @property (nonatomic, strong) UIColor *onTintBorderColor;
  35. @end
  36. NS_ASSUME_NONNULL_END

2、CHSwitch.m

  1. //
  2. // 文 件 名:CHSwitch.m
  3. //
  4. // 版权所有:Copyright © 2018 lelight. All rights reserved.
  5. // 创 建 者:lelight
  6. // 创建日期:2018/12/19.
  7. // 文档说明:
  8. // 修 改 人:
  9. // 修改日期:
  10. //
  11. #import "CHSwitch.h"
  12. #import <QuartzCore/QuartzCore.h>
  13. static const CGFloat kAnimateDuration = 0.3f;
  14. static const CGFloat kHorizontalAdjustment = 3.0f;
  15. static const CGFloat kRectShapeCornerRadius = 4.0f;
  16. static const CGFloat kThumbShadowOpacity = 0.3f;
  17. static const CGFloat kThumbShadowRadius = 0.5f;
  18. static const CGFloat kSwitchBorderWidth = 1.75f;
  19. @interface CHSwitch ()
  20. @property (nonatomic, strong) UIView *onBackgroundView;
  21. @property (nonatomic, strong) UIView *offBackgroundView;
  22. @property (nonatomic, strong) UIView *thumbView;
  23. @end
  24. @implementation CHSwitch
  25. @synthesize onBackgroundView = _onBackgroundView;
  26. @synthesize offBackgroundView = _offBackgroundView;
  27. @synthesize thumbView = _thumbView;
  28. @synthesize on = _on;
  29. @synthesize shape = _shape;
  30. @synthesize onTintColor = _onTintColor;
  31. @synthesize tintColor = _tintColor;
  32. @synthesize thumbTintColor = _thumbTintColor;
  33. @synthesize shadow = _shadow;
  34. @synthesize onTintBorderColor = _onTintBorderColor;
  35. @synthesize tintBorderColor = _tintBorderColor;
  36. #pragma mark - View
  37. - (id)initWithFrame:(CGRect)frame {
  38. self = [super initWithFrame:frame];
  39. if (self) {
  40. [self setupUI];
  41. }
  42. return self;
  43. }
  44. - (void) awakeFromNib {
  45. [super awakeFromNib];
  46. [self setupUI];
  47. }
  48. - (void)setupUI {
  49. self.shape = CHSwitchShapeOval;
  50. [self setBackgroundColor:[UIColor clearColor]];
  51. // Background view for ON
  52. self.onBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
  53. [self.onBackgroundView setBackgroundColor:[UIColor colorWithRed:(19.0f/255.0f) green:(121.0f/255.0f) blue:(208.0f/255.0f) alpha:1.0f]];
  54. [self.onBackgroundView.layer setCornerRadius:self.frame.size.height/2];
  55. [self.onBackgroundView.layer setShouldRasterize:YES];
  56. [self.onBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale];
  57. [self addSubview:self.onBackgroundView];
  58. // Background view for OFF
  59. self.offBackgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
  60. [self.offBackgroundView setBackgroundColor:[UIColor whiteColor]];
  61. [self.offBackgroundView.layer setCornerRadius:self.frame.size.height/2];
  62. [self.offBackgroundView.layer setShouldRasterize:YES];
  63. [self.offBackgroundView.layer setRasterizationScale:[UIScreen mainScreen].scale];
  64. [self addSubview:self.offBackgroundView];
  65. // Round switch view
  66. self.thumbView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.height-kHorizontalAdjustment, self.frame.size.height-kHorizontalAdjustment)];
  67. [self.thumbView setBackgroundColor:[UIColor whiteColor]];
  68. [self.thumbView setUserInteractionEnabled:YES];
  69. [self.thumbView.layer setCornerRadius:(self.frame.size.height-kHorizontalAdjustment)/2];
  70. [self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)];
  71. [self.thumbView.layer setShouldRasterize:YES];
  72. [self.thumbView.layer setShadowOpacity:kThumbShadowOpacity];
  73. [self.thumbView.layer setRasterizationScale:[UIScreen mainScreen].scale];
  74. [self addSubview:self.thumbView];
  75. self.shadow = YES;
  76. // Default to OFF position
  77. [self.thumbView setCenter:CGPointMake(self.thumbView.frame.size.width/2, self.frame.size.height/2)];
  78. // Handle Thumb Tap Gesture
  79. UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
  80. action:@selector(handleSwitchTap:)];
  81. [tapGestureRecognizer setDelegate:self];
  82. [self.thumbView addGestureRecognizer:tapGestureRecognizer];
  83. // Handle Background Tap Gesture
  84. UITapGestureRecognizer *tapBgGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBgTap:)];
  85. [tapBgGestureRecognizer setDelegate:self];
  86. [self addGestureRecognizer:tapBgGestureRecognizer];
  87. // Handle Thumb Pan Gesture
  88. UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
  89. [panGestureRecognizer setDelegate:self];
  90. [self.thumbView addGestureRecognizer:panGestureRecognizer];
  91. [self setOn:NO];
  92. }
  93. #pragma mark - Accessor
  94. - (BOOL)isOn {
  95. return _on;
  96. }
  97. - (void)setOn:(BOOL)on {
  98. if (_on != on)
  99. _on = on;
  100. if (_on) {
  101. [self.onBackgroundView setAlpha:1.0];
  102. self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0);
  103. self.thumbView.center = CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width + kHorizontalAdjustment)/2, self.thumbView.center.y);
  104. }
  105. else {
  106. [self.onBackgroundView setAlpha:0.0];
  107. self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0);
  108. self.thumbView.center = CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y);
  109. }
  110. }
  111. - (void)setOnTintColor:(UIColor *)color
  112. {
  113. if (_onTintColor != color)
  114. _onTintColor = color;
  115. [self.onBackgroundView setBackgroundColor:color];
  116. }
  117. - (void)setOnTintBorderColor:(UIColor *)color
  118. {
  119. if (_onTintBorderColor != color)
  120. _onTintBorderColor = color;
  121. [self.onBackgroundView.layer setBorderColor:color.CGColor];
  122. if (color)
  123. [self.onBackgroundView.layer setBorderWidth:kSwitchBorderWidth];
  124. else
  125. [self.onBackgroundView.layer setBorderWidth:0.0];
  126. }
  127. - (void)setTintColor:(UIColor *)color
  128. {
  129. if (_tintColor != color)
  130. _tintColor = color;
  131. [self.offBackgroundView setBackgroundColor:color];
  132. }
  133. - (void)setTintBorderColor:(UIColor *)color
  134. {
  135. if (_tintBorderColor != color)
  136. _tintBorderColor = color;
  137. [self.offBackgroundView.layer setBorderColor:color.CGColor];
  138. if (color)
  139. [self.offBackgroundView.layer setBorderWidth:kSwitchBorderWidth];
  140. else
  141. [self.offBackgroundView.layer setBorderWidth:0.0];
  142. }
  143. - (void)setThumbTintColor:(UIColor *)color
  144. {
  145. if (_thumbTintColor != color)
  146. _thumbTintColor = color;
  147. [self.thumbView setBackgroundColor:color];
  148. }
  149. - (void)setShape:(CHSwitchShape)newShape
  150. {
  151. if (_shape != newShape)
  152. _shape = newShape;
  153. if (newShape == CHSwitchShapeOval)
  154. {
  155. [self.onBackgroundView.layer setCornerRadius:self.frame.size.height/2];
  156. [self.offBackgroundView.layer setCornerRadius:self.frame.size.height/2];
  157. [self.thumbView.layer setCornerRadius:(self.frame.size.height-kHorizontalAdjustment)/2];
  158. }
  159. else if (newShape == CHSwitchShapeRectangle)
  160. {
  161. [self.onBackgroundView.layer setCornerRadius:kRectShapeCornerRadius];
  162. [self.offBackgroundView.layer setCornerRadius:kRectShapeCornerRadius];
  163. [self.thumbView.layer setCornerRadius:kRectShapeCornerRadius];
  164. }
  165. else if (newShape == CHSwitchShapeRectangleNoCorner)
  166. {
  167. [self.onBackgroundView.layer setCornerRadius:0];
  168. [self.offBackgroundView.layer setCornerRadius:0];
  169. [self.thumbView.layer setCornerRadius:0];
  170. }
  171. }
  172. - (void)setShadow:(BOOL)showShadow
  173. {
  174. if (_shadow != showShadow)
  175. _shadow = showShadow;
  176. if (showShadow)
  177. {
  178. [self.thumbView.layer setShadowOffset:CGSizeMake(0, 1)];
  179. [self.thumbView.layer setShadowRadius:kThumbShadowRadius];
  180. [self.thumbView.layer setShadowOpacity:kThumbShadowOpacity];
  181. }
  182. else
  183. {
  184. [self.thumbView.layer setShadowRadius:0.0];
  185. [self.thumbView.layer setShadowOpacity:0.0];
  186. }
  187. }
  188. #pragma mark - Animation
  189. - (void)animateToDestination:(CGPoint)centerPoint withDuration:(CGFloat)duration switch:(BOOL)on
  190. {
  191. [UIView animateWithDuration:duration
  192. delay:0.0f
  193. options:UIViewAnimationOptionCurveEaseOut
  194. animations:^{
  195. self.thumbView.center = centerPoint;
  196. if (on)
  197. {
  198. [self.onBackgroundView setAlpha:1.0];
  199. }
  200. else
  201. {
  202. [self.onBackgroundView setAlpha:0.0];
  203. }
  204. }
  205. completion:^(BOOL finished) {
  206. if (finished)
  207. {
  208. [self updateSwitch:on];
  209. }
  210. }];
  211. [UIView animateWithDuration:duration
  212. delay:0.075f
  213. options:UIViewAnimationOptionCurveEaseOut
  214. animations:^{
  215. if (on)
  216. {
  217. self.offBackgroundView.transform = CGAffineTransformMakeScale(0.0, 0.0);
  218. }
  219. else
  220. {
  221. self.offBackgroundView.transform = CGAffineTransformMakeScale(1.0, 1.0);
  222. }
  223. }
  224. completion:^(BOOL finished) {
  225. }];
  226. }
  227. #pragma mark - Gesture Recognizers
  228. - (void)handlePan:(UIPanGestureRecognizer *)recognizer
  229. {
  230. CGPoint translation = [recognizer translationInView:self.thumbView];
  231. // Check the new center to see if within the boud
  232. CGPoint newCenter = CGPointMake(recognizer.view.center.x + translation.x,
  233. recognizer.view.center.y);
  234. if (newCenter.x < (recognizer.view.frame.size.width+kHorizontalAdjustment)/2 || newCenter.x > self.onBackgroundView.frame.size.width-(recognizer.view.frame.size.width+kHorizontalAdjustment)/2)
  235. {
  236. // New center is Out of bound. Animate to left or right position
  237. if(recognizer.state == UIGestureRecognizerStateBegan ||
  238. recognizer.state == UIGestureRecognizerStateChanged)
  239. {
  240. CGPoint velocity = [recognizer velocityInView:self.thumbView];
  241. if (velocity.x >= 0)
  242. {
  243. // Animate move to right
  244. [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
  245. }
  246. else
  247. {
  248. // Animate move to left
  249. [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
  250. }
  251. }
  252. return;
  253. }
  254. // Only allow vertical pan
  255. recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
  256. recognizer.view.center.y);
  257. [recognizer setTranslation:CGPointMake(0, 0) inView:self.thumbView];
  258. CGPoint velocity = [recognizer velocityInView:self.thumbView];
  259. if(recognizer.state == UIGestureRecognizerStateEnded)
  260. {
  261. if (velocity.x >= 0)
  262. {
  263. if (recognizer.view.center.x < self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2)
  264. {
  265. // Animate move to right
  266. [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
  267. }
  268. }
  269. else
  270. {
  271. // Animate move to left
  272. [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
  273. }
  274. }
  275. }
  276. - (void)handleSwitchTap:(UIPanGestureRecognizer *)recognizer
  277. {
  278. if (recognizer.state == UIGestureRecognizerStateEnded)
  279. {
  280. if (self.isOn)
  281. {
  282. // Animate move to left
  283. [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:NO];
  284. }
  285. else
  286. {
  287. // Animate move to right
  288. [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, recognizer.view.center.y) withDuration:kAnimateDuration switch:YES];
  289. }
  290. }
  291. }
  292. - (void)handleBgTap:(UIPanGestureRecognizer *)recognizer
  293. {
  294. if (recognizer.state == UIGestureRecognizerStateEnded)
  295. {
  296. if (self.isOn)
  297. {
  298. // Animate move to left
  299. [self animateToDestination:CGPointMake((self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:NO];
  300. }
  301. else
  302. {
  303. // Animate move to right
  304. [self animateToDestination:CGPointMake(self.onBackgroundView.frame.size.width - (self.thumbView.frame.size.width+kHorizontalAdjustment)/2, self.thumbView.center.y) withDuration:kAnimateDuration switch:YES];
  305. }
  306. }
  307. }
  308. #pragma mark -
  309. - (void)updateSwitch:(BOOL)on
  310. {
  311. if (_on != on)
  312. _on = on;
  313. [self sendActionsForControlEvents:UIControlEventValueChanged];
  314. }
  315. @end

可变大小、颜色边框、样式的UISwitch的更多相关文章

  1. Android CheckBox修改大小、边框颜色,以及自定义CheckBox;

    CheckBox修改大小: android:scaleX="0.8" android:scaleY="0.8" CheckBox修改边框颜色,注意不是背景色: ...

  2. css盒子模型之边框宽度,边框颜色与边框样式

    /* width和height只是设置盒子内容区的大小,而不是盒子的整个大小, 盒子可见框的大小由内容区,内边距和边框共同决定. */ .box1 { /* 设置内容区的宽度为400px */ wid ...

  3. css中的边框样式

    在盒子模型中,盒子的边框是其重要的样式,通过边框我们可以很方便地看出盒子的长宽以及大小.边框的特性可以通过边框线,边框的宽度及颜色来呈现. 1,边框线 边框线指的是边框线条的样式,包括实线,虚线,点划 ...

  4. css边框样式、边框配色、边框阴影、边框圆角、图片边框

     边框样式 点线式边框 破折线式边框 直线式边框 双线式边框 槽线式边框 脊线式边框 内嵌效果的边框 突起效果的边框 <div style="width: 300px; height: ...

  5. [转]CSS如何设置html table表格边框样式

    原文地址:http://www.divcss5.com/wenji/w503.shtml 对table设置css样式边框,分为几种情况: 1.只对table设置边框 2.对td设置边框 3.对tabl ...

  6. UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(二)

    上篇UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一) 讲到该控件的需要和设计过程. 这篇讲讲开发过程中一些重要问题解决. 1.支持 ...

  7. CSS3初学篇章_4(边框样式/段落样式)

    边框样式 1.边框线语法:border-style : none | hidden | dotted | dashed | solid | double | groove | ridge | inse ...

  8. 改变 Panel 跟 groupbox边框样式

    更改panel和groupbox的边框颜色因为在控件的属性中没有设置边框颜色的属性只有一个设置边框样式,遂在网络中搜寻出一下方法: panel的边框颜色在paint中重新对颜色进行定义 private ...

  9. CSS 边框样式

    CSS 边框样式 直线边框样式 <html> <body> <!-- border: 1px 边框像素为1.solid red 边框样式以及边框颜色 --> < ...

  10. python 输出颜色与样式的方法

    上次遇到这个问题就想写下来,其实当时我也不怎么会,老师说这个东西不需要理解,只需要死记硬背,写的多了就记住了,所以今天搜集了几篇文章,加上自己的理解,写下了这篇python 输出颜色的样式与方法的文章 ...

随机推荐

  1. Vue源码学习(一):调试环境搭建

    最近开始学习Vue源码,第一步就是要把调试环境搭好,这个过程遇到小坑着实费了点功夫,在这里记下来 一.调试环境搭建过程 1.安装node.js,具体不展开 2.下载vue项目源码,git或svn等均可 ...

  2. [原创]Spring boot 框架构建jsp web应用

    说明 Spring boot支持将web项目打包成一个可执行的jar包,内嵌tomcat服务器,独立部署 为支持jsp,则必须将项目打包为war包 pom.xml中设置打包方式 <packagi ...

  3. Scala语言简介和开发环境配置

    Scala语言的简介和开发环境搭建 Scala是一门结合了面向对象特征和函数式编程特征的语言,它是一个创新的编程语言产品.Scala可以做脚本(就像shell脚本一样),可以做服务端编程语言,可以写数 ...

  4. Mac hook—DYLD_INSERT_LIBRARIES

    [Mac hook—DYLD_INSERT_LIBRARIES] 1.gcc生成dylib. gcc -dynamiclib -o mysharedlib.dylib mysharedlib.c 2. ...

  5. java定时任务实现的几种方式(Timer、Spring Task、Quartz)

    Timer JDK自带的Timer类,允许调度一个TimerTask任务. Demo: /** * Timer测试类 */ public class TimerDemo { public static ...

  6. leetcode:Median of Two Sorted Arrays分析和实现

    这个问题的大意是提供两个有序的整数数组A与B,A与B并集的中间数.[1,3]与[2]的中间数为2,因为2能将A与B交集均分.而[1,3]与[2,4]的中间数为2.5,取2与3的平均值.故偶数数目的中间 ...

  7. WDCP/wdlinux安装php_zip扩展教程

    linux服务器安装wdcp之后,php的路径默认是/www/wdlinux/php,有些网友按照网上的教程安装的时候总出错,原因就是php的路径不对,我们知道了php的路径之后就可以开始安装了> ...

  8. 面试题: java多线程 背1

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

  9. Django框架 之 modelform组件

    Django框架 之 modelform组件 浏览目录 创建mldelform 添加记录 编辑记录 Django框架中的modelform组件 通过名字我们可以看出来,这个组件的功能就是把model和 ...

  10. 专题1-MMU-lesson3-MMU配置与使用

    1.段方式MMU 利用虚拟地址然后找到物理地址,通过物理地址访问到led,其过程如下: 一个段的大小是[19:0]总共有1M的地址空间. 从上面可知对应GPIO的段物理基地址是0x7f000000.那 ...