You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
11 KiB
324 lines
11 KiB
// |
|
// CKAudioProgressView.m |
|
// CKAudioProgress |
|
// |
|
// Created by guo on 2019/5/14. |
|
// Copyright © 2019 guo. All rights reserved. |
|
// |
|
|
|
#import "CKAudioProgressView.h" |
|
#import "CALayer+CKViewCategory.h" |
|
|
|
@interface CKAudioProgressView() |
|
|
|
@property (nonatomic, assign) BOOL isSliding; |
|
@property (nonatomic, assign) NSInteger audioLength; |
|
|
|
@property (nonatomic, strong) UIView *slideView; |
|
@property (nonatomic, strong) UILabel *lb_time; |
|
// 进度指示器 |
|
@property (nonatomic, strong) UILabel *lb_indicator; |
|
@property (nonatomic, strong) CALayer *bgLayer; |
|
@property (nonatomic, strong) CALayer *cachedLayer; |
|
@property (nonatomic, strong) UIView *progressLineView; |
|
|
|
@end |
|
|
|
@implementation CKAudioProgressView |
|
|
|
- (instancetype)initWithFrame:(CGRect)frame type:(CKAudioProgressType)progressType { |
|
self = [super initWithFrame:frame]; |
|
if (self) { |
|
[self initViews]; |
|
} |
|
return self; |
|
} |
|
|
|
- (void)initViews { |
|
|
|
[self.layer addSublayer:self.bgLayer]; |
|
[self.layer addSublayer:self.cachedLayer]; |
|
[self addSubview:self.progressLineView]; |
|
|
|
[self addSubview:self.lb_indicator]; |
|
|
|
[self addSubview:self.lb_time]; |
|
|
|
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)]]; |
|
|
|
[self setNeedsLayout]; |
|
} |
|
|
|
- (void)layoutSubviews |
|
{ |
|
[super layoutSubviews]; |
|
CGFloat originY = (self.bounds.size.height-2)/2; |
|
self.bgLayer.ckOriginY = originY; |
|
self.bgLayer.ckWidth = self.frame.size.width; |
|
self.cachedLayer.ckOriginY = originY; |
|
self.progressLineView.ckOriginY = originY; |
|
|
|
_lb_time.ckOriginY = (self.bounds.size.height-_lb_time.bounds.size.height)/2; |
|
} |
|
|
|
#pragma mark - Action |
|
static CGFloat percent = 0.0; |
|
- (void)timeLabelPanGesture:(UIPanGestureRecognizer *)gesture |
|
{ |
|
UIGestureRecognizerState state = gesture.state; |
|
if (UIGestureRecognizerStateBegan == state) { |
|
_isSliding = YES; |
|
percent = 0.0; |
|
if (_delegate && [_delegate respondsToSelector:@selector(audioProgressTouchBegin)]) { |
|
[_delegate audioProgressTouchBegin]; |
|
} |
|
|
|
[UIView animateWithDuration:kAnimatedDurationFast animations:^{ |
|
self.lb_indicator.alpha = 1; |
|
}]; |
|
|
|
} else if (UIGestureRecognizerStateChanged == state) { |
|
CGPoint translation = [gesture translationInView:self]; |
|
CGPoint slideViewCenter = CGPointMake(gesture.view.center.x+ translation.x, gesture.view.center.y); |
|
slideViewCenter.x = MAX(gesture.view.bounds.size.width/2, slideViewCenter.x); |
|
slideViewCenter.x = MIN(self.bounds.size.width-gesture.view.bounds.size.width/2, slideViewCenter.x); |
|
gesture.view.center = slideViewCenter; |
|
[gesture setTranslation:CGPointZero inView:self]; |
|
|
|
_progressLineView.width = gesture.view.frame.origin.x; |
|
|
|
CGFloat totalWith = self.bounds.size.width - _lb_time.bounds.size.width; |
|
NSInteger audioProgress = gesture.view.frame.origin.x / totalWith * self.audioLength; |
|
|
|
percent = gesture.view.frame.origin.x / totalWith; |
|
|
|
[self setProgress:audioProgress total:self.audioLength]; |
|
|
|
self.lb_indicator.ckOriginY = _lb_time.origin.y - 45; |
|
self.lb_indicator.ckCenterX = _lb_time.center.x; |
|
|
|
} else if (UIGestureRecognizerStateEnded == state || UIGestureRecognizerStateCancelled == state) { |
|
_isSliding = NO; |
|
|
|
NSInteger audioProgress = gesture.view.frame.origin.x / (self.bounds.size.width - _lb_time.bounds.size.width) * self.audioLength; |
|
|
|
[UIView animateWithDuration:kAnimatedDurationFast animations:^{ |
|
self.lb_indicator.alpha = 0; |
|
}]; |
|
|
|
if (_delegate && [_delegate respondsToSelector:@selector(audioProgresstouchEndhCurrentTime:totalTime:)]) { |
|
[_delegate audioProgresstouchEndhCurrentTime:audioProgress totalTime:self.audioLength]; |
|
} |
|
} |
|
} |
|
|
|
- (void)tapGesture:(UITapGestureRecognizer *)gesture |
|
{ |
|
CGPoint translation = [gesture locationInView:self]; |
|
|
|
NSInteger audioProgress = translation.x / self.bounds.size.width * self.audioLength; |
|
|
|
[self setProgress:audioProgress total:self.audioLength]; |
|
|
|
if (_delegate && [_delegate respondsToSelector:@selector(audioProgresstouchEndhCurrentTime:totalTime:)]) { |
|
[_delegate audioProgresstouchEndhCurrentTime:audioProgress totalTime:self.audioLength]; |
|
} |
|
} |
|
|
|
- (void)setProgress:(NSInteger)progress total:(NSInteger)total |
|
{ |
|
NSString *title = @""; |
|
if (total >= 3600) { |
|
title = [NSString stringWithFormat:@"%@/%@", [TFUtilsHelper getHourTimeTransformationWithTotalTimeLenght:progress], [TFUtilsHelper getHourTimeTransformationWithTotalTimeLenght:total]]; |
|
} else { |
|
title = [NSString stringWithFormat:@"%@/%@", [TFUtilsHelper getMinuteTimeTransformationWithTotalTimeLenght:progress], [TFUtilsHelper getMinuteTimeTransformationWithTotalTimeLenght:total]]; |
|
} |
|
_lb_time.text = title; |
|
|
|
if (self.lb_indicator.alpha > 0) { |
|
self.lb_indicator.text = title; |
|
} |
|
} |
|
|
|
- (void)updateProgress:(CGFloat)progress audioLength:(NSInteger)audioLength |
|
{ |
|
if (isnan(percent) || isinf(percent)) { |
|
percent = 0; |
|
} |
|
if (audioLength <= 0) { |
|
_lb_time.text = @"00:00/00:00"; |
|
self.lb_indicator.text = @"00:00/00:00"; |
|
_lb_time.xtfei_x = 0; |
|
_progressLineView.xtfei_width = 0; |
|
return; |
|
} |
|
|
|
if (progress > 1) { |
|
percent = 1; |
|
} else if (progress < 0) { |
|
percent = 0; |
|
} else { |
|
percent = progress; |
|
} |
|
|
|
if (!_isSliding) { |
|
|
|
self.audioLength = audioLength; |
|
|
|
[self setProgress:(NSInteger)(percent*audioLength) total:audioLength]; |
|
|
|
CGFloat totalWith = self.bounds.size.width-_lb_time.bounds.size.width; |
|
CGFloat playedWidth = totalWith*percent; |
|
_progressLineView.width = playedWidth; |
|
_lb_time.ckCenterX = playedWidth+_lb_time.bounds.size.width/2; |
|
} |
|
} |
|
|
|
- (void)updateCacheProgress:(CGFloat)progress |
|
{ |
|
if (!isnan(progress)) { |
|
self.cachedLayer.ckWidth = self.frame.size.width * progress; |
|
} |
|
} |
|
|
|
#pragma mark - Getter & Setter |
|
|
|
- (void)setCachedBgColor:(UIColor *)cachedBgColor { |
|
if (cachedBgColor) { |
|
_cachedBgColor = cachedBgColor; |
|
self.cachedLayer.backgroundColor = cachedBgColor.CGColor; |
|
} |
|
} |
|
- (void)setProgressBgColor:(UIColor *)progressBgColor { |
|
if (progressBgColor) { |
|
_progressBgColor = progressBgColor; |
|
self.bgLayer.backgroundColor = progressBgColor.CGColor; |
|
} |
|
} |
|
|
|
- (void)setCornerRadius:(CGFloat)cornerRadius { |
|
_cornerRadius = cornerRadius; |
|
self.cornerRadius = cornerRadius; |
|
self.bgLayer.cornerRadius = cornerRadius; |
|
self.cachedLayer.cornerRadius = cornerRadius; |
|
self.progressLineView.layer.cornerRadius = cornerRadius; |
|
} |
|
|
|
- (void)setColors:(NSArray *)colors { |
|
if (!_playedBgColor && colors) { |
|
_colors = colors; |
|
} |
|
} |
|
- (void)setPlayedBgColor:(UIColor *)playedBgColor { |
|
if (!_colors && playedBgColor) { |
|
_playedBgColor = playedBgColor; |
|
self.progressLineView.backgroundColor = playedBgColor; |
|
} |
|
} |
|
|
|
- (void)setSlideViewBounds:(CGRect)slideViewBounds { |
|
if (slideViewBounds.size.width > 0) { |
|
_slideViewBounds = slideViewBounds; |
|
|
|
self.lb_time.bounds = slideViewBounds; |
|
[self setNeedsLayout]; |
|
} |
|
} |
|
|
|
- (void)setTotalTimeLength:(NSInteger)totalTimeLength |
|
{ |
|
_totalTimeLength = totalTimeLength; |
|
if (totalTimeLength >= 0) { |
|
|
|
NSString *title = @""; |
|
if (totalTimeLength >= 3600) { |
|
title = [NSString stringWithFormat:@"%@/%@", [TFUtilsHelper getHourTimeTransformationWithTotalTimeLenght:totalTimeLength], [TFUtilsHelper getHourTimeTransformationWithTotalTimeLenght:totalTimeLength]]; |
|
} else { |
|
title = [NSString stringWithFormat:@"%@/%@", [TFUtilsHelper getMinuteTimeTransformationWithTotalTimeLenght:totalTimeLength], [TFUtilsHelper getMinuteTimeTransformationWithTotalTimeLenght:totalTimeLength]]; |
|
} |
|
_lb_time.xtfei_width = [TFViewHelper getDynamicWidthWithLabelFont:[UIFont systemFontOfSize:10] labelHeight:20 labelText:title] + kHalfMargin; |
|
_lb_indicator.xtfei_width = [TFViewHelper getDynamicWidthWithLabelFont:kFont12 labelHeight:30 labelText:title] + kHalfMargin; |
|
} |
|
} |
|
|
|
- (CALayer *)bgLayer { |
|
if (!_bgLayer) { |
|
_bgLayer = [CALayer layer]; |
|
_bgLayer.backgroundColor = _progressBgColor ? _progressBgColor.CGColor : [UIColor colorWithRed:242/255.0 green:242/255.0 blue:242/255.0 alpha:1].CGColor; |
|
_bgLayer.frame = CGRectMake(0, (self.bounds.size.height-2)/2, self.bounds.size.width, 2); |
|
} |
|
return _bgLayer; |
|
} |
|
|
|
- (CALayer *)cachedLayer { |
|
if (!_cachedLayer) { |
|
_cachedLayer = [CALayer layer]; |
|
_cachedLayer.backgroundColor = [UIColor colorWithRed:230/255.0 green:230/255.0 blue:230/255.0 alpha:1.0].CGColor; |
|
_cachedLayer.frame = CGRectMake(0, (self.bounds.size.height-2)/2, 0, 2); |
|
} |
|
return _cachedLayer; |
|
} |
|
|
|
- (UIView *)progressLineView { |
|
if (!_progressLineView) { |
|
_progressLineView = [[UIView alloc] init]; |
|
_progressLineView.frame = CGRectMake(0, (self.bounds.size.height - 2 ) / 2, 0, 2); |
|
} |
|
return _progressLineView; |
|
} |
|
|
|
- (UIView *)slideView { |
|
if (!_slideView) { |
|
_slideView = [UIView new]; |
|
_slideView.frame = CGRectMake(-(24-24/2-12/2), 0, 24, 24); |
|
CAShapeLayer *dotLayer = [CAShapeLayer layer]; |
|
dotLayer.fillColor = [UIColor whiteColor].CGColor; |
|
dotLayer.frame = CGRectMake((24-12)/2, (24-12)/2, 12, 12); |
|
dotLayer.cornerRadius = 6; |
|
dotLayer.shadowColor = [UIColor colorWithRed:255/255.0 green:120/255.0 blue:2/255.0 alpha:1.0].CGColor; |
|
dotLayer.shadowOffset = CGSizeMake(0,0); |
|
dotLayer.shadowOpacity = 1; |
|
dotLayer.shadowRadius = 10; |
|
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:dotLayer.bounds]; |
|
dotLayer.path = path.CGPath; |
|
[_slideView.layer addSublayer:dotLayer]; |
|
} |
|
return _slideView; |
|
} |
|
|
|
- (UILabel *)lb_indicator |
|
{ |
|
if (!_lb_indicator) { |
|
_lb_indicator = [[UILabel alloc] init]; |
|
_lb_indicator.font = kFont12; |
|
_lb_indicator.textAlignment = NSTextAlignmentCenter; |
|
_lb_indicator.textColor = kWhiteColor; |
|
_lb_indicator.frame = CGRectMake(0, 0, 92, 30); |
|
_lb_indicator.alpha = 0; |
|
_lb_indicator.layer.cornerRadius = 15; |
|
_lb_indicator.layer.backgroundColor = kColorRGBA(0, 0, 0, 0.7).CGColor; |
|
_lb_indicator.userInteractionEnabled = YES; |
|
} |
|
return _lb_indicator; |
|
} |
|
|
|
- (UILabel *)lb_time { |
|
if (!_lb_time) { |
|
_lb_time = [UILabel new]; |
|
_lb_time.font = [UIFont systemFontOfSize:10]; |
|
_lb_time.textAlignment = NSTextAlignmentCenter; |
|
_lb_time.textColor = kGrayTextDeepColor; |
|
_lb_time.frame = CGRectMake(0, 0, 72, 20); |
|
_lb_time.layer.cornerRadius = 10; |
|
_lb_time.layer.shadowColor = [UIColor colorWithRed:87/255.0 green:92/255.0 blue:111/255.0 alpha:0.5].CGColor; |
|
_lb_time.layer.shadowOffset = CGSizeMake(0,0); |
|
_lb_time.layer.shadowOpacity = 3; |
|
_lb_time.layer.shadowRadius = 1; |
|
_lb_time.layer.backgroundColor = kWhiteColor.CGColor; |
|
_lb_time.userInteractionEnabled = YES; |
|
[_lb_time addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(timeLabelPanGesture:)]]; |
|
} |
|
return _lb_time; |
|
} |
|
|
|
@end
|
|
|