123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- //
- // DFPlayerUIManager.m
- // DFPlayer
- //
- // Created by ihoudf on 2017/7/20.
- // Copyright © 2017年 ihoudf. All rights reserved.
- //
- #import "DFPlayerUIManager.h"
- #import "DFPlayer.h"
- #import "DFPlayerTool.h"
- #import "DFPlayerLyricsTableview.h"
- #import <MediaPlayer/MediaPlayer.h>
- #pragma mark - DFPlayerSlider
- @interface DFPlayerSlider : UISlider
- @property (nonatomic, assign) CGFloat trackHeight;
- @end
- @implementation DFPlayerSlider
- - (CGRect)trackRectForBounds:(CGRect)bounds{
- return CGRectMake(0, (CGRectGetHeight(self.frame)-self.trackHeight) / 2, CGRectGetWidth(self.frame), self.trackHeight);
- }
- @end
- #pragma mark - DFPlayer控制管理器
- //KEY
- NSString * const DFStateKey = @"state";
- NSString * const DFBufferProgressKey = @"bufferProgress";
- NSString * const DFProgressKey = @"progress";
- NSString * const DFCurrentTimeKey = @"currentTime";
- NSString * const DFTotalTimeKey = @"totalTime";
- typedef void(^DFPlayerLyricsBlock)(NSString *onPlayingLyrics);
- @interface DFPlayerUIManager() <DFPlayerLyricsTableviewDelegate>
- {
- BOOL _stopUpdate;
- BOOL _isSeek;
- }
- @property (nonatomic, strong) UIButton *playBtn;
- @property (nonatomic, strong) UIButton *typeBtn;
- @property (nonatomic, strong) UIProgressView *bufferProgressView;
- @property (nonatomic, strong) DFPlayerSlider *progressSlider;
- @property (nonatomic, strong) UILabel *currentTimeLabel;
- @property (nonatomic, strong) UILabel *totalTimeLabel;
- @property (nonatomic, strong) DFPlayerLyricsTableview *lyricsTableView;
- @property (nonatomic, copy) DFPlayerLyricsBlock lyricsBlock;
- @property (nonatomic, strong) UIImage *playImage;
- @property (nonatomic, strong) UIImage *pauseImage;
- @property (nonatomic, strong) UIImage *singleImage;
- @property (nonatomic, strong) UIImage *circleImage;
- @property (nonatomic, strong) UIImage *shuffleImage;
- @end
- @implementation DFPlayerUIManager
- + (DFPlayerUIManager *)sharedManager{
- static DFPlayerUIManager *manager = nil;
- static dispatch_once_t predicate;
- dispatch_once(&predicate, ^{
- manager = [[[self class] alloc] init];
- });
- return manager;
- }
- - (UIButton *)button:(CGRect)frame
- image:(UIImage *)image
- superView:(UIView *)superView
- block:(nullable void (^)(void))block
- action:(nullable void(^)(void))action{
- UIButton *btn = [UIButton buttonWithType:(UIButtonTypeSystem)];
- btn.frame = frame;
- [btn setBackgroundImage:image forState:(UIControlStateNormal)];
- btn.handleButtonActionBlock = ^(UIButton * _Nullable sender) {
- if (block) {
- block();
- }
- if (action) {
- action();
- }
- };
- [superView addSubview:btn];
- return btn;
- }
- - (UILabel *)label:(CGRect)frame
- textColor:(UIColor *)textColor
- textAlignment:(NSTextAlignment)textAlignment
- font:(UIFont *)font
- superView:(UIView *)superView
- observerKey:(NSString *)observerKey{
- UILabel *label = [[UILabel alloc] initWithFrame:frame];
- label.text = @"00:00";
- label.textColor = textColor;
- label.textAlignment = textAlignment;
- label.font = font;
- [superView addSubview:label];
- [[DFPlayer sharedPlayer] addObserver:self forKeyPath:observerKey options:NSKeyValueObservingOptionNew context:nil];
- return label;
- }
- - (void)df_stopUpdate{
- _stopUpdate = YES;
- self.lyricsTableView.stopUpdate = YES;
- }
- - (void)df_resumeUpdate{
- _stopUpdate = NO;
- self.lyricsTableView.stopUpdate = NO;
- }
- #pragma mark - 播放暂停按钮
- - (UIButton *)df_playPauseBtnWithFrame:(CGRect)frame
- playImage:(UIImage *)playImage
- pauseImage:(UIImage *)pauseImage
- superView:(UIView *)superView
- block:(nullable void (^)(void))block{
- self.playImage = playImage;
- self.pauseImage = pauseImage;
- UIImage *img = [DFPlayer sharedPlayer].state == DFPlayerStatePlaying ? self.playImage : self.pauseImage;
- self.playBtn = [self button:frame image:img superView:superView block:block action:^{
- if ([DFPlayer sharedPlayer].state == DFPlayerStatePlaying) {
- [[DFPlayer sharedPlayer] df_pause];
- }else{
- [[DFPlayer sharedPlayer] df_play];
- }
- }];
- [[DFPlayer sharedPlayer] addObserver:self forKeyPath:DFStateKey options:NSKeyValueObservingOptionNew context:nil];
- return self.playBtn;
- }
- #pragma mark - 上一首按钮
- - (UIButton *)df_lastBtnWithFrame:(CGRect)frame
- image:(UIImage *)image
- superView:(UIView *)superView
- block:(void (^)(void))block{
- return [self button:frame image:image superView:superView block:block action:^{
- [[DFPlayer sharedPlayer] df_last];
- }];
- }
- #pragma mark - 下一首按钮
- - (UIButton *)df_nextBtnWithFrame:(CGRect)frame
- image:(UIImage *)image
- superView:(UIView *)superView
- block:(void (^)(void))block{
- return [self button:frame image:image superView:superView block:block action:^{
- [[DFPlayer sharedPlayer] df_next];
- }];
- }
- #pragma mark - 播放模式设置按钮
- - (UIButton *)df_typeBtnWithFrame:(CGRect)frame
- singleImage:(UIImage *)singleImage
- circleImage:(UIImage *)circleImage
- shuffleImage:(UIImage *)shuffleImage
- superView:(UIView *)superView
- block:(void (^)(void))block{
-
- if ([DFPlayer sharedPlayer].playMode == DFPlayerModeOnlyOnce) {
- return nil;
- }
- self.singleImage = singleImage;
- self.circleImage = circleImage;
- self.shuffleImage = shuffleImage;
-
- UIImage *img = [UIImage new];
- if ([DFPlayer sharedPlayer].playMode == DFPlayerModeSingleCycle) {
- img = self.singleImage;
- }else if ([DFPlayer sharedPlayer].playMode == DFPlayerModeOrderCycle){
- img = self.circleImage;
- }else{
- img = self.shuffleImage;
- }
- UIButton *btn = [self button:frame image:img superView:superView block:block action:nil];
- btn.handleButtonActionBlock = ^(UIButton * _Nullable sender) {
- switch ([DFPlayer sharedPlayer].playMode) {
- case DFPlayerModeSingleCycle:
- [DFPlayer sharedPlayer].playMode = DFPlayerModeOrderCycle;
- [sender setBackgroundImage:self.circleImage forState:(UIControlStateNormal)];
- break;
- case DFPlayerModeOrderCycle:
- [DFPlayer sharedPlayer].playMode = DFPlayerModeShuffleCycle;
- [sender setBackgroundImage:self.shuffleImage forState:(UIControlStateNormal)];
- break;
- case DFPlayerModeShuffleCycle:
- [DFPlayer sharedPlayer].playMode = DFPlayerModeSingleCycle;
- [sender setBackgroundImage:self.singleImage forState:(UIControlStateNormal)];
- break;
- default:
- break;
- }
- };
- return btn;
- }
- #pragma mark - 音频当前时间
- - (UILabel *)df_currentTimeLabelWithFrame:(CGRect)frame
- textColor:(UIColor *)textColor
- textAlignment:(NSTextAlignment)textAlignment
- font:(UIFont *)font
- superView:(UIView *)superView{
- self.currentTimeLabel = [self label:frame textColor:textColor textAlignment:textAlignment font:font superView:superView observerKey:DFCurrentTimeKey];
- return self.currentTimeLabel;
- }
- #pragma mark - 音频总时长
- - (UILabel *)df_totalTimeLabelWithFrame:(CGRect)frame
- textColor:(UIColor *)textColor
- textAlignment:(NSTextAlignment)textAlignment
- font:(UIFont *)font
- superView:(UIView *)superView{
- self.totalTimeLabel = [self label:frame textColor:textColor textAlignment:textAlignment font:font superView:superView observerKey:DFTotalTimeKey];
- return self.totalTimeLabel;
- }
- #pragma mark - 缓冲进度条
- - (UIProgressView *)df_bufferViewWithFrame:(CGRect)frame
- trackTintColor:(UIColor *)trackTintColor
- progressTintColor:(UIColor *)progressTintColor
- superView:(UIView *)superView{
- self.bufferProgressView = [[UIProgressView alloc] initWithFrame:frame];
- self.bufferProgressView.trackTintColor = trackTintColor;
- self.bufferProgressView.progressTintColor = progressTintColor;
- [superView addSubview:self.bufferProgressView];
- [[DFPlayer sharedPlayer] addObserver:self forKeyPath:DFBufferProgressKey options:NSKeyValueObservingOptionNew context:nil];
- return self.bufferProgressView;
- }
- #pragma mark - 播放进度条
- - (UISlider *)df_sliderWithFrame:(CGRect)frame
- minimumTrackTintColor:(UIColor *)minimumTrackTintColor
- maximumTrackTintColor:(UIColor *)maximumTrackTintColor
- trackHeight:(CGFloat)trackHeight
- thumbImage:(UIImage *)thumbImage
- superView:(UIView *)superView{
- self.progressSlider = [[DFPlayerSlider alloc] initWithFrame:frame];
- self.progressSlider.trackHeight = trackHeight;
- [self.progressSlider setThumbImage:thumbImage forState:UIControlStateNormal];
- self.progressSlider.minimumValue = 0;
- self.progressSlider.maximumValue = 1;
- self.progressSlider.minimumTrackTintColor = minimumTrackTintColor;
- self.progressSlider.maximumTrackTintColor = maximumTrackTintColor;
- [superView addSubview:self.progressSlider];
-
- [[DFPlayer sharedPlayer] addObserver:self forKeyPath:DFProgressKey options:NSKeyValueObservingOptionNew context:nil];
-
- //开始滑动
- [self.progressSlider addTarget:self action:@selector(progressSliderTouchBegan:) forControlEvents:UIControlEventTouchDown];
- //滑动中
- [self.progressSlider addTarget:self action:@selector(progressSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
- //滑动结束
- [self.progressSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchCancel | UIControlEventTouchUpOutside];
- //点击slider
- UITapGestureRecognizer *sliderTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapSliderAction:)];
- [self.progressSlider addGestureRecognizer:sliderTap];
- return self.progressSlider;
- }
- #pragma mark 刷新总时长
- - (void)RefreshTotalTimeLabelFun
- {
- [self configTimeLabel:self.totalTimeLabel time:[DFPlayer sharedPlayer].totalTime];
- }
- - (void)progressSliderTouchBegan:(UISlider *)sender{
- _isSeek = YES;
- }
- - (void)progressSliderValueChanged:(UISlider *)sender{
- CGFloat time = [DFPlayer sharedPlayer].totalTime * self.progressSlider.value;
- [self configTimeLabel:self.currentTimeLabel time:time];
- }
- - (void)progressSliderTouchEnded:(UISlider *)sender{
- [self seek:self.progressSlider.value];
- }
- - (void)handleTapSliderAction:(UITapGestureRecognizer *)tap{
- if ([tap.view isKindOfClass:[UISlider class]]) {
- _isSeek = YES;
- UISlider *slider = (UISlider *)tap.view;
- CGPoint point = [tap locationInView:slider];
- CGFloat value = point.x / slider.frame.size.width;
- [self seek:value];
- }
- }
- - (void)seek:(CGFloat)value{
- [[DFPlayer sharedPlayer] df_seekToTime:value completionBlock:^{
- [[NSNotificationCenter defaultCenter] postNotificationName:DFPlayerNotificationSeekEnd object:nil];
- self->_isSeek = NO;
- }];
- }
- #pragma mark - KVO
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
- if (object == [DFPlayer sharedPlayer]) {
- dispatch_async(dispatch_get_main_queue(), ^{
- if ([keyPath isEqualToString:DFStateKey]) {
- if (!self->_isSeek) {
- UIImage *img = [DFPlayer sharedPlayer].state == (DFPlayerStateBuffering | DFPlayerStatePlaying) ? self.pauseImage : self.playImage;
- [self.playBtn setBackgroundImage:img forState:(UIControlStateNormal)];
- }
- }else{
- if (self->_stopUpdate) {
- return;
- }
- if ([keyPath isEqualToString:DFBufferProgressKey]){
- [self.bufferProgressView setProgress:[DFPlayer sharedPlayer].bufferProgress];
- }else if ([keyPath isEqualToString:DFProgressKey]){
- if (!self->_isSeek) {
- if (self.progressSlider.state != UIControlStateHighlighted) {
- self.progressSlider.value = [DFPlayer sharedPlayer].progress;
- }
- }
- }else if ([keyPath isEqualToString:DFCurrentTimeKey]){
- if (!self->_isSeek) {
- [self configTimeLabel:self.currentTimeLabel time:[DFPlayer sharedPlayer].currentTime];
- }
- }else if ([keyPath isEqualToString:DFTotalTimeKey]){
- [self configTimeLabel:self.totalTimeLabel time:[DFPlayer sharedPlayer].totalTime];
- }
- }
- });
- }
- }
- - (void)configTimeLabel:(UILabel *)label time:(CGFloat)time{
- NSInteger seconds = (NSInteger)time % 60;
- NSInteger minutes = ((NSInteger)time / 60) % 60;
- dispatch_async(dispatch_get_main_queue(), ^{
- label.text = [NSString stringWithFormat:@"%02ld:%02ld",(long)minutes,(long)seconds];
- });
- }
- - (void)dealloc{
- [[DFPlayer sharedPlayer] removeObserver:self forKeyPath:DFStateKey];
- [[DFPlayer sharedPlayer] removeObserver:self forKeyPath:DFBufferProgressKey];
- [[DFPlayer sharedPlayer] removeObserver:self forKeyPath:DFProgressKey];
- [[DFPlayer sharedPlayer] removeObserver:self forKeyPath:DFCurrentTimeKey];
- [[DFPlayer sharedPlayer] removeObserver:self forKeyPath:DFTotalTimeKey];
- }
- #pragma mark - 歌词tableview
- - (UITableView *)df_lyricTableViewWithFrame:(CGRect)frame
- cellRowHeight:(CGFloat)cellRowHeight
- cellBackgroundColor:(UIColor *)cellBackgroundColor
- currentLineLrcForegroundTextColor:(nullable UIColor *)currentLineLrcForegroundTextColor
- currentLineLrcBackgroundTextColor:(UIColor *)currentLineLrcBackgroundTextColor
- otherLineLrcBackgroundTextColor:(UIColor *)otherLineLrcBackgroundTextColor
- currentLineLrcFont:(UIFont *)currentLineLrcFont
- otherLineLrcFont:(UIFont *)otherLineLrcFont
- superView:(UIView *)superView
- block:(nullable void (^)(NSString * onPlayingLyrics))block{
- self.lyricsTableView = [[DFPlayerLyricsTableview alloc] init];
- self.lyricsTableView.frame = frame;
- self.lyricsTableView.backgroundColor = cellBackgroundColor;
- self.lyricsTableView.cellRowHeight = cellRowHeight;
- self.lyricsTableView.cellBackgroundColor = cellBackgroundColor;
- self.lyricsTableView.currentLineLrcForegroundTextColor = currentLineLrcForegroundTextColor;
- self.lyricsTableView.currentLineLrcBackgroundTextColor = currentLineLrcBackgroundTextColor;
- self.lyricsTableView.otherLineLrcBackgroundTextColor = otherLineLrcBackgroundTextColor;
- self.lyricsTableView.currentLineLrcFont = currentLineLrcFont;
- self.lyricsTableView.otherLineLrcFont = otherLineLrcFont;
- self.lyricsTableView.lrcTableViewSuperview = superView;
- self.lyricsTableView.lyricsDelegate = self;
- [superView addSubview:self.lyricsTableView];
- if (block) { self.lyricsBlock = block; }
- return self.lyricsTableView;
- }
- - (void)df_lyricsTableview:(DFPlayerLyricsTableview *)lyricsTableview
- onPlayingLyrics:(NSString *)onPlayingLyrics{
- if (self.lyricsBlock) {
- self.lyricsBlock(onPlayingLyrics);
- }
- }
- /**释放播放器UI*/
- - (void)dfUI_deallocPlayer
- {
- if(_playBtn){
- _playBtn = nil;
- }
-
- if(_typeBtn){
- _typeBtn = nil;
- }
-
- if(_bufferProgressView){
- _bufferProgressView = nil;
- }
-
- if(_progressSlider){
- _progressSlider = nil;
- }
-
- if(_currentTimeLabel){
- _currentTimeLabel = nil;
- }
- if(_totalTimeLabel){
- _totalTimeLabel = nil;
- }
-
- if(_lyricsTableView){
- _lyricsTableView = nil;
- }
-
- if(_playImage){
- _playImage = nil;
- }
-
- if(_pauseImage){
- _pauseImage = nil;
- }
- if(_singleImage){
- _singleImage = nil;
- }
-
- if(_circleImage){
- _circleImage = nil;
- }
-
- if(_shuffleImage){
- _shuffleImage = nil;
- }
- }
- @end
|