KZVideoSupport.m 26 KB

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