HXCustomCameraViewController.m 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. //
  2. // HXCustomCameraViewController.m
  3. // HXPhotoPickerExample
  4. //
  5. // Created by Silence on 2017/9/30.
  6. // Copyright © 2017年 Silence. All rights reserved.
  7. //
  8. #import "HXCustomCameraViewController.h"
  9. #import "HXCustomCameraController.h"
  10. #import "HXCustomPreviewView.h"
  11. #import "HXPhotoTools.h"
  12. #import "HXPhotoManager.h"
  13. #import <MediaPlayer/MediaPlayer.h>
  14. #import "UIImage+HXExtension.h"
  15. #import "HXPhotoCustomNavigationBar.h"
  16. #import "UIViewController+HXExtension.h"
  17. #import "HXCameraBottomView.h"
  18. #import "HX_PhotoEditViewController.h"
  19. #import "HXCustomNavigationController.h"
  20. #import <CoreLocation/CoreLocation.h>
  21. @interface HXCustomCameraViewController ()
  22. <HXCustomPreviewViewDelegate ,
  23. HXCustomCameraControllerDelegate ,
  24. CLLocationManagerDelegate
  25. >
  26. @property (strong, nonatomic) HXCustomCameraController *cameraController;
  27. @property (strong, nonatomic) HXCustomPreviewView *previewView;
  28. @property (strong, nonatomic) UIImageView *previewImageView;
  29. @property (strong, nonatomic) CAGradientLayer *topMaskLayer;
  30. @property (strong, nonatomic) UIView *topView;
  31. @property (strong, nonatomic) UIButton *cancelBtn;
  32. @property (strong, nonatomic) UIButton *changeCameraBtn;
  33. @property (strong, nonatomic) HXCameraBottomView *bottomView;
  34. @property (strong, nonatomic) NSTimer *timer;
  35. @property (strong, nonatomic) NSDate *dateVideoStarted;
  36. @property (strong, nonatomic) UIImageView *imageView;
  37. @property (strong, nonatomic) HXCustomCameraPlayVideoView *playVideoView;
  38. @property (strong, nonatomic) UIButton *doneBtn;
  39. @property (strong, nonatomic) UIButton *videoCropBtn;
  40. @property (assign, nonatomic) BOOL addAudioInputComplete;
  41. @property (strong, nonatomic) NSURL *videoURL;
  42. @property (strong, nonatomic) CLLocationManager *locationManager;
  43. @property (strong, nonatomic) CLLocation *location;
  44. @property (strong, nonatomic) UIVisualEffectView *effectView;
  45. @property (strong, nonatomic) UINavigationBar *customNavigationBar;
  46. @property (strong, nonatomic) UINavigationItem *navItem;
  47. @property (assign, nonatomic) CGFloat currentZoomFacto;
  48. @property (strong, nonatomic) UIView *bottomToolsView;
  49. @property (strong, nonatomic) CAGradientLayer *bottomMaskLayer;
  50. @end
  51. @implementation HXCustomCameraViewController
  52. - (UIImage *)jumpImage {
  53. if (self.videoURL) {
  54. return [UIImage hx_thumbnailImageForVideo:self.videoURL atTime:0.1];
  55. }
  56. return self.imageView.image;
  57. }
  58. - (CGRect)jumpRect {
  59. if (self.videoURL) {
  60. CGFloat width = self.playVideoView.playerLayer.videoRect.size.width;
  61. CGFloat height = self.playVideoView.playerLayer.videoRect.size.height;
  62. return CGRectMake(0, (self.view.hx_h - height) / 2, width, height);
  63. }
  64. return self.imageView.frame;
  65. }
  66. - (void)showPlayerView{
  67. self.playVideoView.hidden = NO;
  68. self.previewView.hidden = NO;
  69. }
  70. - (void)hidePlayerView {
  71. self.playVideoView.hidden = YES;
  72. self.previewView.hidden = YES;
  73. }
  74. - (void)hiddenTopBottomView {
  75. self.customNavigationBar.alpha = 0;
  76. self.topView.alpha = 0;
  77. self.videoCropBtn.alpha = 0;
  78. self.doneBtn.alpha = 0;
  79. }
  80. - (void)showTopBottomView {
  81. [UIView animateWithDuration:0.2 animations:^{
  82. self.customNavigationBar.alpha = 1;
  83. self.topView.alpha = 1;
  84. self.videoCropBtn.alpha = 1;
  85. self.doneBtn.alpha = 1;
  86. }];
  87. }
  88. - (void)viewDidLoad {
  89. [super viewDidLoad];
  90. self.extendedLayoutIncludesOpaqueBars = YES;
  91. self.edgesForExtendedLayout = UIRectEdgeAll;
  92. // if (self.manager.configuration.saveSystemAblum && !self.manager.albums &&
  93. // !self.manager.onlyCamera) {
  94. // dispatch_async(self.manager.loadAssetQueue, ^{
  95. // [self.manager getAllAlbumModelFilter:NO select:nil completion:nil];
  96. // });
  97. // }
  98. self.view.backgroundColor = [UIColor blackColor];
  99. if (self.manager.configuration.cameraCanLocation && HX_ALLOW_LOCATION) {
  100. if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusDenied) {
  101. [self.locationManager startUpdatingLocation];
  102. }
  103. }
  104. if (self.manager.configuration.videoMaximumDuration > self.manager.configuration.videoMaximumSelectDuration) {
  105. self.manager.configuration.videoMaximumDuration = self.manager.configuration.videoMaximumSelectDuration;
  106. }else if (self.manager.configuration.videoMaximumDuration < 3.f) {
  107. self.manager.configuration.videoMaximumDuration = 4.f;
  108. }
  109. self.previewView.themeColor = self.manager.configuration.cameraFocusBoxColor;
  110. [self.view addSubview:self.previewView];
  111. self.cameraController = [[HXCustomCameraController alloc] init];
  112. self.cameraController.defaultFrontCamera = self.manager.configuration.defaultFrontCamera;
  113. self.cameraController.videoMaximumDuration = self.manager.configuration.videoMaximumDuration;
  114. self.cameraController.sessionPreset = self.manager.configuration.sessionPreset;
  115. self.cameraController.videoCodecKey = self.manager.configuration.videoCodecKey;
  116. self.cameraController.delegate = self;
  117. NSData *imageData = [NSData dataWithContentsOfURL:[HXPhotoCommon photoCommon].cameraImageURL];
  118. if (imageData) {
  119. UIImage *image = [UIImage imageWithData:imageData scale:1];
  120. if (image) {
  121. self.previewImageView.image = image;
  122. [self.previewView addSubview:self.previewImageView];
  123. [self.previewView addSubview:self.effectView];
  124. }
  125. }
  126. self.bottomView.userInteractionEnabled = NO;
  127. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  128. [self.cameraController initSeesion];
  129. self.previewView.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.cameraController.captureSession];
  130. HXWeakSelf
  131. [self.cameraController.captureSession beginConfiguration];
  132. [self.cameraController setupPreviewLayer:self.previewView.previewLayer startSessionCompletion:^(BOOL success) {
  133. if (success) {
  134. [weakSelf addOutputs];
  135. [weakSelf.cameraController.captureSession commitConfiguration];
  136. [weakSelf.cameraController.captureSession startRunning];
  137. dispatch_async(dispatch_get_main_queue(), ^{
  138. [weakSelf.previewView setupPreviewLayer];
  139. weakSelf.previewView.delegate = weakSelf;
  140. [weakSelf setupCamera];
  141. });
  142. }
  143. }];
  144. });
  145. [self.view addSubview:self.bottomView];
  146. [self.view addSubview:self.topView];
  147. [self.view addSubview:self.bottomToolsView];
  148. [self changeSubviewFrame];
  149. [self.view addSubview:self.customNavigationBar];
  150. if (self.manager.configuration.navigationBar) {
  151. self.manager.configuration.navigationBar(self.customNavigationBar, self);
  152. }
  153. self.customNavigationBar.translucent = YES;
  154. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationBecomeActive) name:UIApplicationWillEnterForegroundNotification object:nil];
  155. if (@available(iOS 13.0, *)) {
  156. UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
  157. appearance.shadowImage = [[UIImage alloc] init];
  158. appearance.shadowColor = [UIColor clearColor];
  159. appearance.titleTextAttributes = self.customNavigationBar.titleTextAttributes;
  160. appearance.backgroundEffect = nil;
  161. self.customNavigationBar.standardAppearance = appearance;
  162. if (@available(iOS 15.0, *)) {
  163. self.customNavigationBar.scrollEdgeAppearance = appearance;
  164. }
  165. }
  166. }
  167. - (void)applicationBecomeActive {
  168. if (self.addAudioInputComplete) {
  169. [self.cameraController initMovieOutput];
  170. }
  171. }
  172. - (void)setupImageOutput {
  173. [self.cameraController initImageOutput];
  174. self.cameraController.flashMode = AVCaptureFlashModeAuto;
  175. }
  176. - (void)setupMovieOutput {
  177. [self.cameraController addAudioInput];
  178. self.addAudioInputComplete = YES;
  179. [self.cameraController initMovieOutput];
  180. self.cameraController.torchMode = 0;
  181. dispatch_async(dispatch_get_main_queue(), ^{
  182. [self requestAccessForAudio];
  183. [self.view insertSubview:self.playVideoView belowSubview:self.bottomView];
  184. });
  185. }
  186. - (void)setupImageAndMovieOutput {
  187. [self setupImageOutput];
  188. [self setupMovieOutput];
  189. }
  190. - (void)addOutputs {
  191. switch (self.manager.configuration.customCameraType) {
  192. case HXPhotoCustomCameraTypeUnused: {
  193. if (self.manager.type == HXPhotoManagerSelectedTypePhoto) {
  194. [self setupImageOutput];
  195. // [self.cameraController addDataOutput];
  196. }else if (self.manager.type == HXPhotoManagerSelectedTypeVideo) {
  197. [self setupMovieOutput];
  198. }else {
  199. if (!self.manager.configuration.selectTogether && self.isOutside) {
  200. if (self.manager.afterSelectedPhotoArray.count > 0) {
  201. [self setupImageOutput];
  202. // [self.cameraController addDataOutput];
  203. }else if (self.manager.afterSelectedVideoArray.count > 0) {
  204. [self setupMovieOutput];
  205. }else {
  206. [self setupImageAndMovieOutput];
  207. }
  208. }else {
  209. [self setupImageAndMovieOutput];
  210. }
  211. }
  212. } break;
  213. case HXPhotoCustomCameraTypePhoto: {
  214. [self setupImageOutput];
  215. // [self.cameraController addDataOutput];
  216. } break;
  217. case HXPhotoCustomCameraTypeVideo: {
  218. [self setupMovieOutput];
  219. } break;
  220. case HXPhotoCustomCameraTypePhotoAndVideo: {
  221. [self setupImageAndMovieOutput];
  222. } break;
  223. default:
  224. break;
  225. }
  226. }
  227. - (void)setupCamera {
  228. self.bottomView.userInteractionEnabled = YES;
  229. if (_previewImageView) {
  230. [UIView animateWithDuration:0.25 animations:^{
  231. self.previewImageView.alpha = 0;
  232. if (HX_IOS9Later) {
  233. [self.effectView setEffect:nil];
  234. }else {
  235. self.effectView.alpha = 0;
  236. }
  237. } completion:^(BOOL finished) {
  238. [self.effectView removeFromSuperview];
  239. [self.previewImageView removeFromSuperview];
  240. [self.previewView firstFocusing];
  241. }];
  242. }else {
  243. [self.previewView firstFocusing];
  244. }
  245. self.previewView.tapToFocusEnabled = self.cameraController.cameraSupportsTapToFocus;
  246. self.previewView.tapToExposeEnabled = self.cameraController.cameraSupportsTapToExpose;
  247. UIBarButtonItem *rightBtn1 = [[UIBarButtonItem alloc] initWithCustomView:self.changeCameraBtn];
  248. if ([self.cameraController canSwitchCameras] && [self.cameraController cameraHasFlash]) {
  249. self.navItem.rightBarButtonItems = @[rightBtn1];
  250. }
  251. self.previewView.maxScale = [self.cameraController maxZoomFactor];
  252. [self resetCameraZoom];
  253. self.cameraController.flashMode = AVCaptureFlashModeAuto;
  254. [self setupFlashAndTorchBtn];
  255. self.previewView.tapToExposeEnabled = self.cameraController.cameraSupportsTapToExpose;
  256. self.previewView.tapToFocusEnabled = self.cameraController.cameraSupportsTapToFocus;
  257. }
  258. - (void)requestAccessForAudio {
  259. HXWeakSelf
  260. [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
  261. dispatch_async(dispatch_get_main_queue(), ^{
  262. if (granted) {
  263. if (!weakSelf.addAudioInputComplete) {
  264. [weakSelf.cameraController addAudioInput];
  265. weakSelf.addAudioInputComplete = YES;
  266. }
  267. }else {
  268. hx_showAlert(weakSelf, [NSBundle hx_localizedStringForKey:@"无法使用麦克风"], [NSBundle hx_localizedStringForKey:@"请在设置-隐私-相机中允许访问麦克风"], [NSBundle hx_localizedStringForKey:@"取消"], [NSBundle hx_localizedStringForKey:@"设置"], ^{
  269. [weakSelf.view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"麦克风添加失败,录制视频会没有声音哦!"]];
  270. }, ^{
  271. NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
  272. if (@available(iOS 10.0, *)) {
  273. [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
  274. }else {
  275. [[UIApplication sharedApplication] openURL:url];
  276. }
  277. });
  278. }
  279. });
  280. }];
  281. }
  282. - (void)setupFlashAndTorchBtn {
  283. self.previewView.pinchToZoomEnabled = [self.cameraController cameraSupportsZoom];
  284. }
  285. - (void)changeSubviewFrame {
  286. self.customNavigationBar.frame = CGRectMake(0, self.previewView.hx_y, self.view.hx_w, hxNavigationBarHeight);
  287. if (!HX_IS_IPhoneX_All && HX_IOS11_Later) {
  288. self.customNavigationBar.hx_y = self.previewView.hx_y + 10;
  289. self.topView.frame = self.customNavigationBar.frame;
  290. self.topView.hx_y = -10;
  291. }else if (HX_IS_IPhoneX_All) {
  292. self.customNavigationBar.hx_y = self.previewView.hx_y - 40;
  293. self.topView.frame = self.customNavigationBar.frame;
  294. }
  295. self.topMaskLayer.frame = self.topView.bounds;
  296. if (HX_IS_IPhoneX_All) {
  297. self.bottomView.frame = CGRectMake(0, self.view.hx_h - 100 - self.previewView.hx_y, self.view.hx_w, 130);
  298. }else {
  299. self.bottomView.frame = CGRectMake(0, self.view.hx_h - 130 - self.previewView.hx_y, self.view.hx_w, 130);
  300. }
  301. }
  302. - (BOOL)prefersStatusBarHidden {
  303. return YES;
  304. }
  305. - (void)viewWillAppear:(BOOL)animated {
  306. [super viewWillAppear:animated];
  307. [self.navigationController setNavigationBarHidden:YES];
  308. [self.customNavigationBar setBackgroundColor:[UIColor clearColor]];
  309. [self.customNavigationBar setShadowImage:[[UIImage alloc] init]];
  310. [self.customNavigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
  311. [self.customNavigationBar setTintColor:[UIColor whiteColor]];
  312. [self.customNavigationBar setBarTintColor:nil];
  313. #pragma clang diagnostic push
  314. #pragma clang diagnostic ignored"-Wdeprecated-declarations"
  315. [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
  316. #pragma clang diagnostic pop
  317. AVCaptureConnection *previewLayerConnection = [(AVCaptureVideoPreviewLayer *)self.previewView.previewLayer connection];
  318. if ([previewLayerConnection isVideoOrientationSupported])
  319. [previewLayerConnection setVideoOrientation:(AVCaptureVideoOrientation)[[UIApplication sharedApplication] statusBarOrientation]];
  320. [self preferredStatusBarUpdateAnimation];
  321. if (self.manager.viewWillAppear) {
  322. self.manager.viewWillAppear(self);
  323. }
  324. }
  325. - (void)viewWillDisappear:(BOOL)animated {
  326. [super viewWillDisappear:animated];
  327. #pragma clang diagnostic push
  328. #pragma clang diagnostic ignored"-Wdeprecated-declarations"
  329. [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
  330. #pragma clang diagnostic pop
  331. [self.cameraController stopMontionUpdate];
  332. [self preferredStatusBarUpdateAnimation];
  333. if (self.manager.viewWillDisappear) {
  334. self.manager.viewWillDisappear(self);
  335. }
  336. }
  337. - (void)viewDidAppear:(BOOL)animated {
  338. [super viewDidAppear:animated];
  339. [self.navigationController setNavigationBarHidden:YES];
  340. [self.cameraController startMontionUpdate];
  341. if (self.manager.viewDidAppear) {
  342. self.manager.viewDidAppear(self);
  343. }
  344. }
  345. - (void)viewDidDisappear:(BOOL)animated {
  346. [super viewDidDisappear:animated];
  347. [self stopTimer];
  348. [self.cameraController stopSession];
  349. if (self.manager.viewDidDisappear) {
  350. self.manager.viewDidDisappear(self);
  351. }
  352. }
  353. - (void)dealloc {
  354. if (HX_ALLOW_LOCATION && _locationManager) {
  355. [self.locationManager stopUpdatingLocation];
  356. }
  357. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
  358. if (HXShowLog) NSSLog(@"dealloc");
  359. }
  360. - (void)cancelClick:(UIButton *)button {
  361. if (button.selected) {
  362. self.videoURL = nil;
  363. [self setupFlashAndTorchBtn];
  364. self.bottomView.inTranscribe = NO;
  365. self.bottomView.inTakePictures = NO;
  366. [self.imageView removeFromSuperview];
  367. [self hideBottomToolsView];
  368. [self.playVideoView stopPlay];
  369. self.playVideoView.hidden = YES;
  370. self.playVideoView.playerLayer.hidden = YES;
  371. self.changeCameraBtn.hidden = NO;
  372. self.cancelBtn.selected = NO;
  373. self.cancelBtn.hx_w = 50;
  374. self.bottomView.hidden = NO;
  375. self.previewView.tapToFocusEnabled = YES;
  376. }
  377. }
  378. - (void)didDoneBtnClick {
  379. HXPhotoModel *cameraModel;
  380. if (!self.videoURL) {
  381. cameraModel = [HXPhotoModel photoModelWithImage:self.imageView.image];
  382. }else {
  383. NSTimeInterval timeElapsed = [[NSDate date] timeIntervalSinceDate:self.dateVideoStarted];
  384. if (timeElapsed < self.manager.configuration.videoMinimumDuration) {
  385. [self.view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"录制时间少于%0.f秒"], self.manager.configuration.videoMinimumDuration]];
  386. return;
  387. }
  388. [self.playVideoView stopPlay];
  389. cameraModel = [HXPhotoModel photoModelWithVideoURL:self.videoURL videoTime:timeElapsed];
  390. }
  391. cameraModel.creationDate = [NSDate date];
  392. cameraModel.location = self.location;
  393. HXWeakSelf
  394. if (!self.manager.configuration.saveSystemAblum) {
  395. if (cameraModel.subType == HXPhotoModelMediaSubTypePhoto) {
  396. if (self.manager.configuration.cameraPhotoJumpEdit && !self.manager.configuration.useWxPhotoEdit) {
  397. [self hx_presentPhotoEditViewControllerWithManager:self.manager photoModel:cameraModel delegate:nil done:^(HXPhotoModel *beforeModel, HXPhotoModel *afterModel, HXPhotoEditViewController *viewController) {
  398. [weakSelf doneCompleteWithModel:afterModel];
  399. } cancel:^(HXPhotoEditViewController *viewController) {
  400. [weakSelf cancelClick:weakSelf.cancelBtn];
  401. }];
  402. }else {
  403. [self doneCompleteWithModel:cameraModel];
  404. }
  405. }else if (cameraModel.subType == HXPhotoModelMediaSubTypeVideo) {
  406. [self doneCompleteWithModel:cameraModel];
  407. }
  408. }else {
  409. if (self.manager.configuration.editAssetSaveSystemAblum) {
  410. if (cameraModel.subType == HXPhotoModelMediaSubTypePhoto) {
  411. if (self.manager.configuration.cameraPhotoJumpEdit && !self.manager.configuration.useWxPhotoEdit) {
  412. [self hx_presentPhotoEditViewControllerWithManager:self.manager photoModel:cameraModel delegate:nil done:^(HXPhotoModel *beforeModel, HXPhotoModel *afterModel, HXPhotoEditViewController *viewController) {
  413. [weakSelf doneCompleteWithModel:afterModel];
  414. } cancel:^(HXPhotoEditViewController *viewController) {
  415. [weakSelf cancelClick:weakSelf.cancelBtn];
  416. }];
  417. }else {
  418. [self doneCompleteWithModel:cameraModel];
  419. }
  420. }else if (cameraModel.subType == HXPhotoModelMediaSubTypeVideo) {
  421. [self doneCompleteWithModel:cameraModel];
  422. }
  423. }else {
  424. [self.view hx_immediatelyShowLoadingHudWithText:nil];
  425. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  426. id location = self.location;
  427. if (!self.videoURL) {
  428. [HXPhotoTools savePhotoToCustomAlbumWithName:self.manager.configuration.customAlbumName photo:self.imageView.image location:location complete:^(HXPhotoModel *model, BOOL success) {
  429. if (success) {
  430. if (weakSelf.manager.configuration.cameraPhotoJumpEdit) {
  431. [weakSelf hx_presentPhotoEditViewControllerWithManager:weakSelf.manager photoModel:cameraModel delegate:nil done:^(HXPhotoModel *beforeModel, HXPhotoModel *afterModel, HXPhotoEditViewController *viewController) {
  432. [weakSelf doneCompleteWithModel:afterModel];
  433. } cancel:^(HXPhotoEditViewController *viewController) {
  434. [weakSelf cancelClick:weakSelf.cancelBtn];
  435. }];
  436. }else {
  437. [weakSelf doneCompleteWithModel:model];
  438. }
  439. [weakSelf.view hx_handleLoading:NO];
  440. }else {
  441. [weakSelf.view hx_showImageHUDText:@"保存失败!"];
  442. }
  443. }];
  444. }else {
  445. [HXPhotoTools saveVideoToCustomAlbumWithName:self.manager.configuration.customAlbumName videoURL:self.videoURL location:location complete:^(HXPhotoModel *model, BOOL success) {
  446. [weakSelf.view hx_handleLoading:NO];
  447. if (success) {
  448. model.videoURL = weakSelf.videoURL;
  449. [weakSelf doneCompleteWithModel:model];
  450. }else {
  451. [weakSelf.view hx_showImageHUDText:@"保存失败!"];
  452. }
  453. }];
  454. }
  455. });
  456. }
  457. }
  458. }
  459. - (void)doneCompleteWithModel:(HXPhotoModel *)model {
  460. [[HXPhotoCommon photoCommon] saveCamerImage];
  461. [self stopTimer];
  462. [self.cameraController stopMontionUpdate];
  463. [self.cameraController stopSession];
  464. self.cameraController.flashMode = 0;
  465. self.cameraController.torchMode = 0;
  466. if ([self.delegate respondsToSelector:@selector(customCameraViewController:didDone:)]) {
  467. [self.delegate customCameraViewController:self didDone:model];
  468. }
  469. if (self.doneBlock) {
  470. self.doneBlock(model, self);
  471. }
  472. BOOL cameraFinishDismissAnimated = self.manager.cameraFinishDismissAnimated;
  473. if (self.manager.configuration.cameraPhotoJumpEdit) {
  474. [self.presentingViewController dismissViewControllerAnimated:cameraFinishDismissAnimated completion:^{
  475. if ([self.delegate respondsToSelector:@selector(customCameraViewControllerFinishDismissCompletion:)]) {
  476. [self.delegate customCameraViewControllerFinishDismissCompletion:self];
  477. }
  478. }];
  479. }else {
  480. [self dismissViewControllerAnimated:cameraFinishDismissAnimated completion:^{
  481. if ([self.delegate respondsToSelector:@selector(customCameraViewControllerFinishDismissCompletion:)]) {
  482. [self.delegate customCameraViewControllerFinishDismissCompletion:self];
  483. }
  484. }];
  485. }
  486. }
  487. - (void)resetCameraZoom {
  488. self.previewView.maxScale = [self.cameraController maxZoomFactor];
  489. if ([self.cameraController cameraSupportsZoom]) {
  490. self.previewView.effectiveScale = 1.0f;
  491. self.previewView.beginGestureScale = 1.0f;
  492. [self.cameraController rampZoomToValue:1.0f];
  493. [self.cameraController cancelZoom];
  494. }
  495. }
  496. - (void)didchangeCameraClick {
  497. if ([self.cameraController switchCameras]) {
  498. [self resetCameraZoom];
  499. [self setupFlashAndTorchBtn];
  500. self.previewView.tapToExposeEnabled = self.cameraController.cameraSupportsTapToExpose;
  501. self.previewView.tapToFocusEnabled = self.cameraController.cameraSupportsTapToFocus;
  502. [self.cameraController resetFocusAndExposureModes];
  503. }
  504. }
  505. - (void)handleDeviceMotion:(UIDeviceOrientation)deviceOrientation {
  506. if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
  507. [UIView animateWithDuration:0.2 animations:^{
  508. self.changeCameraBtn.transform = CGAffineTransformMakeRotation(M_PI / 2);
  509. }];
  510. }else if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
  511. [UIView animateWithDuration:0.2 animations:^{
  512. self.changeCameraBtn.transform = CGAffineTransformMakeRotation(-M_PI / 2);
  513. }];
  514. }else {
  515. [UIView animateWithDuration:0.2 animations:^{
  516. self.changeCameraBtn.transform = CGAffineTransformIdentity;
  517. }];
  518. }
  519. }
  520. - (void)takePicturesComplete:(UIImage *)image {
  521. [self needHideViews];
  522. self.imageView.image = image;
  523. [HXPhotoCommon photoCommon].cameraImage = [image hx_normalizedImage];
  524. [self.view insertSubview:self.imageView belowSubview:self.bottomView];
  525. // [self.cameraController stopSession];
  526. if (self.manager.configuration.useWxPhotoEdit &&
  527. self.manager.configuration.cameraPhotoJumpEdit) {
  528. self.topView.hidden = YES;
  529. HXWeakSelf
  530. HXPhotoModel *model = [HXPhotoModel photoModelWithImage:image];
  531. model.creationDate = [NSDate date];
  532. HX_PhotoEditViewController *vc = [[HX_PhotoEditViewController alloc] initWithConfiguration:self.manager.configuration.photoEditConfigur];
  533. vc.saveAlbum = self.manager.configuration.saveSystemAblum;
  534. vc.photoModel = model;
  535. vc.albumName = self.manager.configuration.customAlbumName;
  536. vc.location = self.location;
  537. vc.finishBlock = ^(HXPhotoEdit * _Nullable photoEdit, HXPhotoModel * _Nonnull photoModel, HX_PhotoEditViewController * _Nonnull viewController) {
  538. if (photoModel.photoEdit) {
  539. photoModel = [HXPhotoModel photoModelWithImage:photoModel.photoEdit.editPreviewImage];
  540. }
  541. [weakSelf doneCompleteWithModel:photoModel];
  542. };
  543. vc.cancelBlock = ^(HX_PhotoEditViewController * _Nonnull viewController) {
  544. weakSelf.topView.hidden = NO;
  545. [weakSelf.cameraController startSession];
  546. [weakSelf cancelClick:weakSelf.cancelBtn];
  547. };
  548. vc.supportRotation = NO;
  549. vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
  550. vc.modalPresentationCapturesStatusBarAppearance = YES;
  551. [self presentViewController:vc animated:YES completion:nil];
  552. }else {
  553. self.videoCropBtn.hidden = YES;
  554. [self showBottomToolsView];
  555. self.cancelBtn.hidden = NO;
  556. }
  557. }
  558. - (void)takePicturesFailed {
  559. self.cancelBtn.hidden = NO;
  560. self.changeCameraBtn.hidden = NO;
  561. self.cancelBtn.selected = NO;
  562. self.cancelBtn.hx_w = 50;
  563. self.bottomView.hidden = NO;
  564. self.previewView.tapToFocusEnabled = YES;
  565. self.previewView.pinchToZoomEnabled = [self.cameraController cameraSupportsZoom];
  566. [self.view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"拍摄失败"]];
  567. }
  568. - (void)startTimer {
  569. // [self.timer invalidate];
  570. // self.timer = [NSTimer timerWithTimeInterval:0.2f
  571. // target:self
  572. // selector:@selector(updateTimeDisplay)
  573. // userInfo:nil
  574. // repeats:YES];
  575. // [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
  576. }
  577. - (void)updateTimeDisplay {
  578. // CMTime duration = self.cameraController.recordedDuration;
  579. // NSTimeInterval time = CMTimeGetSeconds(duration);
  580. // self.time = (NSInteger)time;
  581. // if (time + 0.4f >= self.manager.configuration.videoMaximumDuration) {
  582. // [self.bottomView videoRecordEnd];
  583. // }
  584. }
  585. - (void)stopTimer {
  586. [self.timer invalidate];
  587. self.timer = nil;
  588. }
  589. - (void)videoStartRecording {
  590. [self.bottomView startRecord];
  591. }
  592. - (void)videoNeedHideViews {
  593. self.cancelBtn.hidden = YES;
  594. self.cancelBtn.selected = YES;
  595. self.cancelBtn.hx_w = [self.cancelBtn.titleLabel hx_getTextWidth] + 10;
  596. self.changeCameraBtn.hidden = YES;
  597. }
  598. - (void)videoFinishRecording:(NSURL *)videoURL {
  599. [self.bottomView stopRecord];
  600. if (!self.dateVideoStarted) {
  601. self.dateVideoStarted = [NSDate date];
  602. }
  603. NSTimeInterval timeElapsed = [[NSDate date] timeIntervalSinceDate:self.dateVideoStarted];
  604. if (timeElapsed < self.manager.configuration.videoMinimumDuration) {
  605. self.bottomView.hidden = NO;
  606. self.cancelBtn.selected = NO;
  607. self.cancelBtn.hx_w = 50;
  608. self.changeCameraBtn.hidden = NO;
  609. [self.view hx_showImageHUDText:[NSString stringWithFormat:[NSBundle hx_localizedStringForKey:@"%.0f秒内的视频无效哦~"], self.manager.configuration.videoMinimumDuration]];
  610. }else {
  611. [HXPhotoCommon photoCommon].cameraImage = [[UIImage hx_thumbnailImageForVideo:videoURL atTime:0.1f] hx_normalizedImage];
  612. // [self.cameraController stopSession];
  613. self.previewView.tapToFocusEnabled = NO;
  614. self.previewView.pinchToZoomEnabled = NO;
  615. self.bottomView.hidden = YES;
  616. self.videoURL = [videoURL copy];
  617. self.playVideoView.hidden = NO;
  618. self.playVideoView.playerLayer.hidden = NO;
  619. self.playVideoView.videoURL = self.videoURL;
  620. [self showBottomToolsView];
  621. self.previewView.effectiveScale = 1.0f;
  622. self.previewView.beginGestureScale = 1.0f;
  623. [self.cameraController setZoomValue:1.0f];
  624. self.currentZoomFacto = self.cameraController.currentZoomFacto;
  625. }
  626. self.cancelBtn.hidden = NO;
  627. }
  628. - (void)mediaCaptureFailedWithError:(NSError *)error {
  629. [self stopTimer];
  630. [self.bottomView stopRecord];
  631. [self.view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"录制视频失败!"]];
  632. self.bottomView.hidden = NO;
  633. self.cancelBtn.selected = NO;
  634. self.cancelBtn.hx_w = 50;
  635. self.changeCameraBtn.hidden = NO;
  636. self.cancelBtn.hidden = NO;
  637. }
  638. - (void)bottomDidTakePictures {
  639. [self.cameraController captureStillImage];
  640. self.previewView.tapToFocusEnabled = NO;
  641. self.previewView.pinchToZoomEnabled = NO;
  642. }
  643. - (void)bottomDidTranscribe {
  644. if ([self.cameraController isRecording]) {
  645. [self.cameraController stopRecording];
  646. [self stopTimer];
  647. }else {
  648. if ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio] != AVAuthorizationStatusAuthorized) {
  649. [self.view hx_showImageHUDText:[NSBundle hx_localizedStringForKey:@"麦克风添加失败,录制视频会没有声音哦!"]];
  650. }
  651. [self videoNeedHideViews];
  652. [self playViewAnimateCompletion];
  653. }
  654. }
  655. - (void)needHideViews {
  656. self.cancelBtn.selected = YES;
  657. self.cancelBtn.hx_w = [self.cancelBtn.titleLabel hx_getTextWidth] + 10;
  658. self.changeCameraBtn.hidden = YES;
  659. self.bottomView.hidden = YES;
  660. self.cancelBtn.hidden = YES;
  661. }
  662. - (void)playViewAnimateCompletion {
  663. if (self.bottomView.inTranscribe) {
  664. dispatch_async(dispatch_queue_create("com.hxdatephotopicker.camera", NULL), ^{
  665. [self.cameraController startRecording];
  666. self.dateVideoStarted = [NSDate date];
  667. // dispatch_async(dispatch_get_main_queue(), ^{
  668. // [self startTimer];
  669. // });
  670. });
  671. }
  672. }
  673. - (void)tappedToFocusAtPoint:(CGPoint)point {
  674. [self.cameraController focusAtPoint:point];
  675. [self.cameraController exposeAtPoint:point];
  676. }
  677. - (void)pinchGestureScale:(CGFloat)scale {
  678. [self.cameraController setZoomValue:scale];
  679. }
  680. - (UINavigationBar *)customNavigationBar {
  681. if (!_customNavigationBar) {
  682. _customNavigationBar = [[UINavigationBar alloc] init];
  683. _customNavigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  684. _customNavigationBar.shadowImage = [[UIImage alloc] init];
  685. [_customNavigationBar pushNavigationItem:self.navItem animated:NO];
  686. }
  687. return _customNavigationBar;
  688. }
  689. - (UINavigationItem *)navItem {
  690. if (!_navItem) {
  691. _navItem = [[UINavigationItem alloc] init];
  692. _navItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.cancelBtn];
  693. }
  694. return _navItem;
  695. }
  696. - (HXCustomPreviewView *)previewView {
  697. if (!_previewView) {
  698. _previewView = [[HXCustomPreviewView alloc] init];
  699. if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
  700. _previewView.frame = self.view.bounds;
  701. }else {
  702. _previewView.hx_size = CGSizeMake(self.view.hx_w, self.view.hx_w / 9 * 16);
  703. _previewView.center = CGPointMake(self.view.hx_w / 2, self.view.hx_h / 2);
  704. }
  705. }
  706. return _previewView;
  707. }
  708. - (UIImageView *)previewImageView {
  709. if (!_previewImageView) {
  710. _previewImageView = [[UIImageView alloc] init];
  711. _previewImageView.frame = self.previewView.bounds;
  712. _previewImageView.contentMode = UIViewContentModeScaleAspectFill;
  713. _previewImageView.clipsToBounds = YES;
  714. }
  715. return _previewImageView;
  716. }
  717. - (UIView *)topView {
  718. if (!_topView) {
  719. _topView = [[UIView alloc] init];
  720. [_topView.layer addSublayer:self.topMaskLayer];
  721. }
  722. return _topView;
  723. }
  724. - (CAGradientLayer *)topMaskLayer {
  725. if (!_topMaskLayer) {
  726. _topMaskLayer = [CAGradientLayer layer];
  727. _topMaskLayer.colors = @[
  728. (id)[[UIColor blackColor] colorWithAlphaComponent:0].CGColor,
  729. (id)[[UIColor blackColor] colorWithAlphaComponent:0.3].CGColor
  730. ];
  731. _topMaskLayer.startPoint = CGPointMake(0, 1);
  732. _topMaskLayer.endPoint = CGPointMake(0, 0);
  733. _topMaskLayer.locations = @[@(0.15f),@(0.9f)];
  734. _topMaskLayer.borderWidth = 0.0;
  735. }
  736. return _topMaskLayer;
  737. }
  738. - (UIButton *)cancelBtn {
  739. if (!_cancelBtn) {
  740. _cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  741. [_cancelBtn setTitle:[NSBundle hx_localizedStringForKey:@"重拍"] forState:UIControlStateSelected];
  742. [_cancelBtn setTitle:@"" forState:UIControlStateNormal];
  743. [_cancelBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
  744. [_cancelBtn addTarget:self action:@selector(cancelClick:) forControlEvents:UIControlEventTouchUpInside];
  745. _cancelBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
  746. _cancelBtn.hx_size = CGSizeMake(50, 50);
  747. }
  748. return _cancelBtn;
  749. }
  750. - (UIButton *)changeCameraBtn {
  751. if (!_changeCameraBtn) {
  752. _changeCameraBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  753. [_changeCameraBtn setImage:[UIImage hx_imageNamed:@"hx_camera_overturn"] forState:UIControlStateNormal];
  754. [_changeCameraBtn addTarget:self action:@selector(didchangeCameraClick) forControlEvents:UIControlEventTouchUpInside];
  755. _changeCameraBtn.hx_size = CGSizeMake(50, 50);
  756. _changeCameraBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
  757. CGSize size = _changeCameraBtn.currentImage.size;
  758. _changeCameraBtn.layer.anchorPoint = CGPointMake(((50 - size.width) + size.width / 2) / 50, 0.5);
  759. }
  760. return _changeCameraBtn;
  761. }
  762. - (HXCameraBottomView *)bottomView {
  763. if (!_bottomView) {
  764. _bottomView = [HXCameraBottomView initView];
  765. _bottomView.isOutside = self.isOutside;
  766. _bottomView.manager = self.manager;
  767. HXWeakSelf
  768. _bottomView.takePictures = ^{
  769. weakSelf.imageView.image = nil;
  770. [weakSelf bottomDidTakePictures];
  771. };
  772. _bottomView.startTranscribe = ^{
  773. weakSelf.currentZoomFacto = weakSelf.cameraController.currentZoomFacto;
  774. [weakSelf bottomDidTranscribe];
  775. };
  776. _bottomView.changedTranscribe = ^(CGFloat margin) {
  777. CGFloat scale = margin / 50.f;
  778. scale += weakSelf.currentZoomFacto;
  779. weakSelf.previewView.effectiveScale = scale;
  780. weakSelf.previewView.beginGestureScale = scale;
  781. [weakSelf.cameraController setZoomValue:scale];
  782. };
  783. _bottomView.endTranscribe = ^(BOOL isAnimation) {
  784. if (![weakSelf.cameraController isRecording]) {
  785. [weakSelf stopTimer];
  786. weakSelf.cancelBtn.selected = NO;
  787. weakSelf.cancelBtn.hx_w = 50;
  788. weakSelf.changeCameraBtn.hidden = NO;
  789. }else {
  790. weakSelf.bottomView.hidden = YES;
  791. [weakSelf bottomDidTranscribe];
  792. }
  793. };;
  794. _bottomView.backClick = ^{
  795. [[HXPhotoCommon photoCommon] saveCamerImage];
  796. [weakSelf stopTimer];
  797. [weakSelf.cameraController stopMontionUpdate];
  798. [weakSelf.cameraController stopSession];
  799. if ([weakSelf.delegate respondsToSelector:@selector(customCameraViewControllerDidCancel:)]) {
  800. [weakSelf.delegate customCameraViewControllerDidCancel:weakSelf];
  801. }
  802. if (weakSelf.cancelBlock) {
  803. weakSelf.cancelBlock(weakSelf);
  804. }
  805. BOOL cameraCancelDismissAnimated = weakSelf.manager.cameraCancelDismissAnimated;
  806. [weakSelf dismissViewControllerAnimated:cameraCancelDismissAnimated completion:^{
  807. if ([weakSelf.delegate respondsToSelector:@selector(customCameraViewControllerCancelDismissCompletion:)]) {
  808. [weakSelf.delegate customCameraViewControllerCancelDismissCompletion:weakSelf];
  809. }
  810. }];
  811. };
  812. }
  813. return _bottomView;
  814. }
  815. - (UIImageView *)imageView {
  816. if (!_imageView) {
  817. _imageView = [[UIImageView alloc] initWithFrame:self.previewView.frame];
  818. _imageView.backgroundColor = [UIColor blackColor];
  819. _imageView.contentMode = UIViewContentModeScaleAspectFit;
  820. }
  821. return _imageView;
  822. }
  823. - (HXCustomCameraPlayVideoView *)playVideoView {
  824. if (!_playVideoView) {
  825. _playVideoView = [[HXCustomCameraPlayVideoView alloc] initWithFrame:self.view.bounds];
  826. _playVideoView.hidden = YES;
  827. _playVideoView.playerLayer.hidden = YES;
  828. }
  829. return _playVideoView;
  830. }
  831. - (CAGradientLayer *)bottomMaskLayer {
  832. if (!_bottomMaskLayer) {
  833. _bottomMaskLayer = [CAGradientLayer layer];
  834. _bottomMaskLayer.colors = @[
  835. (id)[[UIColor blackColor] colorWithAlphaComponent:0].CGColor,
  836. (id)[[UIColor blackColor] colorWithAlphaComponent:0.4].CGColor
  837. ];
  838. _bottomMaskLayer.startPoint = CGPointMake(0, 0);
  839. _bottomMaskLayer.endPoint = CGPointMake(0, 1);
  840. _bottomMaskLayer.locations = @[@(0),@(1.f)];
  841. _bottomMaskLayer.borderWidth = 0.0;
  842. }
  843. return _bottomMaskLayer;
  844. }
  845. - (UIView *)bottomToolsView {
  846. if (!_bottomToolsView) {
  847. _bottomToolsView = [[UIView alloc] initWithFrame:CGRectMake(0, HX_ScreenHeight, HX_ScreenWidth, 50.f)];
  848. self.bottomMaskLayer.frame = _bottomToolsView.bounds;
  849. [_bottomToolsView.layer insertSublayer:self.bottomMaskLayer atIndex:0];
  850. _bottomToolsView.hidden = YES;
  851. _bottomToolsView.alpha = 0;
  852. [_bottomToolsView addSubview:self.doneBtn];
  853. [_bottomToolsView addSubview:self.videoCropBtn];
  854. }
  855. return _bottomToolsView;
  856. }
  857. - (void)showBottomToolsView {
  858. self.bottomToolsView.hidden = NO;
  859. [UIView animateWithDuration:0.2 animations:^{
  860. self.bottomToolsView.alpha = 1;
  861. self.bottomToolsView.hx_y = HX_ScreenHeight - 50.f - hxBottomMargin;
  862. }];
  863. }
  864. - (void)hideBottomToolsView {
  865. self.bottomToolsView.hidden = YES;
  866. self.bottomToolsView.alpha = 0;
  867. self.bottomToolsView.hx_y = HX_ScreenHeight;
  868. self.videoCropBtn.hidden = NO;
  869. }
  870. - (UIButton *)doneBtn {
  871. if (!_doneBtn) {
  872. _doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  873. [_doneBtn setTitle:[NSBundle hx_localizedStringForKey:@"完成"] forState:UIControlStateNormal];
  874. _doneBtn.hx_h = 30;
  875. _doneBtn.hx_w = 60;
  876. _doneBtn.hx_x = self.view.hx_w - 15 - _doneBtn.hx_w;
  877. _doneBtn.hx_centerY = 50.f / 2;
  878. [_doneBtn setBackgroundColor:self.manager.configuration.cameraFocusBoxColor];
  879. [_doneBtn addTarget:self action:@selector(didDoneBtnClick) forControlEvents:UIControlEventTouchUpInside];
  880. _doneBtn.titleLabel.font = [UIFont hx_mediumPingFangOfSize:15];
  881. [_doneBtn hx_radiusWithRadius:3 corner:UIRectCornerAllCorners];
  882. }
  883. return _doneBtn;
  884. }
  885. - (UIButton *)videoCropBtn {
  886. if (!_videoCropBtn) {
  887. _videoCropBtn = [UIButton buttonWithType:UIButtonTypeSystem];
  888. [_videoCropBtn setImage:[UIImage hx_imageNamed:@"hx_camera_video_crop"] forState:UIControlStateNormal];
  889. [_videoCropBtn addTarget:self action:@selector(didVideoCropBtnClick) forControlEvents:UIControlEventTouchUpInside];
  890. _videoCropBtn.tintColor = [UIColor whiteColor];
  891. _videoCropBtn.hx_h = 50.f;
  892. _videoCropBtn.hx_w = 40.f;
  893. _videoCropBtn.hx_centerY = self.doneBtn.hx_centerY;
  894. _videoCropBtn.hx_x = 15;
  895. }
  896. return _videoCropBtn;
  897. }
  898. - (void)didVideoCropBtnClick {
  899. [self.playVideoView.playerLayer.player pause];
  900. [self.playVideoView.playerLayer.player.currentItem seekToTime:CMTimeMake(0, 1)];
  901. HXWeakSelf
  902. [self hx_presentVideoEditViewControllerWithManager:self.manager videoURL:self.videoURL done:^(HXPhotoModel *beforeModel, HXPhotoModel *afterModel, HXVideoEditViewController *viewController) {
  903. [weakSelf doneCompleteWithModel:afterModel];
  904. BOOL cameraFinishDismissAnimated = weakSelf.manager.cameraFinishDismissAnimated;
  905. [weakSelf.presentingViewController dismissViewControllerAnimated:cameraFinishDismissAnimated completion:^{
  906. if ([weakSelf.delegate respondsToSelector:@selector(customCameraViewControllerFinishDismissCompletion:)]) {
  907. [weakSelf.delegate customCameraViewControllerFinishDismissCompletion:weakSelf];
  908. }
  909. }];
  910. } cancel:^(HXVideoEditViewController *viewController) {
  911. [weakSelf.playVideoView.playerLayer.player play];
  912. }];
  913. }
  914. - (UIVisualEffectView *)effectView {
  915. if (!_effectView) {
  916. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
  917. _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
  918. _effectView.frame = self.previewView.bounds;
  919. }
  920. return _effectView;
  921. }
  922. - (CLLocationManager *)locationManager {
  923. if (!_locationManager) {
  924. _locationManager = [[CLLocationManager alloc] init];
  925. _locationManager.delegate = self;
  926. _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  927. _locationManager.distanceFilter = kCLDistanceFilterNone;
  928. [_locationManager requestWhenInUseAuthorization];
  929. }
  930. return _locationManager;
  931. }
  932. #pragma mark - < CLLocationManagerDelegate >
  933. - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
  934. if (locations.lastObject) {
  935. self.location = locations.lastObject;
  936. }
  937. }
  938. - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
  939. if(error.code == kCLErrorLocationUnknown) {
  940. if (HXShowLog) NSSLog(@"定位失败,无法检索位置");
  941. }
  942. else if(error.code == kCLErrorNetwork) {
  943. if (HXShowLog) NSSLog(@"定位失败,网络问题");
  944. }
  945. else if(error.code == kCLErrorDenied) {
  946. if (HXShowLog) NSSLog(@"定位失败,定位权限的问题");
  947. [self.locationManager stopUpdatingLocation];
  948. self.locationManager = nil;
  949. }
  950. }
  951. @end
  952. @interface HXCustomCameraPlayVideoView ()
  953. @end
  954. @implementation HXCustomCameraPlayVideoView
  955. - (instancetype)initWithFrame:(CGRect)frame {
  956. self = [super initWithFrame:frame];
  957. if (self) {
  958. [self setupUI];
  959. }
  960. return self;
  961. }
  962. - (void)setupUI {
  963. self.playerLayer = [[AVPlayerLayer alloc] init];
  964. self.playerLayer.frame = self.bounds;
  965. self.playerLayer.backgroundColor = [UIColor blackColor].CGColor;
  966. self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
  967. [self.layer addSublayer:self.playerLayer];
  968. }
  969. - (void)setVideoURL:(NSURL *)videoURL {
  970. _videoURL = videoURL;
  971. AVPlayer *player = [AVPlayer playerWithURL:videoURL];
  972. [player play];
  973. self.playerLayer.player = player;
  974. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerNotifacation) name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
  975. }
  976. - (void)pausePlayerNotifacation {
  977. [self.playerLayer.player.currentItem seekToTime:CMTimeMake(0, 1)];
  978. [self.playerLayer.player play];
  979. }
  980. - (void)stopPlay {
  981. [self.playerLayer.player pause];
  982. [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
  983. }
  984. @end