KZVideoSupport.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. //
  2. // KZVideoSupport.m
  3. // KZWeChatSmallVideo_OC
  4. //
  5. // Created by HouKangzhu on 16/7/19.
  6. // Copyright © 2016年 侯康柱. All rights reserved.
  7. //
  8. #import "KZVideoSupport.h"
  9. #import "KZVideoConfig.h"
  10. #pragma mark - Custom View --
  11. @implementation KZStatusBar {
  12. BOOL _clear;
  13. CAShapeLayer *_nomalLayer;
  14. CALayer *_recodingLayer;
  15. KZVideoViewShowType _style;
  16. UIButton *_cancelBtn;
  17. }
  18. - (instancetype)initWithFrame:(CGRect)frame style:(KZVideoViewShowType)style; {
  19. if (self = [super initWithFrame:frame]) {
  20. _style = style;
  21. //[KZVideoConfig motionBlurView:self];
  22. self.backgroundColor = [UIColor clearColor];
  23. [self setupSubLayers];
  24. }
  25. return self;
  26. }
  27. - (void)addCancelTarget:(id)target selector:(SEL)selector {
  28. [_cancelBtn removeFromSuperview];
  29. _cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  30. _cancelBtn.frame = CGRectMake(10, 22, 50, 40);
  31. [_cancelBtn setTitle:WFCString(@"Cancel") forState:UIControlStateNormal];
  32. [_cancelBtn addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
  33. [_cancelBtn setTitleColor:kzThemeTineColor forState:UIControlStateNormal];
  34. _cancelBtn.alpha = 0.8;
  35. _cancelBtn.backgroundColor = [UIColor clearColor];
  36. [self addSubview:_cancelBtn];
  37. }
  38. - (void)setupSubLayers {
  39. if (_style == KZVideoViewShowTypeSingle) {
  40. return;
  41. }
  42. UIView *showView = [[UIView alloc] initWithFrame:self.bounds];
  43. showView.backgroundColor = [UIColor clearColor];
  44. [self addSubview:showView];
  45. CGAffineTransform transform = CGAffineTransformIdentity;
  46. CGFloat barW = 20.0;
  47. CGFloat barSpace = 4.0;
  48. CGFloat topEdge = 5.5;
  49. CGPoint selfCent = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
  50. CGMutablePathRef nomalPath = CGPathCreateMutable();
  51. for (int i=0; i<3; i++) {
  52. CGPathMoveToPoint(nomalPath, &transform, selfCent.x-(barW/2), topEdge+(barSpace * i));
  53. CGPathAddLineToPoint(nomalPath, &transform, selfCent.x+(barW/2), topEdge+(barSpace * i));
  54. }
  55. _nomalLayer = [CAShapeLayer layer];
  56. _nomalLayer.frame = self.bounds;
  57. _nomalLayer.strokeColor = [UIColor colorWithRed: 0.5 green: 0.5 blue: 0.5 alpha: 0.7 ].CGColor;
  58. _nomalLayer.lineCap = kCALineCapRound;
  59. _nomalLayer.lineWidth = 2.0;
  60. _nomalLayer.path = nomalPath;
  61. [showView.layer addSublayer:_nomalLayer];
  62. CGPathRelease(nomalPath);
  63. CGFloat width = 10;
  64. CGFloat height = 8;
  65. _recodingLayer = [CALayer layer];
  66. _recodingLayer.frame = CGRectMake(selfCent.x - width/2, selfCent.y - height/2, width, height);
  67. _recodingLayer.cornerRadius = height/2;
  68. _recodingLayer.masksToBounds = YES;
  69. _recodingLayer.backgroundColor = kzThemeWaringColor.CGColor;
  70. [showView.layer addSublayer:_recodingLayer];
  71. _recodingLayer.hidden = YES;
  72. }
  73. - (void)setIsRecoding:(BOOL)isRecoding {
  74. _isRecoding = isRecoding;
  75. [self display];
  76. }
  77. - (void)display {
  78. if (_style == KZVideoViewShowTypeSingle) {
  79. return;
  80. }
  81. if (_isRecoding) {
  82. _recodingLayer.hidden = NO;
  83. _nomalLayer.hidden = YES;
  84. kz_dispatch_after(0.5, ^{
  85. if (!_isRecoding) return;
  86. _recodingLayer.hidden = YES;
  87. _nomalLayer.hidden = YES;
  88. });
  89. }
  90. else {
  91. _nomalLayer.hidden = NO;
  92. _recodingLayer.hidden = YES;
  93. }
  94. }
  95. @end
  96. @implementation KZCloseBtn
  97. - (void)setGradientColors:(NSArray *)gradientColors {
  98. self.backgroundColor = [UIColor clearColor];
  99. _gradientColors = gradientColors;
  100. CAShapeLayer *trackLayer = [CAShapeLayer layer];
  101. trackLayer.frame = self.bounds;
  102. trackLayer.strokeColor = kzThemeTineColor.CGColor;
  103. trackLayer.fillColor = [UIColor clearColor].CGColor;
  104. trackLayer.lineCap = kCALineCapRound;
  105. trackLayer.lineWidth = 3.0;
  106. CGMutablePathRef path = [self getDrawPath];
  107. trackLayer.path = path;
  108. [self.layer addSublayer:trackLayer];
  109. CGPathRelease(path);
  110. CAGradientLayer *maskLayer = [CAGradientLayer layer];
  111. maskLayer.frame = self.bounds;
  112. maskLayer.colors = _gradientColors;
  113. [self.layer addSublayer:maskLayer];
  114. maskLayer.mask = trackLayer;
  115. [self setNeedsDisplay];
  116. }
  117. - (void)drawRect:(CGRect)rect {
  118. [super drawRect:rect];
  119. if (_gradientColors != nil) {
  120. return;
  121. }
  122. CGContextRef context = UIGraphicsGetCurrentContext();
  123. CGContextSetAllowsAntialiasing(context, YES);
  124. CGContextSetStrokeColorWithColor(context, kzThemeGraryColor.CGColor);
  125. CGContextSetLineWidth(context, 3.0);
  126. CGContextSetLineCap(context, kCGLineCapRound);
  127. CGMutablePathRef path = [self getDrawPath];
  128. CGContextAddPath(context, path);
  129. CGContextDrawPath(context, kCGPathStroke);
  130. CGPathRelease(path);
  131. }
  132. - (CGMutablePathRef)getDrawPath {
  133. CGMutablePathRef path = CGPathCreateMutable();
  134. CGFloat centX = self.bounds.size.width/2;
  135. CGFloat centY = self.bounds.size.height/2;
  136. CGFloat drawWidth = 22;
  137. CGFloat drawHeight = 10;
  138. CGPathMoveToPoint(path, NULL, (centX - drawWidth/2), (centY - drawHeight/2));
  139. CGPathAddLineToPoint(path, NULL, centX, centY + drawHeight/2);
  140. CGPathAddLineToPoint(path, NULL, centX + drawWidth/2, centY - drawHeight/2);
  141. return path;
  142. }
  143. @end
  144. @implementation KZRecordBtn {
  145. UITapGestureRecognizer *_tapGesture;
  146. KZVideoViewShowType _style;
  147. }
  148. - (instancetype)initWithFrame:(CGRect)frame style:(KZVideoViewShowType)style{
  149. if (self = [super initWithFrame:frame]) {
  150. _style = style;
  151. [self setupRoundButton];
  152. // self.backgroundColor = [UIColor whiteColor];
  153. self.layer.cornerRadius = self.bounds.size.width/2;
  154. self.layer.masksToBounds = YES;
  155. // self.layer.borderWidth = 0.5f;
  156. // self.layer.borderColor = [[UIColor blackColor] CGColor];
  157. self.userInteractionEnabled = YES;
  158. }
  159. return self;
  160. }
  161. - (void)setupRoundButton {
  162. self.backgroundColor = [UIColor clearColor];
  163. CGFloat width = self.frame.size.width;
  164. UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:width/2];
  165. CAShapeLayer *trackLayer = [CAShapeLayer layer];
  166. trackLayer.frame = self.bounds;
  167. trackLayer.strokeColor = kzThemeTineColor.CGColor;
  168. trackLayer.fillColor = [UIColor clearColor].CGColor;
  169. trackLayer.opacity = 1.0;
  170. trackLayer.lineCap = kCALineCapRound;
  171. trackLayer.lineWidth = 2.0;
  172. trackLayer.path = path.CGPath;
  173. [self.layer addSublayer:trackLayer];
  174. if (_style == KZVideoViewShowTypeSingle) {
  175. CATextLayer *textLayer = [CATextLayer layer];
  176. textLayer.string = @"按住拍";
  177. textLayer.frame = CGRectMake(0, 0, 120, 30);
  178. textLayer.position = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
  179. UIFont *font = [UIFont boldSystemFontOfSize:22];
  180. CFStringRef fontName = (__bridge CFStringRef)font.fontName;
  181. CGFontRef fontRef = CGFontCreateWithFontName(fontName);
  182. textLayer.font = fontRef;
  183. textLayer.fontSize = font.pointSize;
  184. CGFontRelease(fontRef);
  185. textLayer.contentsScale = [UIScreen mainScreen].scale;
  186. textLayer.foregroundColor = kzThemeTineColor.CGColor;
  187. textLayer.alignmentMode = kCAAlignmentCenter;
  188. textLayer.wrapped = YES;
  189. [trackLayer addSublayer:textLayer];
  190. }
  191. CAGradientLayer *gradLayer = [CAGradientLayer layer];
  192. gradLayer.frame = self.bounds;
  193. gradLayer.colors = [KZVideoConfig gradualColors];
  194. [self.layer addSublayer:gradLayer];
  195. gradLayer.mask = trackLayer;
  196. }
  197. @end
  198. @implementation KZFocusView {
  199. CGFloat _width;
  200. CGFloat _height;
  201. }
  202. - (instancetype)initWithFrame:(CGRect)frame {
  203. if (self = [super initWithFrame:frame]) {
  204. _width = CGRectGetWidth(frame);
  205. _height = _width;
  206. }
  207. return self;
  208. }
  209. - (void)focusing {
  210. [UIView animateWithDuration:0.5 animations:^{
  211. self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
  212. } completion:^(BOOL finished) {
  213. self.transform = CGAffineTransformIdentity;
  214. }];
  215. }
  216. - (void)drawRect:(CGRect)rect {
  217. [super drawRect:rect];
  218. CGContextRef context = UIGraphicsGetCurrentContext();
  219. CGContextSetStrokeColorWithColor(context, kzThemeTineColor.CGColor);
  220. CGContextSetLineWidth(context, 1.0);
  221. CGFloat len = 4;
  222. CGContextMoveToPoint(context, 0.0, 0.0);
  223. CGContextAddRect(context, self.bounds);
  224. CGContextMoveToPoint(context, 0, _height/2);
  225. CGContextAddLineToPoint(context, len, _height/2);
  226. CGContextMoveToPoint(context, _width/2, _height);
  227. CGContextAddLineToPoint(context, _width/2, _height - len);
  228. CGContextMoveToPoint(context, _width, _height/2);
  229. CGContextAddLineToPoint(context, _width - len, _height/2);
  230. CGContextMoveToPoint(context, _width/2, 0);
  231. CGContextAddLineToPoint(context, _width/2, len);
  232. CGContextDrawPath(context, kCGPathStroke);
  233. }
  234. @end
  235. @implementation KZEyeView
  236. - (instancetype)initWithFrame:(CGRect)frame {
  237. if (self = [super initWithFrame:frame]) {
  238. [KZVideoConfig motionBlurView:self];
  239. [self setupView];
  240. }
  241. return self;
  242. }
  243. - (instancetype)initWithCoder:(NSCoder *)aDecoder {
  244. if (self = [super initWithCoder:aDecoder]) {
  245. [self layoutIfNeeded];
  246. [KZVideoConfig motionBlurView:self];
  247. [self setupView];
  248. }
  249. return self;
  250. }
  251. - (void)setupView {
  252. UIView *view = [[UIView alloc] initWithFrame:self.bounds];
  253. view.backgroundColor = [UIColor clearColor];
  254. [self addSubview:view];
  255. KZEyePath path = createEyePath(self.bounds);
  256. UIColor *color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.9];
  257. CAShapeLayer *shapelayer1 = [CAShapeLayer layer];
  258. shapelayer1.frame = self.bounds;
  259. shapelayer1.strokeColor = color.CGColor;
  260. shapelayer1.fillColor = [UIColor clearColor].CGColor;
  261. shapelayer1.opacity = 1.0;
  262. shapelayer1.lineCap = kCALineCapRound;
  263. shapelayer1.lineWidth = 1.0;
  264. shapelayer1.path = path.strokePath;
  265. [view.layer addSublayer:shapelayer1];
  266. CAShapeLayer *shapelayer2 = [CAShapeLayer layer];
  267. shapelayer2.frame = self.bounds;
  268. shapelayer2.strokeColor = color.CGColor;
  269. shapelayer2.fillColor = color.CGColor;
  270. shapelayer2.opacity = 1.0;
  271. shapelayer2.lineCap = kCALineCapRound;
  272. shapelayer2.lineWidth = 1.0;
  273. shapelayer2.path = path.fillPath;
  274. [view.layer addSublayer:shapelayer2];
  275. KZEyePathRelease(path);
  276. }
  277. /*
  278. - (void)drawRect:(CGRect)rect {
  279. [super drawRect:rect];
  280. return;
  281. KZEyePath path = createEyePath(self.bounds);
  282. CGContextRef context = UIGraphicsGetCurrentContext();
  283. UIColor *color = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.9];
  284. [color setStroke];
  285. [color setFill];
  286. CGContextSetLineWidth(context, 1.0);
  287. CGContextSetLineCap(context, kCGLineCapRound);
  288. CGContextAddPath(context, path.strokePath);
  289. CGContextDrawPath(context, kCGPathStroke);
  290. CGContextAddPath(context, path.fillPath);
  291. CGContextDrawPath(context, kCGPathFillStroke);
  292. KZEyePathRelease(path);
  293. }
  294. */
  295. typedef struct eyePath {
  296. CGMutablePathRef strokePath;
  297. CGMutablePathRef fillPath;
  298. } KZEyePath;
  299. void KZEyePathRelease(KZEyePath path) {
  300. CGPathRelease(path.fillPath);
  301. CGPathRelease(path.strokePath);
  302. }
  303. KZEyePath createEyePath(CGRect rect) {
  304. CGPoint selfCent = CGPointMake(CGRectGetWidth(rect)/2, CGRectGetHeight(rect)/2);
  305. CGFloat eyeWidth = 64.0;
  306. CGFloat eyeHeight = 40.0;
  307. CGFloat curveCtrlH = 44;
  308. CGAffineTransform transform = CGAffineTransformMakeScale(1.0, 1.0);
  309. CGMutablePathRef path = CGPathCreateMutable();
  310. CGPathMoveToPoint(path, &transform, selfCent.x - eyeWidth/2, selfCent.y);
  311. CGPathAddQuadCurveToPoint(path, &transform, selfCent.x, selfCent.y - curveCtrlH, selfCent.x + eyeWidth/2, selfCent.y);
  312. CGPathAddQuadCurveToPoint(path, &transform, selfCent.x, selfCent.y + curveCtrlH, selfCent.x - eyeWidth/2, selfCent.y);
  313. CGFloat arcRadius = eyeHeight/2 - 1;
  314. CGPathMoveToPoint(path, &transform, selfCent.x + arcRadius, selfCent.y);
  315. CGPathAddArc(path, &transform, selfCent.x, selfCent.y, arcRadius, 0, M_PI * 2, false);
  316. CGFloat startAngle = 110;
  317. CGFloat angle1 = startAngle + 30;
  318. CGFloat angle2 = angle1 + 20;
  319. CGFloat angle3 = angle2 + 10;
  320. CGFloat arcRadius2 = arcRadius - 4;
  321. CGFloat arcRadius3 = arcRadius2 - 7;
  322. CGMutablePathRef path2 = createDonutPath(selfCent, angleToRadian(startAngle), angleToRadian(angle1), arcRadius2, arcRadius3, &transform);
  323. CGMutablePathRef path3 = createDonutPath(selfCent, angleToRadian(angle2), angleToRadian(angle3), arcRadius2, arcRadius3, &transform);
  324. CGPathAddPath(path2, NULL, path3);
  325. CGPathRelease(path3);
  326. return (KZEyePath){path, path2};
  327. }
  328. // angle 逆时针角度
  329. CGMutablePathRef createDonutPath(CGPoint center, CGFloat startAngle, CGFloat endAngle, CGFloat bigRadius, CGFloat smallRadius, CGAffineTransform * transform) {
  330. CGFloat arcStart = M_PI*2 - startAngle;
  331. CGFloat arcEnd = M_PI*2 - endAngle;
  332. CGMutablePathRef path = CGPathCreateMutable();
  333. CGPathMoveToPoint(path, transform, center.x + bigRadius * cos(startAngle), center.y - bigRadius * sin(startAngle));
  334. CGPathAddArc(path, transform, center.x, center.y, bigRadius, arcStart, arcEnd, true);
  335. CGPathAddLineToPoint(path, transform, center.x + smallRadius * cos(endAngle), center.y - smallRadius * sin(endAngle));
  336. CGPathAddArc(path, transform, center.x, center.y, smallRadius, arcEnd, arcStart, false);
  337. CGPathAddLineToPoint(path, transform, center.x + bigRadius * cos(startAngle), center.y - bigRadius * sin(startAngle));
  338. return path;
  339. }
  340. double kz_sin(double angle) {
  341. return sin(angleToRadian(angle));
  342. }
  343. double kz_cos(double angle) {
  344. return cos(angleToRadian(angle));
  345. }
  346. CGFloat angleToRadian(CGFloat angle) {
  347. return angle/180.0*M_PI;
  348. }
  349. @end
  350. #pragma mark -------------- 分割线 --------------------------
  351. @implementation KZControllerBar {
  352. KZRecordBtn *_startBtn;
  353. UILongPressGestureRecognizer *_longPress;
  354. UIView *_progressLine;
  355. BOOL _touchIsInside;
  356. BOOL _recording;
  357. NSTimer *_timer;
  358. NSTimeInterval _surplusTime;
  359. UIButton *_videoListBtn;
  360. KZCloseBtn *_closeVideoBtn;
  361. BOOL _videoDidEnd;
  362. }
  363. - (void)setupSubViewsWithStyle:(KZVideoViewShowType)style {
  364. [self layoutIfNeeded];
  365. // [KZVideoConfig motionBlurView:self];
  366. CGFloat selfHeight = self.bounds.size.height;
  367. CGFloat selfWidth = self.bounds.size.width;
  368. CGFloat edge = 20.0;
  369. CGFloat startBtnWidth = style == KZVideoViewShowTypeSmall ? selfHeight - (edge * 2) : selfHeight/2;
  370. _startBtn = [[KZRecordBtn alloc] initWithFrame:CGRectMake(0, 0, startBtnWidth, startBtnWidth) style:style];
  371. _startBtn.center = CGPointMake(selfWidth/2, selfHeight/2);
  372. [self addSubview:_startBtn];
  373. _longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longpressAction:)];
  374. // _longPress.minimumPressDuration = 0.01;
  375. _longPress.delegate = self;
  376. [self addGestureRecognizer:_longPress];
  377. [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)]];
  378. _progressLine = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - 8, selfWidth, 4)];
  379. _progressLine.backgroundColor = kzThemeTineColor;
  380. _progressLine.hidden = YES;
  381. [self addSubview:_progressLine];
  382. _surplusTime = kzRecordTime;
  383. if (style == KZVideoViewShowTypeSingle) {
  384. return;
  385. }
  386. _videoListBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  387. _videoListBtn.frame = CGRectMake(edge, edge+startBtnWidth/6, startBtnWidth/4*3, startBtnWidth/3*2);
  388. _videoListBtn.layer.cornerRadius = 8;
  389. _videoListBtn.imageView.contentMode = UIViewContentModeScaleAspectFill;
  390. _videoListBtn.layer.masksToBounds = YES;
  391. [_videoListBtn addTarget:self action:@selector(videoListAction) forControlEvents:UIControlEventTouchUpInside];
  392. // self.videoListBtn.backgroundColor = kzThemeTineColor
  393. [self addSubview:_videoListBtn];
  394. NSArray<KZVideoModel *> *videoList = [KZVideoUtil getSortVideoList];
  395. if (videoList.count == 0) {
  396. _videoListBtn.hidden = YES;
  397. }
  398. else {
  399. [_videoListBtn setBackgroundImage:[UIImage imageWithContentsOfFile:videoList[0].thumAbsolutePath] forState: UIControlStateNormal];
  400. }
  401. CGFloat closeBtnWidth = _videoListBtn.frame.size.height;
  402. _closeVideoBtn = [KZCloseBtn buttonWithType:UIButtonTypeCustom];
  403. _closeVideoBtn.frame = CGRectMake(self.bounds.size.width - closeBtnWidth - edge, CGRectGetMinY(_videoListBtn.frame), closeBtnWidth, closeBtnWidth);
  404. [_closeVideoBtn addTarget:self action:@selector(videoCloseAction) forControlEvents:UIControlEventTouchUpInside];
  405. [self addSubview:_closeVideoBtn];
  406. [self setBackgroundColor:[UIColor clearColor]];
  407. }
  408. - (void)startRecordSet {
  409. _startBtn.alpha = 1.0;
  410. _progressLine.frame = CGRectMake(0, self.bounds.size.height - 8, self.bounds.size.width, 4);
  411. _progressLine.backgroundColor = kzThemeTineColor;
  412. _progressLine.hidden = NO;
  413. _surplusTime = kzRecordTime;
  414. _recording = YES;
  415. _videoDidEnd = NO;
  416. if (_timer == nil) {
  417. _timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(recordTimerAction) userInfo:nil repeats:YES];
  418. [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
  419. }
  420. [_timer fire];
  421. [UIView animateWithDuration:0.4 animations:^{
  422. _startBtn.alpha = 0.0;
  423. _startBtn.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2.0, 2.0);
  424. } completion:^(BOOL finished) {
  425. if (finished) {
  426. _startBtn.transform = CGAffineTransformIdentity;
  427. }
  428. }];
  429. }
  430. - (void)endRecordSet {
  431. _progressLine.hidden = YES;
  432. [_timer invalidate];
  433. _timer = nil;
  434. _recording = NO;
  435. _startBtn.alpha = 1;
  436. }
  437. #pragma mark - UIGestureRecognizerDelegate
  438. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  439. if (gestureRecognizer == _longPress) {
  440. if (_surplusTime <= 0) return NO;
  441. CGPoint point = [gestureRecognizer locationInView:self];
  442. CGPoint startBtnCent = _startBtn.center;
  443. CGFloat dx = point.x - startBtnCent.x;
  444. CGFloat dy = point.y - startBtnCent.y;
  445. CGFloat startWidth = _startBtn.bounds.size.width;
  446. if ((dx * dx) + (dy * dy) < (startWidth * startWidth)) {
  447. return YES;
  448. }
  449. return NO;
  450. }
  451. return YES;
  452. }
  453. #pragma mark - Actions --
  454. - (void)longpressAction:(UILongPressGestureRecognizer *)gesture {
  455. CGPoint point = [gesture locationInView:self];
  456. _touchIsInside = point.y >= 0;
  457. switch (gesture.state) {
  458. case UIGestureRecognizerStateBegan: {
  459. [self videoStartAction];
  460. }
  461. break;
  462. case UIGestureRecognizerStateChanged: {
  463. if (!_touchIsInside) {
  464. _progressLine.backgroundColor = kzThemeWaringColor;
  465. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoWillCancel:)]) {
  466. [_delegate ctrollVideoWillCancel:self];
  467. }
  468. }
  469. else {
  470. _progressLine.backgroundColor = kzThemeTineColor;
  471. }
  472. }
  473. break;
  474. case UIGestureRecognizerStateEnded: {
  475. [self endRecordSet];
  476. if (!_touchIsInside || kzRecordTime - _surplusTime <= 1) {
  477. KZRecordCancelReason reason = KZRecordCancelReasonTimeShort;
  478. if (!_touchIsInside) {
  479. reason = KZRecordCancelReasonDefault;
  480. }
  481. [self videoCancelAction:reason];
  482. }
  483. else {
  484. [self videoEndAction];
  485. }
  486. }
  487. break;
  488. case UIGestureRecognizerStateCancelled:
  489. break;
  490. default:
  491. break;
  492. }
  493. }
  494. - (void)tapAction:(id)sender {
  495. if (_delegate && [_delegate respondsToSelector:@selector(ctrollImageDidCapture:)]) {
  496. [_delegate ctrollImageDidCapture:self];
  497. }
  498. }
  499. - (void)videoStartAction {
  500. [self startRecordSet];
  501. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoDidStart:)]) {
  502. [_delegate ctrollVideoDidStart:self];
  503. }
  504. }
  505. - (void)videoCancelAction:(KZRecordCancelReason)reason {
  506. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoDidCancel:reason:)]) {
  507. [_delegate ctrollVideoDidCancel:self reason:reason];
  508. }
  509. }
  510. - (void)videoEndAction {
  511. if (_videoDidEnd) return;
  512. _videoDidEnd = YES;
  513. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoDidEnd:)]) {
  514. [_delegate ctrollVideoDidEnd:self];
  515. }
  516. }
  517. - (void)videoListAction {
  518. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoOpenVideoList:)]) {
  519. [_delegate ctrollVideoOpenVideoList:self];
  520. }
  521. }
  522. - (void)videoCloseAction {
  523. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoDidClose:)]) {
  524. [_delegate ctrollVideoDidClose:self];
  525. }
  526. }
  527. - (void)recordTimerAction {
  528. CGFloat reduceLen = self.bounds.size.width/kzRecordTime;
  529. CGFloat oldLineLen = _progressLine.frame.size.width;
  530. CGRect oldFrame = _progressLine.frame;
  531. [UIView animateWithDuration:1.0 delay: 0.0 options: UIViewAnimationOptionCurveLinear animations:^{
  532. _progressLine.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldLineLen - reduceLen, oldFrame.size.height);
  533. _progressLine.center = CGPointMake(self.bounds.size.width/2, oldFrame.origin.y-2);
  534. } completion:^(BOOL finished) {
  535. _surplusTime --;
  536. if (_recording) {
  537. if (_delegate && [_delegate respondsToSelector:@selector(ctrollVideoDidRecordSEC:)]) {
  538. [_delegate ctrollVideoDidRecordSEC:self];
  539. }
  540. }
  541. if (_surplusTime <= 0.0) {
  542. [self endRecordSet];
  543. [self videoEndAction];
  544. }
  545. }];
  546. }
  547. @end
  548. #pragma mark - ********************** Video List 控件 ************************
  549. @implementation KZCircleCloseBtn
  550. - (void)drawRect:(CGRect)rect {
  551. [super drawRect:rect];
  552. self.layer.backgroundColor = [UIColor whiteColor].CGColor;
  553. self.layer.cornerRadius = self.bounds.size.width/2;
  554. self.layer.masksToBounds = YES;
  555. CGContextRef context = UIGraphicsGetCurrentContext();
  556. CGContextSetAllowsAntialiasing(context, YES);
  557. CGContextSetStrokeColorWithColor(context, kzThemeBlackColor.CGColor);
  558. CGContextSetLineWidth(context, 1.0);
  559. CGContextSetLineCap(context, kCGLineCapRound);
  560. CGPoint selfCent = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
  561. CGFloat closeWidth = 8.0;
  562. CGContextMoveToPoint(context, selfCent.x-closeWidth/2, selfCent.y - closeWidth/2);
  563. CGContextAddLineToPoint(context, selfCent.x + closeWidth/2, selfCent.y + closeWidth/2);
  564. CGContextMoveToPoint(context, selfCent.x-closeWidth/2, selfCent.y + closeWidth/2);
  565. CGContextAddLineToPoint(context, selfCent.x + closeWidth/2, selfCent.y - closeWidth/2);
  566. CGContextDrawPath(context, kCGPathStroke);
  567. }
  568. @end
  569. @implementation KZVideoListCell {
  570. UIImageView *_thumImage;
  571. KZCircleCloseBtn *_closeBtn;
  572. }
  573. - (instancetype)initWithFrame:(CGRect)frame {
  574. if (self = [super initWithFrame:frame]) {
  575. _thumImage = [[UIImageView alloc] initWithFrame:CGRectMake(4, 4, self.bounds.size.width - 8, self.bounds.size.height - 8)];
  576. _thumImage.layer.cornerRadius = 6.0;
  577. _thumImage.layer.masksToBounds = YES;
  578. _thumImage.contentMode = UIViewContentModeScaleAspectFill;
  579. [self.contentView addSubview:_thumImage];
  580. _closeBtn = [[KZCircleCloseBtn alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
  581. [_closeBtn addTarget:self action:@selector(deleteAction) forControlEvents:UIControlEventTouchUpInside];
  582. [self.contentView addSubview:_closeBtn];
  583. _closeBtn.hidden = YES;
  584. }
  585. return self;
  586. }
  587. - (void)setVideoModel:(KZVideoModel *)videoModel {
  588. _videoModel = videoModel;
  589. _thumImage.image = [UIImage imageNamed:videoModel.thumAbsolutePath];
  590. // [UIImage imageWithContentsOfFile:videoModel.totalThumPath];
  591. }
  592. - (void)setEdit:(BOOL)canEdit {
  593. _closeBtn.hidden = !canEdit;
  594. }
  595. - (void)deleteAction {
  596. if (self.deleteVideoBlock) {
  597. self.deleteVideoBlock(self.videoModel);
  598. }
  599. }
  600. @end
  601. @implementation KZAddNewVideoCell
  602. - (instancetype)initWithFrame:(CGRect)frame {
  603. if (self = [super initWithFrame:frame]) {
  604. [self setupView];
  605. }
  606. return self;
  607. }
  608. - (void)setupView {
  609. CALayer *bgLayer = [CALayer layer];
  610. bgLayer.frame = CGRectMake(4, 4, self.bounds.size.width - 8, self.bounds.size.height - 8);
  611. bgLayer.backgroundColor = [UIColor colorWithRed: 0.5 green: 0.5 blue: 0.5 alpha: 0.3].CGColor;
  612. bgLayer.cornerRadius = 8.0;
  613. bgLayer.masksToBounds = YES;
  614. [self.contentView.layer addSublayer:bgLayer];
  615. CGPoint selfCent = CGPointMake(bgLayer.bounds.size.width/2, bgLayer.bounds.size.height/2);
  616. CGFloat len = 20;
  617. CGMutablePathRef path = CGPathCreateMutable();
  618. CGPathMoveToPoint(path, nil, selfCent.x, selfCent.y - len);
  619. CGPathAddLineToPoint(path, nil, selfCent.x, selfCent.y + len);
  620. CGPathMoveToPoint(path, nil, selfCent.x - len, selfCent.y);
  621. CGPathAddLineToPoint(path, nil, selfCent.x + len, selfCent.y);
  622. CAShapeLayer *crossLayer = [CAShapeLayer layer];
  623. crossLayer.fillColor = [UIColor clearColor].CGColor;
  624. crossLayer.strokeColor = kzThemeGraryColor.CGColor;
  625. crossLayer.lineWidth = 4.0;
  626. crossLayer.path = path;
  627. crossLayer.opacity = 1.0;
  628. [bgLayer addSublayer:crossLayer];
  629. CGPathRelease(path);
  630. }
  631. - (void)dealloc {
  632. // NSLog(@"cell add dealloc");
  633. }
  634. @end