SWScannerView.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //
  2. // SWScannerView.m
  3. // SWQRCode_Objc
  4. //
  5. // Created by zhuku on 2018/4/8.
  6. // Copyright © 2018年 selwyn. All rights reserved.
  7. //
  8. #import "SWScannerView.h"
  9. #import "objc/runtime.h"
  10. #define Scanner_Width 0.7*self.frame.size.width /** 扫描器宽度 */
  11. #define Scanner_X (self.frame.size.width - Scanner_Width)/2 /** 扫描器初始x值 */
  12. #define Scanner_Y (self.frame.size.height - Scanner_Width)/2 - 50 /** 扫描器初始y值 */
  13. NSString *const ScannerLineAnmationKey = @"ScannerLineAnmationKey"; /** 扫描线条动画Key值 */
  14. CGFloat const Scanner_BorderWidth = 1.0f; /** 扫描器边框宽度 */
  15. CGFloat const Scanner_CornerWidth = 3.0f; /** 扫描器棱角宽度 */
  16. CGFloat const Scanner_CornerLength = 20.0f; /** 扫描器棱角长度 */
  17. CGFloat const Scanner_LineHeight = 10.0f; /** 扫描器线条高度 */
  18. CGFloat const FlashlightBtn_Height_ON = 29.0f; /** 手电筒按钮高度 */
  19. CGFloat const FlashlightBtn_Height_OFF = 24.0f; /** 手电筒按钮高度 */
  20. CGFloat const FlashlightBtn_Width = 20.0f; /** 手电筒按钮宽度 */
  21. CGFloat const FlashlightLab_Height = 15.0f; /** 手电筒提示文字高度 */
  22. CGFloat const TipLab_Height = 50.0f; /** 扫描器下方提示文字高度 */
  23. static char FLASHLIGHT_ON; /** 手电筒开关状态绑定标识符 */
  24. @interface SWScannerView()
  25. @property (nonatomic, strong) UIImageView *scannerLine; /** 扫描线条 */
  26. @property (nonatomic, strong) UIActivityIndicatorView *activityIndicator; /** 加载指示器 */
  27. @property (nonatomic, strong) UIButton *flashlightBtn; /** 手电筒开关 */
  28. @property (nonatomic, strong) UILabel *flashlightLab; /** 手电筒提示文字 */
  29. @property (nonatomic, strong) UILabel *tipLab; /** 扫描器下方提示文字 */
  30. @property (nonatomic, strong) SWQRCodeConfig *config;
  31. @end
  32. @implementation SWScannerView
  33. - (instancetype)initWithFrame:(CGRect)frame config:(SWQRCodeConfig *)config {
  34. self = [super initWithFrame:frame];
  35. if (self) {
  36. self.config = config;
  37. [self _setupUI];
  38. }
  39. return self;
  40. }
  41. - (void)_setupUI {
  42. self.backgroundColor = [UIColor clearColor];
  43. [self addSubview:self.scannerLine];
  44. [self sw_addScannerLineAnimation];
  45. [self addSubview:self.tipLab];
  46. [self addSubview:self.flashlightBtn];
  47. [self addSubview:self.flashlightLab];
  48. }
  49. #pragma mark -- 手电筒点击事件
  50. - (void)flashlightClicked:(UIButton *)button {
  51. button.selected = !button.selected;
  52. if (button.selected) {
  53. button.frame = CGRectMake((self.frame.size.width - FlashlightBtn_Width)/2, Scanner_Y + Scanner_Width - 15 - FlashlightLab_Height - FlashlightBtn_Height_ON, FlashlightBtn_Width, FlashlightBtn_Height_ON);
  54. } else {
  55. button.frame = CGRectMake((self.frame.size.width - FlashlightBtn_Width)/2, Scanner_Y + Scanner_Width - 15 - FlashlightLab_Height - FlashlightBtn_Height_OFF, FlashlightBtn_Width, FlashlightBtn_Height_OFF);
  56. }
  57. [self sw_setFlashlightOn:self.flashlightBtn.selected];
  58. }
  59. /** 添加扫描线条动画 */
  60. - (void)sw_addScannerLineAnimation {
  61. // 若已添加动画,则先移除动画再添加
  62. [self.scannerLine.layer removeAllAnimations];
  63. CABasicAnimation *lineAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
  64. lineAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, Scanner_Width - Scanner_LineHeight, 1)];
  65. lineAnimation.duration = 4;
  66. lineAnimation.repeatCount = HUGE;
  67. [self.scannerLine.layer addAnimation:lineAnimation forKey:ScannerLineAnmationKey];
  68. // 重置动画运行速度为1.0
  69. self.scannerLine.layer.speed = 1.0;
  70. }
  71. /** 暂停扫描器动画 */
  72. - (void)sw_pauseScannerLineAnimation {
  73. // 取出当前时间,转成动画暂停的时间
  74. CFTimeInterval pauseTime = [self.scannerLine.layer convertTime:CACurrentMediaTime() fromLayer:nil];
  75. // 设置动画的时间偏移量,指定时间偏移量的目的是让动画定格在该时间点的位置
  76. self.scannerLine.layer.timeOffset = pauseTime;
  77. // 将动画的运行速度设置为0, 默认的运行速度是1.0
  78. self.scannerLine.layer.speed = 0;
  79. }
  80. /** 显示手电筒 */
  81. - (void)sw_showFlashlightWithAnimated:(BOOL)animated {
  82. if (animated) {
  83. [UIView animateWithDuration:0.6 animations:^{
  84. self.flashlightLab.alpha = 1.0;
  85. self.flashlightBtn.alpha = 1.0;
  86. self.tipLab.alpha = 0;
  87. } completion:^(BOOL finished) {
  88. self.flashlightBtn.enabled = YES;
  89. }];
  90. }else
  91. {
  92. self.flashlightLab.alpha = 1.0;
  93. self.flashlightBtn.alpha = 1.0;
  94. self.tipLab.alpha = 0;
  95. self.flashlightBtn.enabled = YES;
  96. }
  97. }
  98. /** 隐藏手电筒 */
  99. - (void)sw_hideFlashlightWithAnimated:(BOOL)animated {
  100. self.flashlightBtn.enabled = NO;
  101. if (animated) {
  102. [UIView animateWithDuration:0.6 animations:^{
  103. self.flashlightLab.alpha = 0;
  104. self.flashlightBtn.alpha = 0;
  105. self.tipLab.alpha = 1.0;
  106. } completion:^(BOOL finished) {
  107. }];
  108. }else
  109. {
  110. self.tipLab.alpha = 1.0;
  111. self.flashlightLab.alpha = 0;
  112. self.flashlightBtn.alpha = 0;
  113. }
  114. }
  115. /** 添加指示器 */
  116. - (void)sw_addActivityIndicator {
  117. if (!self.activityIndicator) {
  118. self.activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:self.config.indicatorViewStyle];
  119. self.activityIndicator.center = self.center;
  120. [self addSubview:self.activityIndicator];
  121. }
  122. [self.activityIndicator startAnimating];
  123. }
  124. /** 移除指示器 */
  125. - (void)sw_removeActivityIndicator {
  126. if (self.activityIndicator) {
  127. [self.activityIndicator removeFromSuperview];
  128. self.activityIndicator = nil;
  129. }
  130. }
  131. /** 设置手电筒开关 */
  132. - (void)sw_setFlashlightOn:(BOOL)on {
  133. [SWQRCodeManager sw_FlashlightOn:on];
  134. self.flashlightLab.text = on ? @"轻点关闭":@"轻点照亮";
  135. self.flashlightBtn.selected = on;
  136. objc_setAssociatedObject(self, &FLASHLIGHT_ON, @(on), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  137. }
  138. /** 获取手电筒当前开关状态 */
  139. - (BOOL)sw_flashlightOn {
  140. return [objc_getAssociatedObject(self, &FLASHLIGHT_ON) boolValue];
  141. }
  142. - (void)drawRect:(CGRect)rect {
  143. [super drawRect:rect];
  144. // 半透明区域
  145. [[UIColor colorWithWhite:0 alpha:0.7] setFill];
  146. UIRectFill(rect);
  147. // 透明区域
  148. CGRect scanner_rect = CGRectMake(Scanner_X, Scanner_Y, Scanner_Width, Scanner_Width);
  149. [[UIColor clearColor] setFill];
  150. UIRectFill(scanner_rect);
  151. // 边框
  152. UIBezierPath *borderPath = [UIBezierPath bezierPathWithRect:CGRectMake(Scanner_X, Scanner_Y, Scanner_Width, Scanner_Width)];
  153. borderPath.lineCapStyle = kCGLineCapRound;
  154. borderPath.lineWidth = Scanner_BorderWidth;
  155. [self.config.scannerBorderColor set];
  156. [borderPath stroke];
  157. for (int index = 0; index < 4; ++index) {
  158. UIBezierPath *tempPath = [UIBezierPath bezierPath];
  159. tempPath.lineWidth = Scanner_CornerWidth;
  160. [self.config.scannerCornerColor set];
  161. switch (index) {
  162. // 左上角棱角
  163. case 0:
  164. {
  165. [tempPath moveToPoint:CGPointMake(Scanner_X + Scanner_CornerLength, Scanner_Y)];
  166. [tempPath addLineToPoint:CGPointMake(Scanner_X, Scanner_Y)];
  167. [tempPath addLineToPoint:CGPointMake(Scanner_X, Scanner_Y + Scanner_CornerLength)];
  168. }
  169. break;
  170. // 右上角
  171. case 1:
  172. {
  173. [tempPath moveToPoint:CGPointMake(Scanner_X + Scanner_Width - Scanner_CornerLength, Scanner_Y)];
  174. [tempPath addLineToPoint:CGPointMake(Scanner_X + Scanner_Width, Scanner_Y)];
  175. [tempPath addLineToPoint:CGPointMake(Scanner_X + Scanner_Width, Scanner_Y + Scanner_CornerLength)];
  176. }
  177. break;
  178. // 左下角
  179. case 2:
  180. {
  181. [tempPath moveToPoint:CGPointMake(Scanner_X, Scanner_Y + Scanner_Width - Scanner_CornerLength)];
  182. [tempPath addLineToPoint:CGPointMake(Scanner_X, Scanner_Y + Scanner_Width)];
  183. [tempPath addLineToPoint:CGPointMake(Scanner_X + Scanner_CornerLength, Scanner_Y + Scanner_Width)];
  184. }
  185. break;
  186. // 右下角
  187. case 3:
  188. {
  189. [tempPath moveToPoint:CGPointMake(Scanner_X + Scanner_Width - Scanner_CornerLength, Scanner_Y + Scanner_Width)];
  190. [tempPath addLineToPoint:CGPointMake(Scanner_X + Scanner_Width, Scanner_Y + Scanner_Width)];
  191. [tempPath addLineToPoint:CGPointMake(Scanner_X + Scanner_Width, Scanner_Y + Scanner_Width - Scanner_CornerLength)];
  192. }
  193. break;
  194. default:
  195. break;
  196. }
  197. [tempPath stroke];
  198. }
  199. }
  200. - (CGFloat)scanner_x {
  201. return Scanner_X;
  202. }
  203. - (CGFloat)scanner_y {
  204. return Scanner_Y;
  205. }
  206. - (CGFloat)scanner_width {
  207. return Scanner_Width;
  208. }
  209. /** 扫描线条 */
  210. - (UIImageView *)scannerLine {
  211. if (!_scannerLine) {
  212. _scannerLine = [[UIImageView alloc]initWithFrame:CGRectMake(Scanner_X, Scanner_Y, Scanner_Width, Scanner_LineHeight)];
  213. _scannerLine.image = [UIImage imageNamed:@"SWQRCode.bundle/ScannerLine"];
  214. }
  215. return _scannerLine;
  216. }
  217. /** 扫描器下方提示文字 */
  218. - (UILabel *)tipLab {
  219. if (!_tipLab) {
  220. _tipLab = [[UILabel alloc]initWithFrame:CGRectMake(0, Scanner_Y + Scanner_Width, self.frame.size.width, 50)];
  221. _tipLab.textAlignment = NSTextAlignmentCenter;
  222. _tipLab.textColor = [UIColor lightGrayColor];
  223. _tipLab.text = @"将二维码/条码放入框内,即可自动扫描";
  224. _tipLab.font = [UIFont systemFontOfSize:12];
  225. }
  226. return _tipLab;
  227. }
  228. /** 手电筒开关 */
  229. - (UIButton *)flashlightBtn {
  230. if (!_flashlightBtn) {
  231. _flashlightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  232. _flashlightBtn.frame = CGRectMake((self.frame.size.width - FlashlightBtn_Width)/2, Scanner_Y + Scanner_Width - 15 - FlashlightLab_Height - FlashlightBtn_Height_OFF, FlashlightBtn_Width, FlashlightBtn_Height_OFF);
  233. _flashlightBtn.enabled = NO;
  234. _flashlightBtn.alpha = 0;
  235. [_flashlightBtn addTarget:self action:@selector(flashlightClicked:) forControlEvents:UIControlEventTouchUpInside];
  236. [_flashlightBtn setBackgroundImage:[UIImage imageNamed:@"SWQRCode.bundle/Flashlight_Off"] forState:UIControlStateNormal];
  237. [_flashlightBtn setBackgroundImage:[UIImage imageNamed:@"SWQRCode.bundle/Flashlight_On"] forState:UIControlStateSelected];
  238. }
  239. return _flashlightBtn;
  240. }
  241. /** 手电筒提示文字 */
  242. - (UILabel *)flashlightLab {
  243. if (!_flashlightLab) {
  244. _flashlightLab = [[UILabel alloc]initWithFrame:CGRectMake(Scanner_X, Scanner_Y + Scanner_Width - 10 - FlashlightLab_Height, Scanner_Width, FlashlightLab_Height)];
  245. _flashlightLab.font = [UIFont systemFontOfSize:12];
  246. _flashlightLab.textColor = [UIColor whiteColor];
  247. _flashlightLab.text = @"轻点照亮";
  248. _flashlightLab.alpha = 0;
  249. _flashlightLab.textAlignment = NSTextAlignmentCenter;
  250. }
  251. return _flashlightLab;
  252. }
  253. @end