KSMergeAudioControlView.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. //
  2. // KSMergeAudioControlView.m
  3. // KulexiuSchoolStudent
  4. //
  5. // Created by 王智 on 2023/8/29.
  6. //
  7. #import "KSMergeAudioControlView.h"
  8. #import "UIView+KSCovertImage.h"
  9. #define MAX_OFFSET (600)
  10. @interface KSMergeAudioControlView ()
  11. @property (weak, nonatomic) IBOutlet UIView *bgView;
  12. @property (weak, nonatomic) IBOutlet UIView *sliderView;
  13. @property (weak, nonatomic) IBOutlet UIView *pointView;
  14. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *pointLeft;
  15. @property (nonatomic, copy) MergeAudioAction callback;
  16. @property (nonatomic, assign) NSInteger recordVolume;
  17. @property (weak, nonatomic) IBOutlet UISlider *recordSlider;
  18. @property (nonatomic, assign) NSInteger bgVolume;
  19. @property (weak, nonatomic) IBOutlet UISlider *bgSlider;
  20. @property (nonatomic, assign) NSInteger offsetTime;
  21. @property (weak, nonatomic) IBOutlet UILabel *offsetTipsLabel;
  22. @property (weak, nonatomic) IBOutlet UIView *recordBubble;
  23. @property (weak, nonatomic) IBOutlet UILabel *recordBubbleLabel;
  24. @property (weak, nonatomic) IBOutlet UIView *recordGestureView;
  25. @property (weak, nonatomic) IBOutlet UIView *bgBubble;
  26. @property (weak, nonatomic) IBOutlet UILabel *bgVolumeBubble;
  27. @property (weak, nonatomic) IBOutlet UIView *bgGestureView;
  28. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *recordCenterX;
  29. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *bgCenterX;
  30. @property (weak, nonatomic) IBOutlet UILabel *recordTitle;
  31. @property (weak, nonatomic) IBOutlet UIImageView *reRecordImage;
  32. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *recordImgWidth;
  33. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *recordImageRight;
  34. @property (weak, nonatomic) IBOutlet UIButton *recordButton;
  35. @end
  36. @implementation KSMergeAudioControlView
  37. - (void)awakeFromNib {
  38. [super awakeFromNib];
  39. self.bgView.layer.cornerRadius = 16;
  40. self.bgView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMinXMaxYCorner;
  41. UIView *sliderImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 12, 12)];
  42. sliderImg.layer.cornerRadius = 6.0f;
  43. sliderImg.layer.masksToBounds = YES;
  44. sliderImg.backgroundColor = THEMECOLOR;
  45. UIImage *image = [UIView convertViewToImage:sliderImg];
  46. [self.recordSlider setThumbImage:image forState:UIControlStateNormal];
  47. [self.recordSlider setThumbImage:image forState:UIControlStateHighlighted];
  48. [self.bgSlider setThumbImage:image forState:UIControlStateNormal];
  49. [self.bgSlider setThumbImage:image forState:UIControlStateHighlighted];
  50. [self configDefaultVolume];
  51. self.recordTitle.hidden = NO;
  52. self.reRecordImage.hidden = NO;
  53. self.recordImageRight.constant = 20.0f;
  54. self.recordImgWidth.constant = 24.0f;
  55. self.recordButton.userInteractionEnabled = YES;
  56. }
  57. - (void)configDefaultVolume {
  58. self.recordVolume = 100;
  59. self.recordSlider.value = self.recordVolume;
  60. self.bgVolume = 100;
  61. self.bgSlider.value = self.bgVolume;
  62. }
  63. - (void)configWithOffsetTime:(NSInteger)offsetTime {
  64. offsetTime = offsetTime / 10 * 10;
  65. self.offsetTime = offsetTime;
  66. }
  67. - (void)configRecordVolume:(NSInteger)recordVolume bgVolume:(NSInteger)bgVolume {
  68. self.recordVolume = recordVolume;
  69. self.recordSlider.value = recordVolume;
  70. self.bgVolume = bgVolume;
  71. self.bgSlider.value = bgVolume;
  72. // 处理数据
  73. self.recordBubbleLabel.text = [NSString stringWithFormat:@"%zd",bgVolume];
  74. self.recordCenterX.constant = 30 + ((recordVolume *1.0)/ 100)*237;
  75. self.bgVolumeBubble.text = [NSString stringWithFormat:@"%zd",bgVolume];
  76. self.bgCenterX.constant = 30 + ((bgVolume *1.0)/ 100)*237;
  77. }
  78. + (instancetype)shareIntance {
  79. KSMergeAudioControlView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSMergeAudioControlView" owner:nil options:nil] firstObject];
  80. return view;
  81. }
  82. - (void)controlActionCallback:(MergeAudioAction)callback {
  83. if (callback) {
  84. self.callback = callback;
  85. }
  86. }
  87. #pragma mark ----- 音量控制
  88. - (void)configRecordVolumeValue:(NSInteger)volume {
  89. self.recordVolume = volume;
  90. self.recordBubbleLabel.text = [NSString stringWithFormat:@"%zd",volume];
  91. self.recordCenterX.constant = 30 + ((volume *1.0)/ 100)*237;
  92. [UIView animateWithDuration:0.1f animations:^{
  93. [self layoutIfNeeded];
  94. } completion:^(BOOL finished) {
  95. if (finished) {
  96. self.recordBubble.hidden = NO;
  97. }
  98. }];
  99. }
  100. - (void)configBgVolumeValue:(NSInteger)volume {
  101. self.bgVolume = volume;
  102. self.bgVolumeBubble.text = [NSString stringWithFormat:@"%zd",volume];
  103. self.bgCenterX.constant = 30 + ((volume *1.0)/ 100)*237;
  104. [UIView animateWithDuration:0.1f animations:^{
  105. [self layoutIfNeeded];
  106. } completion:^(BOOL finished) {
  107. if (finished) {
  108. self.bgBubble.hidden =NO;
  109. }
  110. }];
  111. }
  112. - (IBAction)cancleMerge:(id)sender {
  113. if (self.callback) {
  114. self.callback(MERGEACTION_CANCLE, self.recordVolume, self.bgVolume, self.offsetTime);
  115. }
  116. }
  117. - (IBAction)saveFile:(id)sender {
  118. if (self.callback) {
  119. self.callback(MERGEACTION_SAVE, self.recordVolume, self.bgVolume, self.offsetTime);
  120. }
  121. }
  122. - (IBAction)uploadFile:(id)sender {
  123. if (self.callback) {
  124. self.callback(MERGEACTION_UPLOAD, self.recordVolume, self.bgVolume, self.offsetTime);
  125. }
  126. }
  127. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  128. if ([[(UITouch *)touches.anyObject view] isEqual:self.recordGestureView]) {
  129. self.recordBubble.hidden = NO;
  130. }
  131. else if ([[(UITouch *)touches.anyObject view] isEqual:self.bgGestureView]) {
  132. self.bgBubble.hidden = NO;
  133. }
  134. [super touchesBegan:touches withEvent:event];
  135. }
  136. - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  137. [super touchesMoved:touches withEvent:event];
  138. if ([[(UITouch *)touches.anyObject view] isEqual:self.sliderView]) {
  139. CGPoint tempPoint = [touches.anyObject locationInView:self.sliderView];
  140. if (tempPoint.x <= 90.5) {
  141. NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
  142. if (offset < -MAX_OFFSET) {
  143. offset = -MAX_OFFSET;
  144. }
  145. self.offsetTime = offset;
  146. }
  147. else if (tempPoint.x > 90.5) {
  148. NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
  149. if (offset > MAX_OFFSET) {
  150. offset = MAX_OFFSET;
  151. }
  152. self.offsetTime = offset;
  153. }
  154. }
  155. else if ([[(UITouch *)touches.anyObject view] isEqual:self.recordGestureView]) {
  156. CGPoint tempPoint = [touches.anyObject locationInView:self.recordGestureView];
  157. CGFloat xPosition = tempPoint.x;
  158. CGFloat width = self.recordGestureView.frame.size.width;
  159. if (xPosition < 0) {
  160. xPosition = 0;
  161. }
  162. else if (xPosition > width) {
  163. xPosition = width;
  164. }
  165. NSInteger value = (xPosition / width) * 100;
  166. [self.recordSlider setValue:value animated:YES];
  167. [self configRecordVolumeValue:value];
  168. }
  169. else if ([[(UITouch *)touches.anyObject view] isEqual:self.bgGestureView]) {
  170. CGPoint tempPoint = [touches.anyObject locationInView:self.bgGestureView];
  171. CGFloat xPosition = tempPoint.x;
  172. CGFloat width = self.recordGestureView.frame.size.width;
  173. if (xPosition < 0) {
  174. xPosition = 0;
  175. }
  176. else if (xPosition > width) {
  177. xPosition = width;
  178. }
  179. NSInteger value = (xPosition / width) * 100;
  180. [self.bgSlider setValue:value animated:YES];
  181. [self configBgVolumeValue:value];
  182. }
  183. }
  184. - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  185. [super touchesEnded:touches withEvent:event];
  186. if ([[(UITouch *)touches.anyObject view] isEqual:self.recordGestureView]) {
  187. CGPoint tempPoint = [touches.anyObject locationInView:self.recordGestureView];
  188. CGFloat xPosition = tempPoint.x;
  189. CGFloat width = self.recordGestureView.frame.size.width;
  190. if (xPosition < 0) {
  191. xPosition = 0;
  192. }
  193. else if (xPosition > width) {
  194. xPosition = width;
  195. }
  196. NSInteger value = (xPosition / width) * 100;
  197. [self refreshRecordValue:value];
  198. }
  199. else if ([[(UITouch *)touches.anyObject view] isEqual:self.bgGestureView]) {
  200. CGPoint tempPoint = [touches.anyObject locationInView:self.bgGestureView];
  201. CGFloat xPosition = tempPoint.x;
  202. CGFloat width = self.recordGestureView.frame.size.width;
  203. if (xPosition < 0) {
  204. xPosition = 0;
  205. }
  206. else if (xPosition > width) {
  207. xPosition = width;
  208. }
  209. NSInteger value = (xPosition / width) * 100;
  210. [self refreshBgValue:value];
  211. }
  212. else if ([[(UITouch *)touches.anyObject view] isEqual:self.sliderView]) {
  213. CGPoint tempPoint = [touches.anyObject locationInView:self.sliderView];
  214. if (tempPoint.x <= 90.5) {
  215. NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
  216. if (offset < -MAX_OFFSET) {
  217. offset = -MAX_OFFSET;
  218. }
  219. self.offsetTime = offset;
  220. }
  221. else if (tempPoint.x > 90.5) {
  222. NSInteger offset = (NSInteger)(tempPoint.x - 90.5) / 3 * 10 * 2;
  223. if (offset > MAX_OFFSET) {
  224. offset = MAX_OFFSET;
  225. }
  226. self.offsetTime = offset;
  227. }
  228. NSLog(@"---- offset - %zd", self.offsetTime);
  229. if (self.callback) {
  230. self.callback(MERGEACTION_DELAY, self.recordVolume, self.bgVolume, self.offsetTime);
  231. }
  232. }
  233. }
  234. - (void)refreshRecordValue:(NSInteger)value {
  235. NSLog(@"---- record volume ---- %zd", value);
  236. [self.recordSlider setValue:value animated:NO];
  237. [self configRecordVolumeValue:value];
  238. if (self.callback) {
  239. self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
  240. }
  241. @weakObj(self);
  242. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
  243. @strongObj(self);
  244. self.recordBubble.hidden = YES;
  245. });
  246. }
  247. - (void)refreshBgValue:(NSInteger)value {
  248. NSLog(@"---- bg volume ---- %zd", value);
  249. [self.bgSlider setValue:value animated:NO];
  250. [self configBgVolumeValue:value];
  251. if (self.callback) {
  252. self.callback(MERGEACTION_MODIFY, self.recordVolume, self.bgVolume, self.offsetTime);
  253. }
  254. @weakObj(self);
  255. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(500 * NSEC_PER_MSEC)), dispatch_get_main_queue(), ^{
  256. @strongObj(self);
  257. self.bgBubble.hidden = YES;
  258. });
  259. }
  260. - (IBAction)leftAction:(id)sender {
  261. if (self.offsetTime <= -MAX_OFFSET) {
  262. self.offsetTime = -MAX_OFFSET;
  263. return;
  264. }
  265. self.offsetTime -= 10;
  266. if (self.callback) {
  267. self.callback(MERGEACTION_DELAY, self.recordVolume, self.bgVolume, self.offsetTime);
  268. }
  269. }
  270. - (IBAction)rightAction:(id)sender {
  271. if (self.offsetTime >= MAX_OFFSET) {
  272. self.offsetTime = MAX_OFFSET;
  273. return;
  274. }
  275. self.offsetTime += 10;
  276. if (self.callback) {
  277. self.callback(MERGEACTION_DELAY, self.recordVolume, self.bgVolume, self.offsetTime);
  278. }
  279. }
  280. - (IBAction)hideAction:(id)sender {
  281. if (self.callback) {
  282. self.callback(MERGEACTION_HIDEVIEW, self.recordVolume, self.bgVolume, self.offsetTime);
  283. }
  284. }
  285. #pragma mark ------ lazying
  286. - (void)setOffsetTime:(NSInteger)offsetTime {
  287. _offsetTime = offsetTime;
  288. NSString *tips = @"";
  289. if (offsetTime > 0) {
  290. tips = [NSString stringWithFormat:@"演奏提前%zd毫秒", labs(offsetTime)];
  291. self.pointLeft.constant = 87 + labs(offsetTime) / 20.0 * 3;
  292. }
  293. else if (offsetTime == 0) {
  294. tips = @"拖动指针移动演奏音频";
  295. self.pointLeft.constant = 87;
  296. }
  297. else {
  298. tips = [NSString stringWithFormat:@"演奏延后%zd毫秒", labs(offsetTime)];
  299. self.pointLeft.constant = 87 - labs(offsetTime) / 20.0 * 3;
  300. }
  301. self.offsetTipsLabel.text = tips;
  302. }
  303. - (void)setHideBackView:(BOOL)hideBackView {
  304. _hideBackView = hideBackView;
  305. if (hideBackView) {
  306. self.recordTitle.hidden = YES;
  307. self.reRecordImage.hidden = YES;
  308. self.recordImageRight.constant = 0.0f;
  309. self.recordImgWidth.constant = 0.0f;
  310. self.recordButton.userInteractionEnabled = NO;
  311. }
  312. else {
  313. self.recordTitle.hidden = NO;
  314. self.reRecordImage.hidden = NO;
  315. self.recordImageRight.constant = 20.0f;
  316. self.recordImgWidth.constant = 24.0f;
  317. self.recordButton.userInteractionEnabled = YES;
  318. }
  319. }
  320. /*
  321. // Only override drawRect: if you perform custom drawing.
  322. // An empty implementation adversely affects performance during animation.
  323. - (void)drawRect:(CGRect)rect {
  324. // Drawing code
  325. }
  326. */
  327. @end