音乐播放

这里写图片描述

这里写图片描述

Podfile


# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'SCMusic' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SCMusic

pod 'AFNetworking', '~> 3.0'
pod 'Masonry'
pod 'MBProgressHUD'
pod 'MJExtension'
pod 'MJRefresh'

end

DownloadTool.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AFNetworking.h"
#import "MJExtension.h"
#import "OMHotSongInfo.h"
#import "OMSongInfo.h"

@interface MusicDownloader : NSObject

@property (nonatomic, assign) BOOL isDataRequestFinish;

@property (nonatomic, strong) OMHotSongInfo *hotSonginfo;

@property (nonatomic, copy) void (^completionHandler)(void);

@property (nonatomic, strong) OMSongInfo *songInfo;

-(void) requestData: (NSString *)urlString ;
- (void)startDownload;
- (void)cancelDownload;

@end

DownloadTool.m

#import <UIKit/UIKit.h>
#import "MusicDownloader.h"
#import <AFNetworking/AFNetworking.h>
#import "MJExtension/MJExtension.h"
#import "OMHotSongInfo.h"
#import "OMSongInfo.h"


#define kAppIconSize 48


@interface MusicDownloader()

// the queue to run our "ParseOperation"
@property (nonatomic, strong) NSOperationQueue *queue;

// url session task
@property (nonatomic, strong) NSURLSessionDataTask *sessionTask;

@end


@implementation MusicDownloader

-(instancetype) init {

    self = [super init];
    if (self) {
        _songInfo = OMSongInfo.sharedManager;
    }
    return self;
}



// -------------------------------------------------------------------------------
//  startDownload
// -------------------------------------------------------------------------------
- (void)startDownload
{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.hotSonginfo.pic_small]];

    // create an session data task to obtain and download the app icon
    _sessionTask = [[NSURLSession sharedSession] dataTaskWithRequest:request
   completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

       // in case we want to know the response status code
       //NSInteger HTTPStatusCode = [(NSHTTPURLResponse *)response statusCode];

       if (error != nil)
       {
           if ([error code] == NSURLErrorAppTransportSecurityRequiresSecureConnection)
           {
               // if you get error NSURLErrorAppTransportSecurityRequiresSecureConnection (-1022),
               // then your Info.plist has not been properly configured to match the target server.
               //
               abort();
           }
       }

       [[NSOperationQueue mainQueue] addOperationWithBlock: ^{

           // Set appIcon and clear temporary data/image
           UIImage *image = [[UIImage alloc] initWithData:data];

           if (image.size.width != kAppIconSize || image.size.height != kAppIconSize)
           {
               CGSize itemSize = CGSizeMake(kAppIconSize, kAppIconSize);
               UIGraphicsBeginImageContextWithOptions(itemSize, NO, 0.0f);
               CGRect imageRect = CGRectMake(0.0, 0.0, itemSize.width, itemSize.height);
               [image drawInRect:imageRect];
               self.hotSonginfo.albumImage_small = UIGraphicsGetImageFromCurrentImageContext();
               UIGraphicsEndImageContext();
           }
           else
           {
               self.hotSonginfo.albumImage_small = image;
           }

           // call our completion handler to tell our client that our icon is ready for display
           if (self.completionHandler != nil)
           {
               self.completionHandler();
           }
       }];
   }];

    [self.sessionTask resume];
}

// -------------------------------------------------------------------------------
//  cancelDownload
// -------------------------------------------------------------------------------
- (void)cancelDownload
{
    [self.sessionTask cancel];
    _sessionTask = nil;
}


// -------------------------------------------------------------------------------
//  handleError:error
//  Reports any error with an alert which was received from connection or loading failures.
// -------------------------------------------------------------------------------
- (void)handleError:(NSError *)error
{
    NSString *errorMessage = [error localizedDescription];

    // alert user that our current record was deleted, and then we leave this view controller
    //
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Cannot Show Top Paid Apps"
                                                                   message:errorMessage
                                                            preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *OKAction = [UIAlertAction actionWithTitle:@"OK"
                                                       style:UIAlertActionStyleDefault
                                                     handler:^(UIAlertAction *action) {
                                                         // dissmissal of alert completed
                                                     }];
    [alert addAction:OKAction];
}

@end

MusicPlayerManager.h

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface MusicPlayerManager : NSObject

typedef enum : NSUInteger {
    RepeatPlayMode,
    RepeatOnlyOnePlayMode,
    ShufflePlayMode,
} ShuffleAndRepeatState;

@property (nonatomic,strong) AVPlayer *play;
@property (nonatomic,strong) AVPlayerItem *playItem;
@property (nonatomic,assign) ShuffleAndRepeatState shuffleAndRepeatState;
@property (nonatomic,assign) NSInteger playingIndex;

+ (MusicPlayerManager *)sharedManager;
-(void) setPlayItem: (NSString *)songURL;
-(void) setPlay;
-(void) startPlay;
-(void) stopPlay;
-(void) play: (NSString *)songURL;

@end

MusicPlayerManager.m

#import "MusicPlayerManager.h"


@implementation MusicPlayerManager

static MusicPlayerManager *_sharedManager = nil;

+(MusicPlayerManager *)sharedManager {
    @synchronized( [MusicPlayerManager class] ){
        if(!_sharedManager)
            _sharedManager = [[self alloc] init];
        return _sharedManager;
    }
    return nil;
}


-(void) setPlayItem: (NSString *)songURL {
    NSURL * url  = [NSURL URLWithString:songURL];
    _playItem = [[AVPlayerItem alloc] initWithURL:url];
}

-(void) setPlay {
    _play = [[AVPlayer alloc] initWithPlayerItem:_playItem];
}

-(void) startPlay {
    [_play play];
}

-(void) stopPlay {
    [_play pause];
}

-(void) play: (NSString *)songURL {
    [self setPlayItem:songURL];
    [self setPlay];
    [self startPlay];
}

@end

AppDelegate.h

//无

AppDelegate.m

#import "AppDelegate.h"
#import "RootViewController.h"
#import "NavigationViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <notify.h>
#import "ContentTableViewController.h"


@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    self.window.rootViewController = [[NavigationViewController alloc] initWithRootViewController:[[RootViewController alloc] init]];
    [self.window makeKeyAndVisible];

    // 后台播放音频设置,需要在Capabilities->Background Modes中勾选Audio,Airplay,and Picture in Picture
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setActive:YES error:nil];
    [session setCategory:AVAudioSessionCategoryPlayback error:nil];

    // 设置接受远程控制
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];


    return YES;
}
#import <UIKit/UIKit.h>
#import "RootViewController.h"

@interface NavigationViewController : UINavigationController


@end
#import "NavigationViewController.h"


@implementation NavigationViewController

#pragma mark - viewDidLoad
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //[self.navigationBar setBarTintColor:UIColorFromRGB(0x5c8aea)];

    [self navigationBarSettting];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


// -------------------------------------------------------------------------------
//    navigationBarSettting:
//  Setting navigationBar
// -------------------------------------------------------------------------------
-(void) navigationBarSettting {

    [self.navigationBar setBarTintColor:UIColorFromRGB(0xff0000)];
    [self.navigationBar setTranslucent:NO];
    [self.navigationBar setTintColor:[UIColor whiteColor]];
    [self.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, nil]];

    // 去掉导航分割线
    [self.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
    [self.navigationBar setShadowImage:[[UIImage alloc] init]];
}


@end

RootViewController.h

#import <UIKit/UIKit.h>
#import "AFNetworking.h"
#import "MJExtension.h"
#import "OMHotSongInfo.h"
#import "OMSongInfo.h"
#import "MusicPlayerManager.h"
#import "OMHotSongInfo.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <notify.h>
#import "SCImageView.h"
#import "DetailControlViewController.h"
#import "Const.h"
#import "TTTopChannelContianerView.h"
#import "ContentTableViewController.h"
#import "Masonry.h"

@interface RootViewController : UIViewController <UIScrollViewDelegate,TTTopChannelContianerViewDelegate>

@property (nonatomic, strong) NSMutableArray *currentChannelsArray;
@property (nonatomic, weak) TTTopChannelContianerView *topContianerView;
@property (nonatomic, strong) DetailControlViewController *detailController;
@property (nonatomic, weak) UIScrollView *contentScrollView;
@property (nonatomic, strong) NSArray *arrayLists;


//当前歌词所在位置
@property (nonatomic,assign)  NSInteger currentRow;


//锁屏图片视图,用来绘制带歌词的image
@property (nonatomic, strong) UIImageView * lrcImageView;
@property (nonatomic, strong) UIImage * lastImage;//最后一次锁屏之后的歌词海报

// playControllerView 控件
@property (nonatomic, strong) UIView *playControllerView;
@property (nonatomic, strong) SCImageView *currentPlaySongImage;
@property (nonatomic, strong) UIButton *playAndPauseButton;
@property (nonatomic, strong) UIButton *nextSongButton;
@property (nonatomic, strong) UISlider *songSlider;
@property (nonatomic, strong) UILabel *songName;
@property (nonatomic, strong) UILabel *singerName;

@property (nonatomic, strong) id playerTimeObserver;

@end

RootViewController.m

#import "RootViewController.h"


MusicPlayerManager *musicPlayer;
OMSongInfo *songInfo;

@implementation RootViewController 


- (void)viewDidLoad {
    [super viewDidLoad];

    // 设置导航栏title
    self.title = @"SCMusic";

    musicPlayer = MusicPlayerManager.sharedManager;
    songInfo = OMSongInfo.sharedManager;

    // 设置Subview
    [self setupSubview];

    // 锁屏播放设置
    [self createRemoteCommandCenter];

    // 设置KVO
    [songInfo addObserver:self forKeyPath:@"playSongIndex" options:NSKeyValueObservingOptionOld
     |NSKeyValueObservingOptionNew context:nil];
    [songInfo addObserver:self forKeyPath:@"isDataRequestFinish" options:NSKeyValueObservingOptionOld
     |NSKeyValueObservingOptionNew context:nil];

    [musicPlayer addObserver:self forKeyPath:@"finishPlaySongIndex" options:NSKeyValueObservingOptionOld
     |NSKeyValueObservingOptionNew context:nil];

    // Notification
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(playSongSetting)
                                                 name: @"repeatPlay"
                                               object: nil];

    // 播放遇到中断,比如电话进来
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAudioSessionEvent:) name:AVAudioSessionInterruptionNotification object:nil];

}

-(void)viewDidAppear:(BOOL)animated {
    [self playStateRecover];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - setupSubview
-(void) setupSubview {

    // 初始化detailController
    _detailController = [[DetailControlViewController alloc] init];

    // 主页控制View
    _playControllerView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.view.frame) * 0.92 - CGRectGetHeight(self.navigationController.navigationBar.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) * 0.08)];
    _playControllerView.backgroundColor = UIColorFromRGB(0xff0000);
    _playControllerView.userInteractionEnabled = YES;
    [self.view bringSubviewToFront:_playControllerView];
    [self.view addSubview:_playControllerView];

    [_playControllerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom).with.offset(0);
        make.left.equalTo(self.view.mas_left).with.offset(0);
        make.right.equalTo(self.view.mas_right).with.offset(0);
        make.width.mas_equalTo(CGRectGetWidth(self.view.frame));
        make.height.mas_equalTo(CGRectGetHeight(self.view.frame) * 0.08);
    }];

    // 专辑图片
    _currentPlaySongImage = [[SCImageView alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.height * 0.1, -_playControllerView.frame.size.height * 0.2 , _playControllerView.frame.size.height * 1.1 , _playControllerView.frame.size.height * 1.1)];
    _currentPlaySongImage.image = [UIImage imageNamed:@"cm2_simple_defaut_album_image"];
    _currentPlaySongImage.clipsToBounds = true;
    _currentPlaySongImage.layer.cornerRadius = _playControllerView.frame.size.height * 0.55;
    [_playControllerView addSubview:_currentPlaySongImage];
    _currentPlaySongImage.userInteractionEnabled = YES;
    UITapGestureRecognizer *tag = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jumpToDeitalController)];
    [_currentPlaySongImage addGestureRecognizer:tag];

    //播放控制
    _playAndPauseButton = [[UIButton alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.width * 0.75 , _playControllerView.frame.size.height * 0.25 , _playControllerView.frame.size.height * 0.65 , _playControllerView.frame.size.height* 0.65)];
    [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
    [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
    [_playAndPauseButton addTarget:self action:@selector(playAndPauseButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [_playControllerView addSubview:_playAndPauseButton];


    _nextSongButton = [[UIButton alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.width * 0.88 , _playControllerView.frame.size.height * 0.25 , _playControllerView.frame.size.height * 0.65 , _playControllerView.frame.size.height* 0.65)];
    [_nextSongButton setImage:[UIImage imageNamed:@"cm2_fm_btn_next"] forState:UIControlStateNormal];
    [_nextSongButton setImage:[UIImage imageNamed:@"cm2_fm_btn_next_prs"] forState:UIControlStateHighlighted];
    [_nextSongButton addTarget:self action:@selector(nextButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    [_playControllerView addSubview:_nextSongButton];

    // 歌曲进度条
    _songSlider = [[UISlider alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.height * 1.3 , 0 , _playControllerView.frame.size.width - _playControllerView.frame.size.height * 1.3 , _playControllerView.frame.size.height* 0.3)];
    [_songSlider setThumbImage:[UIImage imageNamed:@"cm2_simple_knob_nomal"] forState:UIControlStateNormal];
    [_songSlider setThumbImage:[UIImage imageNamed:@"cm2_simple_knob_prs"] forState:UIControlStateHighlighted];
    _songSlider.tintColor = UIColorFromRGB(0xffffff);

    //设置slider响应事件
    [_songSlider addTarget:self //事件委托对象
                    action:@selector(playbackSliderValueChanged) //处理事件的方法
          forControlEvents:UIControlEventValueChanged//具体事件
     ];
    [_songSlider addTarget:self //事件委托对象
                    action:@selector(playbackSliderValueChangedFinish) //处理事件的方法
          forControlEvents:UIControlEventTouchUpInside//具体事件
     ];
    [_playControllerView addSubview:_songSlider];

    // 歌名和歌手名
    _songName = [[UILabel alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.height * 1.3,  _playControllerView.frame.size.height* 0.3 , _playControllerView.frame.size.width * 0.5 , _playControllerView.frame.size.height* 0.3)];
    //    songName.backgroundColor = [UIColor blackColor];
    _songName.text = @"Unkown";
    _songName.textColor = [UIColor whiteColor];
    _songName.font = [UIFont systemFontOfSize:16.0];
    [_playControllerView addSubview:_songName];

    _singerName = [[UILabel alloc] initWithFrame:CGRectMake(_playControllerView.frame.size.height * 1.3,  _playControllerView.frame.size.height* 0.7 , _playControllerView.frame.size.width * 0.5 , _playControllerView.frame.size.height* 0.2)];
    //    singerName.backgroundColor = [UIColor blackColor];
    _singerName.text = @"Unkown";
    _singerName.textColor = [UIColorFromRGB(0xfafafa) colorWithAlphaComponent:0.95];
    _singerName.font = [UIFont systemFontOfSize:13.0];
    [_playControllerView addSubview:_singerName];
    [self.view addSubview:_playControllerView];

    self.automaticallyAdjustsScrollViewInsets = NO;

    [self setupTopContianerView];
    [self setupChildController];
    [self setupContentScrollView];
}

#pragma mark - 初始化子控制器
-(void)setupChildController {
    for (NSInteger i = 0; i<self.currentChannelsArray.count; i++) {

        ContentTableViewController *viewController = [[ContentTableViewController alloc] init];

        viewController.channelTitle = self.currentChannelsArray[i];
        [self addChildViewController:viewController];
    }
}

#pragma mark - 初始化顶部标题scrollView
- (void)setupTopContianerView{
    CGFloat top = CGRectGetMaxY(self.navigationController.navigationBar.frame);
    TTTopChannelContianerView *topContianerView = [[TTTopChannelContianerView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 30)];
    topContianerView.channelNameArray = self.currentChannelsArray;
    self.topContianerView  = topContianerView;
    //self.topContianerView.backgroundColor = [UIColor redColor];
    topContianerView.delegate = self;
    [self.view addSubview:topContianerView];
}

#pragma mark - 初始化ContentScrollView
- (void)setupContentScrollView {
    UIScrollView *contentScrollView = [[UIScrollView alloc] init];
    self.contentScrollView = contentScrollView;
    contentScrollView.frame = self.view.bounds;
    contentScrollView.contentSize = CGSizeMake(contentScrollView.frame.size.width* self.currentChannelsArray.count, 0);
    contentScrollView.pagingEnabled = YES;
    contentScrollView.delegate = self;
    [self.view insertSubview:contentScrollView atIndex:0];
    [self scrollViewDidEndScrollingAnimation:contentScrollView];
}

#pragma mark - scrollView滑动停止调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (scrollView == self.contentScrollView) {
        NSInteger index = scrollView.contentOffset.x/self.contentScrollView.frame.size.width;
        ContentTableViewController *vc = self.childViewControllers[index];
        vc.view.frame = CGRectMake(scrollView.contentOffset.x, 0, self.contentScrollView.frame.size.width, self.contentScrollView.frame.size.height);
        vc.tableView.contentInset = UIEdgeInsetsMake(self.topContianerView.scrollView.frame.size.height, 0, self.tabBarController.tabBar.frame.size.height, 0);
        [scrollView addSubview:vc.view];
        for (int i = 0; i<self.contentScrollView.subviews.count; i++) {
            NSInteger currentIndex = vc.tableView.frame.origin.x/self.contentScrollView.frame.size.width;
            if ([self.contentScrollView.subviews[i] isKindOfClass:[UITableView class]]) {
                UITableView *theTableView = self.contentScrollView.subviews[i];
                NSInteger theIndex = theTableView.frame.origin.x/self.contentScrollView.frame.size.width;
                NSInteger gap = theIndex - currentIndex;
                if (gap<=2&&gap>=-2) {
                    continue;
                } else {
                    [theTableView removeFromSuperview];
                }
            }

        }

    }
}


#pragma mark --UIScrollViewDelegate-- 滑动的减速动画结束后会调用这个方法
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    if (scrollView == self.contentScrollView) {
        [self scrollViewDidEndScrollingAnimation:scrollView];
        NSInteger index = scrollView.contentOffset.x/self.contentScrollView.frame.size.width;
        [self.topContianerView selectChannelButtonWithIndex:index];
    }
}

#pragma mark - UICollectionViewDataSource-- 返回每个UICollectionViewCell发Size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat kDeviceWidth = [UIScreen mainScreen].bounds.size.width;
    CGFloat kMargin = 10;
    return CGSizeMake((kDeviceWidth - 5*kMargin)/4, 40);
}

#pragma mark - TTTopChannelContianerViewDelegate
- (void)chooseChannelWithIndex:(NSInteger)index {
    [self.contentScrollView setContentOffset:CGPointMake(self.contentScrollView.frame.size.width * index, 0) animated:YES];
}

#pragma mark - 顶部标题数组设置
-(NSMutableArray *)currentChannelsArray {
    if (!_currentChannelsArray) {
        if (!_currentChannelsArray) {
            _currentChannelsArray = [NSMutableArray arrayWithObjects:@"新歌", @"热歌", @"经典", @"情歌", @"网络", @"影视", @"欧美",@"Bill", @"摇滚", @"爵士", @"流行", nil];
        }
    }
    return _currentChannelsArray;
}



#pragma mark - 锁屏界面开启和监控远程控制事件
//锁屏界面开启和监控远程控制事件
- (void)createRemoteCommandCenter{

    // 远程控制命令中心 iOS 7.1 之后  详情看官方文档:https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter

    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

    // MPFeedbackCommand对象反映了当前App所播放的反馈状态. MPRemoteCommandCenter对象提供feedback对象用于对媒体文件进行喜欢, 不喜欢, 标记的操作. 效果类似于网易云音乐锁屏时的效果

    //添加喜欢按钮
    MPFeedbackCommand *likeCommand = commandCenter.likeCommand;
    likeCommand.enabled = YES;
    likeCommand.localizedTitle = @"喜欢";
    [likeCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"喜欢");
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    //添加不喜欢按钮,这里用作“下一首”
    MPFeedbackCommand *dislikeCommand = commandCenter.dislikeCommand;
    dislikeCommand.enabled = YES;
    dislikeCommand.localizedTitle = @"下一首";
    [dislikeCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"下一首");
        [self nextButtonAction:nil];
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    //标记
    MPFeedbackCommand *bookmarkCommand = commandCenter.bookmarkCommand;
    bookmarkCommand.enabled = YES;
    bookmarkCommand.localizedTitle = @"标记";
    [bookmarkCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"标记");

        return MPRemoteCommandHandlerStatusSuccess;
    }];

    // 远程控制播放
    [commandCenter.pauseCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        [musicPlayer.play pause];
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    // 远程控制暂停
    [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        [musicPlayer.play play];
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    // 远程控制上一曲
    [commandCenter.previousTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"上一曲");
        return MPRemoteCommandHandlerStatusSuccess;
    }];

    // 远程控制下一曲
    [commandCenter.nextTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        NSLog(@"下一曲");
        [self nextButtonAction:nil];
        return MPRemoteCommandHandlerStatusSuccess;
    }];


    //快进
    MPSkipIntervalCommand *skipBackwardIntervalCommand = commandCenter.skipForwardCommand;
    skipBackwardIntervalCommand.preferredIntervals = @[@(54)];
    skipBackwardIntervalCommand.enabled = YES;
    [skipBackwardIntervalCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {

        NSLog(@"你按了快进按键!");

        // 歌曲总时间
        CMTime duration = musicPlayer.play.currentItem.asset.duration;
        Float64 completeTime = CMTimeGetSeconds(duration);

        // 快进10秒
        _songSlider.value = _songSlider.value + 10 / completeTime;

        // 计算快进后当前播放时间
        Float64 currentTime = (Float64)(_songSlider.value) * completeTime;

        // 播放器定位到对应的位置
        CMTime targetTime = CMTimeMake((int64_t)(currentTime), 1);
        [musicPlayer.play seekToTime:targetTime];

        return MPRemoteCommandHandlerStatusSuccess;
    }];

    //在控制台拖动进度条调节进度(仿QQ音乐的效果)
    [commandCenter.changePlaybackPositionCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent * _Nonnull event) {
        CMTime totlaTime = musicPlayer.play.currentItem.duration;
        MPChangePlaybackPositionCommandEvent * playbackPositionEvent = (MPChangePlaybackPositionCommandEvent *)event;
        [musicPlayer.play seekToTime:CMTimeMake(totlaTime.value*playbackPositionEvent.positionTime/CMTimeGetSeconds(totlaTime), totlaTime.timescale) completionHandler:^(BOOL finished) {
        }];
        return MPRemoteCommandHandlerStatusSuccess;
    }];


}

#pragma mark - removeObserver
- (void)dealloc{
    [self removeObserver];
}

- (void)removeObserver{

    [musicPlayer.play removeTimeObserver:_playerTimeObserver];
    _playerTimeObserver = nil;

    [musicPlayer.play.currentItem cancelPendingSeeks];
    [musicPlayer.play.currentItem.asset cancelLoading];

    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];
    [commandCenter.likeCommand removeTarget:self];
    [commandCenter.dislikeCommand removeTarget:self];
    [commandCenter.bookmarkCommand removeTarget:self];
    [commandCenter.nextTrackCommand removeTarget:self];
    [commandCenter.skipForwardCommand removeTarget:self];
    [commandCenter.changePlaybackPositionCommand removeTarget:self];
}


#pragma mark - KVO
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {

    if ([keyPath  isEqual: @"playSongIndex"]) {
        [self playSongSetting];
    }

    if ([keyPath isEqual:@"isDataRequestFinish"]) {
        if (songInfo.isDataRequestFinish == YES) {
            songInfo.isDataRequestFinish = NO;
            [_detailController.songListView.tableView reloadData];
        }
    }

    if ([keyPath  isEqual: @"finishPlaySongIndex"]) {
        [self playSongSetting];
    }

}


#pragma mark - 音乐被中断处理
- (void) onAudioSessionEvent: (NSNotification *) notification
{
    //Check the type of notification, especially if you are sending multiple AVAudioSession events here
    if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
        NSLog(@"Interruption notification received!");

        //Check to see if it was a Begin interruption
        if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
            NSLog(@"Interruption began!");
            [musicPlayer stopPlay];
        } else {
            NSLog(@"Interruption ended!");
            //Resume your audio
            [musicPlayer startPlay];
        }
    }
}

#pragma mark - 状态恢复
-(void) playStateRecover {

    [_currentPlaySongImage startRotating];

    if (musicPlayer.play.rate == 1) {
        NSLog(@"播放!");
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage resumeRotate];

    } else {
        NSLog(@"暂停");
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage stopRotating];
    }

}

#pragma mark - 播放音乐调用
-(void) playSongSetting {

    if (_playerTimeObserver != nil) {

        [musicPlayer.play removeTimeObserver:_playerTimeObserver];
        _playerTimeObserver = nil;

        [musicPlayer.play.currentItem cancelPendingSeeks];
        [musicPlayer.play.currentItem.asset cancelLoading];

    }


    [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
    [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];

    // 主页面控制界面信息设置
    _songName.text = songInfo.title;
    _singerName.text = songInfo.author;
    _currentPlaySongImage.image = songInfo.pic_small;
    [_currentPlaySongImage resumeRotate];

    // detail页面控制界面信息设置
    _detailController.topView.songTitleLabel.text = songInfo.title;
    _detailController.topView.singerNameLabel.text = [[@"- " stringByAppendingString:songInfo.author] stringByAppendingString:@" -"];
    [_detailController.midView.midIconView setAlbumImage:songInfo.pic_big];
    [_detailController.midView.midLrcView AnalysisLRC:songInfo.lrcString];

    // 播放设置
    [musicPlayer setPlayItem:songInfo.file_link];
    [musicPlayer setPlay];
    [musicPlayer startPlay];

    // 歌词index清零
    songInfo.lrcIndex = 0;

    // 控制界面设置
    [_detailController playStateRecover];


    // 播放结束通知
    [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(finishedPlaying) name:AVPlayerItemDidPlayToEndTimeNotification object:musicPlayer.play.currentItem];

    // 设置Observer更新播放进度
    _playerTimeObserver = [musicPlayer.play addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {

        CGFloat currentTime = CMTimeGetSeconds(time);
        NSLog(@"当前播放时间:%f", currentTime);

        CMTime total = musicPlayer.play.currentItem.duration;
        CGFloat totalTime = CMTimeGetSeconds(total);

        // 当前播放时间
        _detailController.bottomView.currentTimeLabel.text = [songInfo intToString:(int)currentTime];
        // 总时间
        _detailController.bottomView.durationTimeLabel.text =[songInfo intToString:(int)totalTime];

        _songSlider.value = (float) ( currentTime / totalTime );
        _detailController.bottomView.songSlider.value = (float) ( currentTime / totalTime );

        // 更新歌词
        if (songInfo.isLrcExistFlg == true) {

            if (!_detailController.midView.midLrcView.isDragging) {

                if (songInfo.lrcIndex <= songInfo.mLRCDictinary.count - 1) {

                    if ((int)currentTime >= [songInfo stringToInt:songInfo.mTimeArray[songInfo.lrcIndex]]) {

                        _detailController.midView.midLrcView.currentRow = songInfo.lrcIndex;

                        dispatch_async(dispatch_get_main_queue(), ^{

                            [_detailController.midView.midLrcView.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_detailController.midView.midLrcView.currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

                            [_detailController.midView.midLrcView.lockScreenTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow: _detailController.midView.midLrcView.currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

                        });

                        // 刷新歌词列表
                        [_detailController.midView.midLrcView.tableView reloadData];
                        [_detailController.midView.midLrcView.lockScreenTableView reloadData];

                        songInfo.lrcIndex = songInfo.lrcIndex + 1;

                    } else {

                        if (songInfo.lrcIndex != 0) {

                            if (((int)currentTime >= [songInfo stringToInt:songInfo.mTimeArray[songInfo.lrcIndex - 1]]) && ((int)currentTime < [songInfo stringToInt:songInfo.mTimeArray[songInfo.lrcIndex]])) {

                                _detailController.midView.midLrcView.currentRow = songInfo.lrcIndex - 1;

                                dispatch_async(dispatch_get_main_queue(), ^{
                                    [_detailController.midView.midLrcView.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_detailController.midView.midLrcView.currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
                                    [_detailController.midView.midLrcView.lockScreenTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow: _detailController.midView.midLrcView.currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
                                });

                                // 刷新歌词列表
                                [_detailController.midView.midLrcView.tableView reloadData];
                                [_detailController.midView.midLrcView.lockScreenTableView reloadData];
                            }
                        }

                    }

                }
            }
        }


        //监听锁屏状态 lock=1则为锁屏状态
        uint64_t locked;
        __block int token = 0;
    notify_register_dispatch("com.apple.springboard.lockstate",&token,dispatch_get_main_queue(),^(int t){
        });
        notify_get_state(token, &locked);

        //监听屏幕点亮状态 screenLight = 1则为变暗关闭状态
        uint64_t screenLight;
        __block int lightToken = 0;
    notify_register_dispatch("com.apple.springboard.hasBlankedScreen",&lightToken,dispatch_get_main_queue(),^(int t){
        });
        notify_get_state(lightToken, &screenLight);

        BOOL isShowLyricsPoster = NO;
        // NSLog(@"screenLight=%llu locked=%llu",screenLight,locked);
        if (screenLight == 0 && locked == 1) {
            //点亮且锁屏时
            isShowLyricsPoster = YES;
        }else if(screenLight){
            return;
        }

        //展示锁屏歌曲信息,上面监听屏幕锁屏和点亮状态的目的是为了提高效率
        [self showLockScreenTotaltime:totalTime andCurrentTime:currentTime andLyricsPoster:isShowLyricsPoster];
    }];

}

#pragma mark - 锁屏播放设置
//展示锁屏歌曲信息:图片、歌词、进度、演唱者
- (void)showLockScreenTotaltime:(float)totalTime andCurrentTime:(float)currentTime andLyricsPoster:(BOOL)isShow{

    NSMutableDictionary * songDict = [[NSMutableDictionary alloc] init];
    //设置歌曲题目
    [songDict setObject:songInfo.title forKey:MPMediaItemPropertyTitle];
    //设置歌手名
    [songDict setObject:songInfo.author forKey:MPMediaItemPropertyArtist];
    //设置专辑名
    [songDict setObject:songInfo.album_title forKey:MPMediaItemPropertyAlbumTitle];
    //设置歌曲时长
    [songDict setObject:[NSNumber numberWithDouble:totalTime]  forKey:MPMediaItemPropertyPlaybackDuration];
    //设置已经播放时长
    [songDict setObject:[NSNumber numberWithDouble:currentTime] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];

    UIImage * lrcImage = songInfo.pic_big;
    if (isShow) {

        //制作带歌词的海报
        if (!_lrcImageView) {
            _lrcImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 480,800)];
        }

        //主要为了把歌词绘制到图片上,已达到更新歌词的目的
        [_lrcImageView addSubview:_detailController.midView.midLrcView.lockScreenTableView];
        _lrcImageView.image = lrcImage;
        _lrcImageView.backgroundColor = [UIColor blackColor];

        //获取添加了歌词数据的海报图片
        UIGraphicsBeginImageContextWithOptions(_lrcImageView.frame.size, NO, 0.0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [_lrcImageView.layer renderInContext:context];
        lrcImage = UIGraphicsGetImageFromCurrentImageContext();
        _lastImage = lrcImage;
        UIGraphicsEndImageContext();

    }else{
        if (_lastImage) {
            lrcImage = _lastImage;
        }
    }
    //设置显示的海报图片
    [songDict setObject:[[MPMediaItemArtwork alloc] initWithImage:lrcImage]
                 forKey:MPMediaItemPropertyArtwork];


    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songDict];

}

#pragma mark - 播放或暂停
-(void)playAndPauseButtonAction: (UIButton *)sender {

    NSLog(@"当前播放曲目:%@", songInfo.title);

    if (musicPlayer.play.rate == 0) {

        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage resumeRotate];
        [musicPlayer startPlay];

    } else {

        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage stopRotating];
        [musicPlayer stopPlay];
    }
}

#pragma mark - 下一曲
-(void) nextButtonAction: (UIButton *)sender {

    if (songInfo.playSongIndex < songInfo.OMSongs.count - 1) {
        OMHotSongInfo *info = songInfo.OMSongs[songInfo.playSongIndex + 1];
        NSLog(@"即将播放下一首歌曲: 《%@》", info.title);
        [songInfo setSongInfo:info];
        [songInfo getSelectedSong:info.song_id index:songInfo.playSongIndex + 1];
    } else {
        OMHotSongInfo *info = songInfo.OMSongs[0];
        NSLog(@"即将播放下一首歌曲: 《%@》", info.title);
        [songInfo setSongInfo:info];
        [songInfo getSelectedSong:info.song_id index:0];
    }

}

#pragma mark - 歌曲播放结束操作
-(void) finishedPlaying {

    NSLog(@"本歌曲播放结束,准备播放下一首歌曲!");
    //    songInfo.playSongIndex = songInfo.playSongIndex + 1;
    [self nextButtonAction:nil];
}

#pragma mark - 点击专辑图片
-(void) jumpToDeitalController {
    [self presentViewController:_detailController animated:YES completion:nil];
}


#pragma mark - 进度条改变值时触发
//拖动进度条改变值时触发
-(void) playbackSliderValueChanged {

    // 更新播放时间
    [self updateTime];

    //如果当前时暂停状态,则自动播放
    if (musicPlayer.play.rate == 0) {

        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage resumeRotate];
        [musicPlayer startPlay];

    }
}

#pragma mark - 进度条改变值结束时触发
-(void) playbackSliderValueChangedFinish {
    // 更新播放时间
    [self updateTime];

    //如果当前时暂停状态,则自动播放
    if (musicPlayer.play.rate == 0) {

        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_playAndPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_currentPlaySongImage resumeRotate];
        [musicPlayer startPlay];

    }
}

#pragma mark - 更新播放时间
-(void) updateTime {

    CMTime duration = musicPlayer.play.currentItem.asset.duration;

    // 歌曲总时间和当前时间
    Float64 completeTime = CMTimeGetSeconds(duration);
    Float64 currentTime = (Float64)(_songSlider.value) * completeTime;

    //播放器定位到对应的位置
    CMTime targetTime = CMTimeMake((int64_t)(currentTime), 1);
    [musicPlayer.play seekToTime:targetTime];

    int index = 0;
    for (NSString *indexStr in songInfo.mTimeArray) {
        if ((int)currentTime < [songInfo stringToInt:indexStr]) {
            songInfo.lrcIndex = index;
        } else {
            index = index + 1;
        }
    }

}


@end

ContentTableViewController.h

#import <UIKit/UIKit.h>
#import "AFNetworking.h"
#import "OMHotSongInfo.h"
#import "OMSongInfo.h"
#import "OMAlbumInfo.h"
#import "OMArtistInfo.h"
#import "MJRefresh.h"
#import "Const.h"
#import "MusicDownloader.h"
#import "DetailControlViewController.h"

@interface ContentTableViewController : UITableViewController <UIScrollViewDelegate>

@property (nonatomic, strong) NSString *channelTitle;
@property (nonatomic, strong) DetailControlViewController *detailController;

-(void)reloadData;
-(void)getSelectedSong: (NSString *)songID index: (long)index;


@end

ContentTableViewController.m

#import "ContentTableViewController.h"

#define kCustomRowCount 7

static NSString *CellIdentifier = @"LazyTableCell";
static NSString *PlaceholderCellIdentifier = @"PlaceholderCell";

@interface ContentTableViewController ()
{
    NSArray *hotArtistsArray;
    NSArray *newAlbumsArray;
    NSArray *onlineMusicArray;
    NSString *choosedAlbumID;
    NSString *choosedArtistUID;
    OMSongInfo *songInfo;
}

@property (nonatomic, strong) NSMutableArray *arrayList;

// the set of IconDownloader objects for each app
@property (nonatomic, strong) NSMutableDictionary *imageDownloadInProgress;

@property (nonatomic, strong) UIActivityIndicatorView *indicator;

@property (nonatomic, strong) MusicDownloader *downloader;

@end

@implementation ContentTableViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    _downloader = [[MusicDownloader alloc] init];
    _downloader.isDataRequestFinish = false;
    _imageDownloadInProgress = [NSMutableDictionary dictionary];
    songInfo = OMSongInfo.sharedManager;

    [self setupBasic];
    [self setupRefresh];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark --private Method--设置tableView
-(void)setupBasic {
    self.automaticallyAdjustsScrollViewInsets = NO;
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(104, 0, 0, 0);
}


#pragma mark --private Method--初始化刷新控件
-(void)setupRefresh {
    self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadData)];
    self.tableView.mj_header.automaticallyChangeAlpha = YES;
    [self.tableView.mj_header beginRefreshing];
    self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
}


#pragma mark - /************************* 刷新数据 ***************************/
// ----------------------------------------------------------------------------
//    loadMoreData
//  Pull-Up(上拉)
// ----------------------------------------------------------------------------
- (void)loadData
{
    uint8_t type;
    if ([self.channelTitle  isEqual: @"新歌"]) {
        type = NEW_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"热歌"]) {
        type = HOT_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"经典"]) {
        type = OLD_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"情歌"]) {
        type = LOVE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"网络"]) {
        type = INTERNET_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"影视"]) {
        type = MOVIE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"欧美"]) {
        type = EUROPE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"Bill"]) {
        type = BILLBOARD_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"摇滚"]) {
        type = ROCK_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"爵士"]) {
        type = JAZZ_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"流行"]) {
        type = POP_MUSIC_LIST;
    }else {
        return;
    }

    NSString *partOne = @"http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&";
    NSString *partTwo = [NSString stringWithFormat:@"type=%d&offset=0&size=%d",type, 20];
    NSString *urlString = [partOne stringByAppendingString:partTwo];
    [self loadDataForType:1 withURL:urlString];
}

// ----------------------------------------------------------------------------
//    loadMoreData
//  Pull-Down(下拉)
// ----------------------------------------------------------------------------
- (void)loadMoreData
{
    uint8_t type;
    if ([self.channelTitle  isEqual: @"新歌"]) {
        type = NEW_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"热歌"]) {
        type = HOT_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"经典"]) {
        type = OLD_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"情歌"]) {
        type = LOVE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"网络"]) {
        type = INTERNET_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"影视"]) {
        type = MOVIE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"欧美"]) {
        type = EUROPE_SONG_LIST;
    }else if ([self.channelTitle  isEqual: @"Bill"]) {
        type = BILLBOARD_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"摇滚"]) {
        type = ROCK_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"爵士"]) {
        type = JAZZ_MUSIC_LIST;
    }else if ([self.channelTitle  isEqual: @"流行"]) {
        type = POP_MUSIC_LIST;
    }else {
        return;
    }

    NSString *partOne = @"http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.billboard.billList&format=json&";
    NSString *partTwo = [NSString stringWithFormat:@"type=%d&offset=%lu&size=%d",type,(unsigned long)self.arrayList.count, 20];
    NSString *urlString = [partOne stringByAppendingString:partTwo];
    [self loadDataForType:2 withURL:urlString];
}

// ----------------------------------------------------------------------------
//    loadDataForType:(int)loadingType withURL:(NSString *)urlString
//  Loading data through Pull-Up and Pull-Down
// ----------------------------------------------------------------------------
- (void)loadDataForType:(int)loadingType withURL:(NSString *)urlString
{

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

   NSString *path = urlString;

    [manager GET:path parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if ([responseObject isKindOfClass:[NSDictionary class]])
        {
            NSArray *array = [responseObject objectForKey:@"song_list"];
            NSArray *loadSongArray = [OMHotSongInfo mj_objectArrayWithKeyValuesArray:array];

            if (loadingType == 1) {
                self.arrayList = [loadSongArray mutableCopy];
                [self.tableView.mj_header endRefreshing];
            }else if(loadingType == 2){

                if (self.arrayList.count >= 100) {
                    [self.tableView.mj_footer endRefreshing];
                    return;
                }

                [self.arrayList addObjectsFromArray:loadSongArray];
                [self.tableView.mj_footer endRefreshing];
            }
            songInfo.isDataRequestFinish = YES;
            songInfo.OMSongs = self.arrayList;
            [self.tableView reloadData];
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
         NSLog(@"error--%@",error);
    }];

}





// ----------------------------------------------------------------------------
//    startIconDownload:forIndexPath:
// ----------------------------------------------------------------------------
- (void)startIconDownload:(OMHotSongInfo *)info forIndexPath:(NSIndexPath *)indexPath
{
    MusicDownloader *downloader = (self.imageDownloadInProgress)[indexPath];
    if (downloader == nil)
    {
        downloader = [[MusicDownloader alloc] init];
        downloader.hotSonginfo = info;
        [downloader setCompletionHandler:^{

            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

            // Display the newly loaded image
            cell.imageView.image = info.albumImage_small;

            // Remove the IconDownloader from the in progress list.
            // This will result in it being deallocated.
            [self.imageDownloadInProgress removeObjectForKey:indexPath];

        }];
        (self.imageDownloadInProgress)[indexPath] = downloader;
        [downloader startDownload];
    }
}

// -----------------------------------------------------------------------------
//    loadImagesForOnscreenRows
//  This method is used in case the user scrolled into a set of cells that don't
//  have their app icons yet.
// ------------------------------------------------------------------------------
-(void) loadImagesForOnScreenRows {

    if (self.arrayList.count > 0) {
        NSArray *visiblePaths= [self.tableView indexPathsForVisibleRows];

        for (NSIndexPath *indexPath in visiblePaths) {
            OMHotSongInfo *info = (self.arrayList)[indexPath.row];

            if (!info.albumImage_small) {
                [self startIconDownload:info forIndexPath:indexPath];
            }
        }
    }
}


#pragma - mark TableView代理
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 70;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if ([self.channelTitle isEqualToString:@"新歌"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"热歌"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"经典"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"情歌"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"网络"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"影视"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"欧美"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"Bill"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"摇滚"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"爵士"]) {
        return self.arrayList.count;
    }else if ([self.channelTitle  isEqual: @"流行"]) {
        return self.arrayList.count;
    }

    return 0;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = nil;

    NSUInteger nodeCount = self.arrayList.count;

    if (nodeCount == 0 && indexPath.row == 0)
    {
        // add a placeholder cell while waiting on table data
        cell = [self.tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:PlaceholderCellIdentifier];
        }
    }
    else
    {
        // add a placeholder cell while waiting on table data
        cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:CellIdentifier];
        }

        // Leave cells empty if there's no data yet
        if (nodeCount > 0)
        {
            // Set up the cell representing the app
            OMHotSongInfo *info = (self.arrayList)[indexPath.row];

            cell.textLabel.text = info.title;
            cell.detailTextLabel.text = info.author;

            // Only load cached images; defer new downloads until scrolling ends
            if (!info.albumImage_small)
            {
                if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
                {
                    [self startIconDownload:info forIndexPath:indexPath];
                }
                // if a download is deferred or in progress, return a placeholder image
                cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];
            }
            else
            {
                cell.imageView.image = info.albumImage_small;
            }
        }
    }

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    OMHotSongInfo *info = (self.arrayList)[indexPath.row];
    NSLog(@"你选择了《%@》这首歌", info.title);
    [songInfo setSongInfo:info];
    [songInfo getSelectedSong:info.song_id index:indexPath.row];
}

#pragma mark - UIScrollViewDelegate
// -------------------------------------------------------------------------------
//    scrollViewDidEndDragging:willDecelerate:
//  Load images for all onscreen rows when scrolling is finished.
// -------------------------------------------------------------------------------
-(void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        [self loadImagesForOnScreenRows];
    }
}

// -------------------------------------------------------------------------------
//    scrollViewDidEndDecelerating:scrollView
//   When scrolling stops, proceed to load the app icons that are on screen.
// -------------------------------------------------------------------------------
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self loadImagesForOnScreenRows];
}


@end

DetailControlViewController.h

#import <UIKit/UIKit.h>
#import "TopView.h"
#import "MidView.h"
#import "BottomView.h"
#import "OMSongInfo.h"
#import "MusicPlayerManager.h"
#import "OMHotSongInfo.h"
#import "SongListView.h"
#import "Const.h"


@interface DetailControlViewController : UIViewController

// 底部弹出View
@property (nonatomic ,strong) SongListView *songListView;   // 底部View
@property (nonatomic ,strong) UIView *shadowView;           // 阴影部分
@property(nonatomic, strong) TopView *topView;              // SongListView的topView
@property(nonatomic, strong) MidView *midView;
@property(nonatomic, strong) BottomView *bottomView;
@property(nonatomic, strong) UIImageView *backgroundImageView;

-(void) setBackgroundImage: (UIImage *)image;
-(void) playStateRecover;

@end

DetailControlViewController.m

#import "DetailControlViewController.h"


extern MusicPlayerManager *musicPlayer;
extern OMSongInfo *songInfo;

@implementation DetailControlViewController

int lrcIndex = 0;

-(instancetype) init {
    self = [super init];
    if (self) {
        // 初始化SubView
        [self configSubView];
    }

    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self getShuffleAndRepeatState];
}

-(void) viewWillAppear:(BOOL)animated {
    [self playStateRecover];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - configSubView
-(void) configSubView {
    // 初始化musicPlayer和songInfo
    musicPlayer = MusicPlayerManager.sharedManager;
    songInfo = OMSongInfo.sharedManager;

    // top view初始化
    _topView = [[TopView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height / 5)];
    [_topView.backBtn addTarget:self action:@selector(backAction) forControlEvents: UIControlEventTouchUpInside];
    [self.view addSubview:_topView];

    // mid view 初始化
    _midView = [[MidView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height / 5, self.view.frame.size.width, self.view.frame.size.height / 5 * 3)];
    [self.view addSubview:_midView];

    // bottom view 初始化
    _bottomView = [[BottomView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height / 5 * 4, self.view.frame.size.width, self.view.frame.size.height / 5)];
    [self.view addSubview:_bottomView];

    // SongListView初始化
    _songListView                 = [[SongListView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, ScreenHeight * 0.618)];
    _songListView.backgroundColor = [UIColor whiteColor];

    // 添加playOrPauseButton响应事件
    [_bottomView.playOrPauseButton addTarget:self action:@selector(playOrPauseButtonAction) forControlEvents:UIControlEventTouchUpInside];

    // 添加nextSongButton响应事件
    [_bottomView.nextSongButton addTarget:self action:@selector(nextButtonAction) forControlEvents:UIControlEventTouchUpInside];

    // 添加preButton响应事件
    [_bottomView.preSongButtton addTarget:self action:@selector(preButtonAction) forControlEvents:UIControlEventTouchUpInside];

    // 添加shuffleAndRepeat响应事件
    [_bottomView.playModeButton addTarget:self action:@selector(shuffleAndRepeat) forControlEvents:UIControlEventTouchUpInside];

    // 添加songListButton响应事件
    [_bottomView.songListButton addTarget:self action:@selector(songListButtonAction) forControlEvents:UIControlEventTouchUpInside];

    // 播放进度条添加响应事件
    [_bottomView.songSlider addTarget:self //事件委托对象
                               action:@selector(playbackSliderValueChanged) //处理事件的方法
                     forControlEvents:UIControlEventValueChanged//具体事件
     ];
    [_bottomView.songSlider addTarget:self //事件委托对象
                               action:@selector(playbackSliderValueChangedFinish) //处理事件的方法
                     forControlEvents:UIControlEventTouchUpInside//具体事件
     ];

    // 设置背景图片
    [self setBackgroundImage:[UIImage imageNamed:@"backgroundImage3"]];
}

#pragma mark - 状态恢复
-(void) playStateRecover {

    [_midView.midIconView.imageView startRotating];

    if (musicPlayer.play.rate == 1) {
        NSLog(@"播放!");
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView resumeRotate];

    } else {
        NSLog(@"暂停");
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView stopRotating];
    }

}

#pragma - mark 设置detail控制界面背景图片
-(void) setBackgroundImage: (UIImage *)image {

    _backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(-UIScreen.mainScreen.bounds.size.width / 2, -UIScreen.mainScreen.bounds.size.height / 2, UIScreen.mainScreen.bounds.size.width * 2, UIScreen.mainScreen.bounds.size.height * 2)];
    _backgroundImageView.image = image;
    _backgroundImageView.clipsToBounds = true;
    [self.view addSubview:_backgroundImageView];
    [self.view sendSubviewToBack:_backgroundImageView];

    // 毛玻璃效果
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    UIVisualEffectView *visualView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    visualView.alpha = 1.0;
    visualView.frame = CGRectMake(-UIScreen.mainScreen.bounds.size.width / 2, -UIScreen.mainScreen.bounds.size.height / 2, UIScreen.mainScreen.bounds.size.width * 2, UIScreen.mainScreen.bounds.size.height * 2);
    visualView.clipsToBounds = true;
    [_backgroundImageView addSubview:visualView];
}

#pragma - mark 播放或暂停
-(void) playOrPauseButtonAction {

    if (musicPlayer.play.rate == 0) {
        NSLog(@"播放!");
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView resumeRotate];
        [musicPlayer startPlay];

    } else {
        NSLog(@"暂停");
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView stopRotating];
        [musicPlayer stopPlay];
    }

}

#pragma - mark 下一曲
-(void) nextButtonAction {

    musicPlayer.playingIndex = songInfo.playSongIndex;

    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode:
        {
            musicPlayer.playingIndex++;
            if (musicPlayer.playingIndex >= songInfo.OMSongs.count)//最后一首了
            {
                musicPlayer.playingIndex = 0;              //跳到第一首
            }
        }
            break;
        case RepeatOnlyOnePlayMode:
        {

        }
            break;
        case ShufflePlayMode:
        {
            if (musicPlayer.playingIndex == songInfo.OMSongs.count - 1)//最后一首了
            {
                musicPlayer.playingIndex = [self getRandomNumber:0 with:(songInfo.OMSongs.count - 2)];//重头开始不包括本首歌
            }
            else
            {
                musicPlayer.playingIndex = [self getRandomNumber:(musicPlayer.playingIndex + 1) with:(songInfo.OMSongs.count - 1)];//不包括本首歌
            }
        }
            break;
        default:
            break;
    }

    if ( musicPlayer.playingIndex != songInfo.playSongIndex ) {
        if (songInfo.playSongIndex < songInfo.OMSongs.count) {
            OMHotSongInfo *info = songInfo.OMSongs[ musicPlayer.playingIndex];
            NSLog(@"即将播放下一首歌曲: 《%@》", info.title);
            [songInfo setSongInfo:info];
            [songInfo getSelectedSong:info.song_id index:songInfo.playSongIndex + 1];

        }
    } else {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"repeatPlay" object:self];
    }

}

#pragma - mark 上一曲
-(void) preButtonAction {

    musicPlayer.playingIndex = songInfo.playSongIndex;

    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode:
        {
            if ( musicPlayer.playingIndex == 0)//第一首
            {
                musicPlayer.playingIndex = songInfo.OMSongs.count - 1;  //跳到最后一首
            }
            else
            {
                musicPlayer.playingIndex--;    //索引为上一首
            }
        }
            break;
        case RepeatOnlyOnePlayMode:
        {

        }
            break;
        case ShufflePlayMode:
        {
            if ( musicPlayer.playingIndex == 0)//是第一首歌
            {
                musicPlayer.playingIndex = [self getRandomNumber:1 with:(songInfo.OMSongs.count - 1)];//播放除第一首歌之外的所有歌曲
            }

            else
            {
                musicPlayer.playingIndex = [self getRandomNumber:0 with:( musicPlayer.playingIndex - 1)];
            }
        }
            break;
        default:
            break;
    }

    if ( musicPlayer.playingIndex != songInfo.playSongIndex ) {
        if (songInfo.playSongIndex > 0) {
            OMHotSongInfo *info = songInfo.OMSongs[songInfo.playSongIndex - 1];
            NSLog(@"即将播放上一首歌曲: 《%@》", info.title);
            [songInfo setSongInfo:info];
            [songInfo getSelectedSong:info.song_id index:songInfo.playSongIndex - 1];
        }
    } else {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"repeatPlay" object:self];
    }

}


#pragma - mark 歌曲列表
-(void) songListButtonAction {
    NSLog(@"你按下了songList按键!");

    // 设置播放模式
    [_songListView setPlayModeButtonState];

    // 剩下阴影部分
    _shadowView                 = [[UIView alloc] init];
    _shadowView.frame           = CGRectMake(0, 0, ScreenWidth, ScreenHeight * (1.0 - 0.618));
    _shadowView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];


    // UIWindow的优先级最高,Window包含了所有视图,在这之上添加视图,可以保证添加在最上面
    UIWindow *appWindow = [[UIApplication sharedApplication] keyWindow];
    // 阴影部分view
    [appWindow addSubview:_shadowView];
    // 底部弹出的SongListView
    [appWindow addSubview:_songListView];

    // 给阴影部分添加的点击事件,单击隐藏SongListView
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(responseGlide)];
    gesture.numberOfTapsRequired = 1;
    gesture.cancelsTouchesInView = NO;
    [_shadowView addGestureRecognizer:gesture];

    // 向下滑动退出
    //UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(responseGlide)];
    //[recognizer setDirection:(UISwipeGestureRecognizerDirectionDown)];
    //[_songListView  addGestureRecognizer:recognizer];


    // SongListView弹出动画
    _songListView.transform = CGAffineTransformMakeTranslation(0.0, ScreenHeight);
    _shadowView.transform = CGAffineTransformMakeTranslation(0.0, ScreenHeight);
    [UIView animateWithDuration:0.3 animations:^{

        _shadowView.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
        _songListView.transform = CGAffineTransformMakeTranslation(0.0, ScreenHeight * (1.0 - 0.618));

    } completion:^(BOOL finished){

        _shadowView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];

    }];
}

#pragma mark - 下滑退出detail控制界面
- (void)responseGlide {

    // 设置播放模式
    [self setShuffleAndRepeatState];

    // SongListView隐藏动画
    [UIView animateWithDuration:0.3 animations:^{

        _songListView.transform = CGAffineTransformMakeTranslation(0.0, ScreenHeight);
        _shadowView.alpha = 0;

    } completion:^(BOOL finished) {

        [_shadowView removeFromSuperview];
        [_songListView removeFromSuperview];
    }];

}

#pragma - mark 进度条改变值时触发
//拖动进度条改变值时触发
-(void) playbackSliderValueChanged {

    // 更新播放时间
    [self updateTime];

    //如果当前时暂停状态,则自动播放
    if (musicPlayer.play.rate == 0) {

        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView resumeRotate];
        [musicPlayer startPlay];
    }
}

#pragma - mark 进度条改变值结束时触发
-(void) playbackSliderValueChangedFinish {
    // 更新播放时间
    [self updateTime];

    //如果当前时暂停状态,则自动播放
    if (musicPlayer.play.rate == 0) {

        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play"] forState:UIControlStateNormal];
        [_bottomView.playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_play_prs"] forState:UIControlStateHighlighted];
        [_midView.midIconView.imageView resumeRotate];
        [musicPlayer startPlay];

    }
}

#pragma - mark 更新播放时间
-(void) updateTime {

    CMTime duration = musicPlayer.play.currentItem.asset.duration;

    // 歌曲总时间和当前时间
    Float64 completeTime = CMTimeGetSeconds(duration);
    Float64 currentTime = (Float64)(_bottomView.songSlider.value) * completeTime;

    //播放器定位到对应的位置
    CMTime targetTime = CMTimeMake((int64_t)(currentTime), 1);
    [musicPlayer.play seekToTime:targetTime];

    int index = 0;
    for (NSString *indexStr in songInfo.mTimeArray) {
        if ((int)currentTime < [songInfo stringToInt:indexStr]) {
            songInfo.lrcIndex = index;
        } else {
            index = index + 1;
        }
    }
}


#pragma - mark 播放模式按键action
-(void) shuffleAndRepeat {

    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode:
        {

            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = RepeatOnlyOnePlayMode;  //单曲循环
            [self showMiddleHint:@"单曲循环"];
        }
            break;
        case RepeatOnlyOnePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = ShufflePlayMode;
            [self showMiddleHint:@"列表播放"];
        }
            break;
        case ShufflePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = RepeatPlayMode;
            [self showMiddleHint:@"随机播放"];
        }
            break;
        default:
            break;
    }

    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:musicPlayer.shuffleAndRepeatState] forKey:@"SHFFLEANDREPEATSTATE"];//存储路径
}


#pragma - mark 获取保存的播放模式
- (void)getShuffleAndRepeatState
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSNumber *repeatAndShuffleNumber = [defaults objectForKey:@"SHFFLEANDREPEATSTATE"];
    if (repeatAndShuffleNumber == nil)
    {
        musicPlayer.shuffleAndRepeatState = RepeatPlayMode;
    }
    else
    {
        musicPlayer.shuffleAndRepeatState = (ShuffleAndRepeatState)[repeatAndShuffleNumber integerValue];
    }

    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
        }
            break;
        case RepeatOnlyOnePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one_prs"] forState:UIControlStateHighlighted];
        }
            break;
        case ShufflePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle_prs"] forState:UIControlStateHighlighted];
            break;
        default:
            break;
        }
    }
}

#pragma - mark 设置播放模式
-(void) setShuffleAndRepeatState {

    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
        }
            break;
        case RepeatOnlyOnePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_one_prs"] forState:UIControlStateHighlighted];
        }
            break;
        case ShufflePlayMode:
        {
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle"] forState:UIControlStateNormal];
            [_bottomView.playModeButton setImage:[UIImage imageNamed:@"cm2_icn_shuffle_prs"] forState:UIControlStateHighlighted];
            break;
        default:
            break;
        }
    }

    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:musicPlayer.shuffleAndRepeatState] forKey:@"SHFFLEANDREPEATSTATE"];//存储路径
}


#pragma mark - 播放模式提示框
- (void)showMiddleHint:(NSString *)hint {

    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];

    hud.userInteractionEnabled = NO;
    hud.mode = MBProgressHUDModeText;
    hud.label.font = [UIFont systemFontOfSize:15];
    hud.label.text = hint;
    hud.margin = 10.f;
    hud.offset = CGPointMake(0.f, 0.f);
    hud.removeFromSuperViewOnHide = YES;
    [hud hideAnimated:YES afterDelay:2.f];
}

-(void) backAction {
    [self dismissViewControllerAnimated:YES completion:nil];
}


#pragma - mark 获取随机数,用于随机播放
-(NSUInteger) getRandomNumber:(NSUInteger)from with:(NSUInteger)to//包括两边边界
{
    NSUInteger res =  from + (arc4random() % (to - from + 1));
    return res;
}

@end

OMAlbumInfo.h

#import <Foundation/Foundation.h>

@interface OMAlbumInfo : NSObject
@property (nonatomic, strong) NSString *album_id;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *pic_small;
@property (nonatomic, strong) NSString *pic_big;
@end

OMAlbumInfo.m

#import "OMAlbumInfo.h"

@implementation OMAlbumInfo

@end

OMHotSongInfo.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface OMHotSongInfo : NSObject
@property (nonatomic,strong) UIImage *albumImage_big;
@property (nonatomic,strong) UIImage *albumImage_small;
@property (nonatomic,strong) NSString *pic_big;
@property (nonatomic,strong) NSString *lrclink;
@property (nonatomic,strong) NSString *pic_small;
@property (nonatomic,strong) NSString *song_id;
@property (nonatomic,strong) NSString *title;
@property (nonatomic,strong) NSString *author;
@property (nonatomic,strong) NSString *album_title;
@property (nonatomic,strong) NSString *file_duration;


@end

OMHotSongInfo.m

#import "OMHotSongInfo.h"

@implementation OMHotSongInfo

@end

OMArtistInfo.h

#import <Foundation/Foundation.h>

@interface OMArtistInfo : NSObject
@property (nonatomic,strong) NSString *ting_uid;
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSString *avatar_big;
@property (nonatomic,strong) NSString *avatar_middle;
@end

OMArtistInfo.m

#import "OMArtistInfo.h"

@implementation OMArtistInfo

@end

OMSongInfo.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "AFNetworking.h"
#import "MJExtension.h"
#import "OMHotSongInfo.h"


@interface OMSongInfo : NSObject
+ (OMSongInfo *)sharedManager;
@property (nonatomic,strong) UIImage *pic_big;
@property (nonatomic,strong) UIImage *pic_small;
@property (nonatomic,strong) NSString *song_id;
@property (nonatomic,strong) NSString *title;
@property (nonatomic,strong) NSString *author;
@property (nonatomic,strong) NSString *album_title;
@property (nonatomic,strong) NSString *file_duration;
@property (nonatomic,strong) NSString *file_link;
@property (nonatomic,strong) NSString *file_size;
@property (nonatomic,strong) NSString *lrclink;
@property (nonatomic,assign) BOOL isLrcExistFlg;
@property (nonatomic,strong) NSString *lrcString;
@property (nonatomic,strong) NSMutableDictionary *mLRCDictinary;
@property (nonatomic,strong) NSMutableArray *mTimeArray;
@property (nonatomic,assign) int lrcIndex;
@property (nonatomic,assign) long playSongIndex;
@property (nonatomic,assign) BOOL isDataRequestFinish;
@property (nonatomic,strong) NSArray *OMSongs;


- (void)loadNewSongs: (UITableView *)songListTableView;
- (void)loadHotSongs: (UITableView *)songListTableView;
- (void)loadHotArtists: (UITableView *)songListTableView;
- (void)loadClassicOldSongs: (UITableView *)songListTableView;
- (void)loadLoveSongs: (UITableView *)songListTableView;
- (void)loadMovieSongs: (UITableView *)songListTableView;
- (void)loadEuropeAndTheUnitedStatesSongs: (UITableView *)songListTableView;

-(void)getSelectedSong: (NSString *)songID index: (long)index;
-(void) setSongInfo: (OMHotSongInfo *)info;
-(NSString *)intToString: (int)needTransformInteger;
-(int) stringToInt: (NSString *)timeString;

@end

OMSongInfo.m

#import "OMSongInfo.h"

@implementation OMSongInfo

static OMSongInfo *_sharedManager = nil;

+(OMSongInfo *)sharedManager {
    @synchronized( [OMSongInfo class] ){
        if(!_sharedManager)
            _sharedManager = [[self alloc] init];
        return _sharedManager;
    }
    return nil;
}


#pragma mark - 获取歌曲url
-(void)getSelectedSong: (NSString *)songID index: (long)index {

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    NSString *path = [@"http://tingapi.ting.baidu.com/v1/restserver/ting?from=qianqian&version=2.1.0&method=baidu.ting.song.play&songid="  stringByAppendingString:songID];

    [manager GET:path parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if ([responseObject isKindOfClass:[NSDictionary class]])
        {
            NSDictionary *array = [responseObject objectForKey:@"bitrate"];

            self.file_link = [array objectForKey:@"file_link"];
            self.file_size = [array objectForKey:@"file_size"];
            self.file_duration = [array objectForKey:@"file_duration"];
            self.playSongIndex = index;
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"error--%@",error);
    }];

}


#pragma mark - 设置歌曲的所有信息
-(void) setSongInfo: (OMHotSongInfo *)info {

    self.title = info.title;
    self.author = info.author;
    self.album_title = info.author;
    self.lrclink = info.lrclink;

    NSString *path = info.pic_small;
    if (path)
    {
        NSURL *url = [NSURL URLWithString:path];

        @try {

            NSData *imageData = [NSData dataWithContentsOfURL:url];
            UIImage *albumArt = [UIImage imageWithData:imageData];

            if (albumArt)
            {
                self.pic_small = albumArt;
            }
            else
            {
                self.pic_small = [UIImage imageNamed:@"album_default"];
            }


        } @catch (NSException *exception) {
            NSLog(@"下载图片出错!");
        }


    }
    else
    {
        self.pic_small = [UIImage imageNamed:@"album_default"];
    }

    path = info.pic_big;
    if (path)
    {
        NSURL *url = [NSURL URLWithString:path];

        @try {

            NSData *imageData = [NSData dataWithContentsOfURL:url];
            UIImage *albumArt = [UIImage imageWithData:imageData];

            if (albumArt)
            {
                self.pic_big = albumArt;
            }
            else
            {
                self.pic_big = [UIImage imageNamed:@"album_default"];
            }


        } @catch (NSException *exception) {
            NSLog(@"下载图片出错!");
        }


    }
    else
    {
        self.pic_big = [UIImage imageNamed:@"album_default"];
    }

    path = info.lrclink;
    if (![path isEqualToString:@""] && path != nil)
    {
        NSURL *url = [NSURL URLWithString:path];

        @try {
            NSData *lrcData = [NSData dataWithContentsOfURL:url];
            NSString *lrcStr = [[NSString alloc] initWithData:lrcData encoding:NSUTF8StringEncoding];

            if (![lrcStr isEqualToString:@""] && lrcStr != nil) {
                self.lrcString = lrcStr;
                self.isLrcExistFlg = true;
            } else {
                NSLog(@"获取歌词出错!");
                self.isLrcExistFlg = false;
            }

        } @catch (NSException *exception) {
            NSLog(@"获取歌词出错!");
            self.isLrcExistFlg = false;
        }

    }
    else
    {
        NSLog(@"歌词不存在!");
        self.isLrcExistFlg = false;
    }

}

#pragma mark - int转NSString
-(NSString *)intToString: (int)needTransformInteger {

    //实现00:00这种格式播放时间
    int wholeTime = needTransformInteger;

    int min  = wholeTime / 60;

    int sec = wholeTime % 60;

    NSString *str = [NSString stringWithFormat:@"%02d:%02d", min , sec];

    return str;
}

#pragma mark - NSString转int
-(int) stringToInt: (NSString *)timeString {

    NSArray *strTemp = [timeString componentsSeparatedByString:@":"];

    int time = [strTemp.firstObject intValue] * 60 + [strTemp.lastObject intValue];

    return time;

}

@end

Const.h

#import <Foundation/Foundation.h>

// color const
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

// size const
#define ScreenWidth    ([UIScreen mainScreen].bounds.size.width)
#define ScreenHeight   ([UIScreen mainScreen].bounds.size.height)

// Music const
#define NEW_SONG_LIST           1
#define HOT_SONG_LIST           2
#define OLD_SONG_LIST           22
#define LOVE_SONG_LIST          23
#define INTERNET_SONG_LIST      25
#define MOVIE_SONG_LIST         24
#define EUROPE_SONG_LIST        21
#define BILLBOARD_MUSIC_LIST    8
#define ROCK_MUSIC_LIST         11
#define JAZZ_MUSIC_LIST         12
#define POP_MUSIC_LIST          16

@interface Const : NSObject

@end

Const.m

#import "Const.h"

@implementation Const

@end

TTTopChannelContianerView.h

#import <UIKit/UIKit.h>

@protocol TTTopChannelContianerViewDelegate <NSObject>

@optional

- (void)showOrHiddenAddChannelsCollectionView:(UIButton *)button;
- (void)chooseChannelWithIndex:(NSInteger)index;

@end

@interface TTTopChannelContianerView : UIView

- (instancetype)initWithFrame:(CGRect)frame;
- (void)addAChannelButtonWithChannelName:(NSString *)channelName;
- (void)selectChannelButtonWithIndex:(NSInteger)index;
- (void)deleteChannelButtonWithIndex:(NSInteger)index;

//- (void)didShowEditChannelView:(BOOL)value;

@property (nonatomic, strong) NSArray *channelNameArray;
@property (nonatomic, weak) UIScrollView *scrollView;
//@property (nonatomic, weak) UIButton *addButton;
@property (nonatomic, weak) id<TTTopChannelContianerViewDelegate> delegate;

@end

TTTopChannelContianerView.m

#import "TTTopChannelContianerView.h"


@interface TTTopChannelContianerView()

@property (nonatomic, weak) UIButton *lastSelectedButton;
@property (nonatomic, weak) UIView *indicatorView;

@end

static CGFloat kTitleLabelNorimalFont = 13;
static CGFloat kTitleLabelSelectedFont = 16;
static CGFloat kAddChannelWidth = 30;
static CGFloat kSliderViewWidth = 20;
static CGFloat buttonWidth = 70;

@implementation TTTopChannelContianerView

#pragma mark 初始化View
- (instancetype)initWithFrame:(CGRect)frame {
    if (self= [super initWithFrame:frame]) {
        [self initialization];
    }
    return self;
}

#pragma mark channelNameArray的setter方法,channelNameArray
- (void)setChannelNameArray:(NSArray *)channelNameArray {
    _channelNameArray = channelNameArray;
//    CGFloat buttonWidth = self.scrollView.frame.size.width/5;
    self.scrollView.contentSize = CGSizeMake(buttonWidth * channelNameArray.count, 0);
    for (NSInteger i = 0; i < channelNameArray.count; i++) {
        UIButton *button = [self createChannelButton];
        button.frame = CGRectMake(i*buttonWidth, 0, buttonWidth, self.frame.size.height);
        [button setTitle:channelNameArray[i] forState:UIControlStateNormal];
        [self.scrollView addSubview:button];
    }

    //默认选中第一个channelButton
    [self clickChannelButton:self.scrollView.subviews[1]];
}

#pragma mark 初始化子控件
- (void)initialization {
    self.alpha = 0.9;

    //初始化scrollView
    UIScrollView *scrollView = [self createScrollView];
    self.scrollView = scrollView;
    [self addSubview:self.scrollView];

    //初始化被选中channelButton的红线,也就是indicatorView
    UIView *indicatorView = [self createIndicatorView];
    self.indicatorView = indicatorView;
    [self.scrollView addSubview:self.indicatorView];

}

#pragma mark 创建容纳channelButton的ScrollView
- (UIScrollView *)createScrollView {
    UIScrollView *scrollView = [[UIScrollView alloc] init];
    self.scrollView = scrollView;
    scrollView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    return scrollView;
}



#pragma mark 初始化scrollView右侧的显示阴影效果的imageView
- (UIView *)createSliderView {
    UIImageView *slideView = [[UIImageView alloc] init];
    slideView.frame = CGRectMake(self.frame.size.width - kSliderViewWidth -kAddChannelWidth, 0, kSliderViewWidth, self.frame.size.height);
    slideView.alpha = 0.9;
    slideView.image = [UIImage imageNamed:@"slidetab_mask"];
    return slideView;
}

#pragma mark 创建被选中channelButton的红线,也就是indicatorView
- (UIView *)createIndicatorView {
    UIView *indicatorView = [[UIView alloc] init];
    indicatorView.backgroundColor = [UIColor colorWithRed:243/255.0 green:75/255.0 blue:80/255.0 alpha:1.0];
    [self addSubview:indicatorView];
    return indicatorView;
}

#pragma mark 创建ChannelButton
- (UIButton *)createChannelButton{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0]];
    [button setTitleColor:[UIColor colorWithRed:243/255.0 green:75/255.0 blue:80/255.0 alpha:1.0] forState:UIControlStateDisabled];
    [button.titleLabel setFont:[UIFont systemFontOfSize:kTitleLabelNorimalFont]];
    [button addTarget:self action:@selector(clickChannelButton:) forControlEvents:UIControlEventTouchUpInside];
    [button layoutIfNeeded];
    return button;
}

#pragma mark 选择了某个ChannelButton
- (void)clickChannelButton:(UIButton *)sender {
    self.lastSelectedButton.titleLabel.font = [UIFont systemFontOfSize:kTitleLabelNorimalFont];
    self.lastSelectedButton.enabled = YES;
    self.lastSelectedButton = sender;
    self.lastSelectedButton.enabled = NO;
    //选中的标签要居中,也就是scrollView的offset.x加屏幕的一半要等于标签的中心
    CGFloat newOffsetX = sender.center.x - [UIScreen mainScreen].bounds.size.width*0.5;
    if (newOffsetX < 0) {
        newOffsetX = 0;
    }
    if (newOffsetX > self.scrollView.contentSize.width - self.scrollView.frame.size.width) {
        newOffsetX = self.scrollView.contentSize.width - self.scrollView.frame.size.width;
    }
    [UIView animateWithDuration:0.25 animations:^{
        [sender.titleLabel setFont:[UIFont systemFontOfSize:kTitleLabelSelectedFont]];
        [sender layoutIfNeeded];
        [self.scrollView setContentOffset:CGPointMake(newOffsetX, 0)];
        //indicatorView宽度会比titleLabel宽20,centerX与titleLabel相同
        self.indicatorView.frame = CGRectMake(sender.frame.origin.x + sender.titleLabel.frame.origin.x - 10, self.frame.size.height - 2, sender.titleLabel.frame.size.width + 20, 2);
    }];

    //因为subviews包含indicatorView,所以index需要减1
    NSInteger index = [self.scrollView.subviews indexOfObject:sender] - 1;
    if ([self.delegate respondsToSelector:@selector(chooseChannelWithIndex:)]) {
        [self.delegate chooseChannelWithIndex:index];
    }
}

#pragma mark 选中某个ChannelButton
- (void)selectChannelButtonWithIndex:(NSInteger)index {
    self.indicatorView.hidden = NO;
    //因为subviews包含indicatorView,所以index需要加1
    [self clickChannelButton:self.scrollView.subviews[index+1]];
}

#pragma mark 删除某个ChannelButton
- (void)deleteChannelButtonWithIndex:(NSInteger)index {
    //删除index对应的button,因为subviews包含indicatorView,所以index需要加1
    NSInteger realIndex= index + 1;
    [self.scrollView.subviews[realIndex] removeFromSuperview];
    //后面的button的x向左移动buuton宽度的距离
    for (NSInteger i = realIndex; i<self.scrollView.subviews.count; i++) {
        UIButton *button = self.scrollView.subviews[i];
        CGRect buttonFrame = button.frame;
        button.frame = CGRectMake(buttonFrame.origin.x - button.frame.size.width, buttonFrame.origin.y, buttonFrame.size.width, buttonFrame.size.height);
    }

    //将scrollView的contentSize减小一个buuton的宽度
    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width - self.scrollView.frame.size.width/5, 0);
}

#pragma mark 添加新闻频道:增加scrollView的contensize,然后在最后添加一个channelButton
- (void)addAChannelButtonWithChannelName:(NSString *)channelName {
//    CGFloat buttonWidth = self.scrollView.frame.size.width/5;
    UIButton *button = [self createChannelButton];
    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width + buttonWidth, 0);
    button.frame = CGRectMake(self.scrollView.contentSize.width - buttonWidth , 0, buttonWidth, self.frame.size.height);
    [button setTitle:channelName forState:UIControlStateNormal];
    [self.scrollView addSubview:button];
}



@end

SCImageView.h

#import <UIKit/UIKit.h>

@interface SCImageView : UIImageView

-(void) startRotating;
-(void) stopRotating;
-(void) resumeRotate;

@end

SCImageView.m

#import "SCImageView.h"

@implementation SCImageView

// 开始旋转
-(void) startRotating {
    CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotateAnimation.fromValue = [NSNumber numberWithFloat:0.0];
    rotateAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2];   // 旋转一周
    rotateAnimation.duration = 20.0;                                 // 旋转时间20秒
    rotateAnimation.repeatCount = MAXFLOAT;                          // 重复次数,这里用最大次数

    [self.layer addAnimation:rotateAnimation forKey:nil];

}

// 停止旋转
-(void) stopRotating {

    CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    self.layer.speed = 0.0;                                          // 停止旋转
    self.layer.timeOffset = pausedTime;                              // 保存时间,恢复旋转需要用到
}

// 恢复旋转
-(void) resumeRotate {

    if (self.layer.timeOffset == 0) {
        [self startRotating];
        return;
    }

    CFTimeInterval pausedTime = self.layer.timeOffset;
    self.layer.speed = 1.0;                                         // 开始旋转
    self.layer.timeOffset = 0.0;
    self.layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;                                             // 恢复时间
    self.layer.beginTime = timeSincePause;                          // 从暂停的时间点开始旋转
}

@end

SimpleControlView.h

#import <UIKit/UIKit.h>

#define ScreenWidth UIScreen.mainScreen.bounds.size.width
#define ScreenHeight UIScreen.mainScreen.bounds.size.height

@interface SimpleControlView : UIView

@property (nonatomic, strong) UIImageView *albumImage;
@property (nonatomic, strong) UILabel *songName;
@property (nonatomic, strong) UILabel *singerName;
@property (nonatomic, strong) UIButton *playOrPauseBtn;
@property (nonatomic, strong) UIButton *nextBtn;

@end

SimpleControlView.m

#import "SimpleControlView.h"
#import "Masonry.h"
#import "Const.h"

@implementation SimpleControlView

-(instancetype) initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {

        [self setBackgroundColor:UIColorFromRGB(0xff0000)];
        //创建imageView添加到SimpleControlView中
        _albumImage = [[UIImageView alloc] init];
        [self addSubview:_albumImage];

        [_albumImage mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(self.mas_left).with.offset(5);
            make.width.mas_equalTo(60);
            make.height.mas_equalTo(60);
            make.bottom.equalTo(self.mas_bottom).with.offset(-5);
        }];

        // 创建歌名label添加到SimpleControlView中
        _songName = [[UILabel alloc] init];
        _songName.font = [UIFont systemFontOfSize:18.0];
        [_songName setTextColor:UIColorFromRGB(0x000000)];
        [self addSubview:_songName];

        [_songName mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(_albumImage.mas_right).with.offset(5);
            make.width.mas_equalTo(150);
            make.height.mas_equalTo(35);
            make.bottom.equalTo(self.mas_bottom).with.offset(-30);
        }];

        // 创建歌手名label添加到SimpleControlView中
        _singerName = [[UILabel alloc] init];
        _singerName.font = [UIFont systemFontOfSize:12.0];
         [_singerName setTextColor:UIColorFromRGB(0x000000)];
        [self addSubview:_singerName];

        [_singerName mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(_songName.mas_bottom).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(_albumImage.mas_right).with.offset(5);
            make.width.mas_equalTo(150);
            make.height.mas_equalTo(20);
            make.bottom.equalTo(self.mas_bottom).with.offset(-5);
        }];

        // 创建下一曲按键添加到SimpleControlView中
        _nextBtn = [[UIButton alloc] init];
        [_nextBtn  setImage:[UIImage imageNamed:@"cm2_fm_btn_next"] forState:UIControlStateNormal];
        [_nextBtn setImage:[UIImage imageNamed:@"cm2_fm_btn_next_prs"] forState:UIControlStateHighlighted];
        [self addSubview:_nextBtn];

        [_nextBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(10); //with is an optional semantic filler
            make.right.equalTo(self.mas_right).with.offset(20);
            make.width.mas_equalTo(50);
            make.height.mas_equalTo(50);
            make.bottom.equalTo(self.mas_bottom).with.offset(-10);
        }];

        // 创建播放暂停按键添加到SimpleControlView中
        _playOrPauseBtn = [[UIButton alloc] init];
        [_playOrPauseBtn setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
        [_playOrPauseBtn setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
        [self addSubview:_playOrPauseBtn];

        [_playOrPauseBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(10); //with is an optional semantic filler
            make.right.equalTo(_nextBtn.mas_right).with.offset(10);
            make.width.mas_equalTo(50);
            make.height.mas_equalTo(50);
            make.bottom.equalTo(self.mas_bottom).with.offset(-10);
        }];


    }

    return self;
}

@end

TopView.h

#import <UIKit/UIKit.h>

@interface TopView : UIView

@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UILabel *songTitleLabel;
@property (nonatomic, strong) UILabel *singerNameLabel;

@end

TopView.m

#import "TopView.h"

@implementation TopView

-(instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];

    _backBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 30, 40, 40)];
    [_backBtn setImage:[UIImage imageNamed:@"cm2_live_btn_back"] forState:UIControlStateNormal];
    [_backBtn setImage:[UIImage imageNamed:@"cm2_live_btn_back_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_backBtn];

    _songTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, frame.size.width - 20, frame.size.height / 2)];
    [_songTitleLabel setFont:[UIFont systemFontOfSize:20.0]];
    [_songTitleLabel setTextColor:[UIColor whiteColor]];
    [_songTitleLabel setText:@""];
    _songTitleLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview: _songTitleLabel];

    _singerNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, frame.size.height / 2 - 20, frame.size.width - 20, frame.size.height / 2 - 30)];
    [_singerNameLabel setFont:[UIFont systemFontOfSize:17.0]];
    [_singerNameLabel setTextColor:[UIColor whiteColor]];
    [_singerNameLabel setText:@""];
    _singerNameLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview: _singerNameLabel];

    return self;
}

@end

MidView.h

#import <UIKit/UIKit.h>
#import "SCIconView.h"
#import "SCLrcTableView.h"


@interface MidView : UIScrollView<UIScrollViewDelegate>

@property (nonatomic, strong) SCIconView* midIconView;
@property (nonatomic, strong) SCLrcTableView *midLrcView;

@end

MidView.m

#import "MidView.h"

#define Screen_Width    ([UIScreen mainScreen].bounds.size.width)
#define Screen_Height   ([UIScreen mainScreen].bounds.size.height)

@implementation MidView

-(instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    self.delegate = self;

    self.showsHorizontalScrollIndicator = false;

    self.pagingEnabled = true;

    self.contentSize = CGSizeMake(Screen_Width * 2, 0);

    // 专辑图片视图配置
    _midIconView = [[SCIconView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, frame.size.height)];
    [self addSubview:_midIconView];

    // 歌词视图配置
    _midLrcView = [[SCLrcTableView alloc] initWithStyle:UITableViewStylePlain];
    [_midLrcView SC_SetUpLrcTableViewFrame:CGRectMake(Screen_Width, 0, frame.size.width, frame.size.height)];
    _midLrcView.tableView.allowsSelection = false;
    _midLrcView.tableView.backgroundColor = [UIColor clearColor];
    _midLrcView.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    _midLrcView.tableView.showsVerticalScrollIndicator = false;
    _midLrcView.tableView.contentInset = UIEdgeInsetsMake(frame.size.height / 2, 0, frame.size.height / 2, 0);
    [self addSubview:_midLrcView.view];

    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {

    }
    return self;
}

-(void) scrollViewDidScroll: (UIScrollView *)scrollView {

    double spread = self.contentOffset.x / Screen_Width;

    _midIconView.alpha =  1.0 - spread;

    _midLrcView.tableView.alpha = spread;

}

@end

SCLrcTableView.h

#import <UIKit/UIKit.h>
#import "SCLrcTableViewCell.h"
#import "OMSongInfo.h"

@interface SCLrcTableView : UITableViewController
@property (nonatomic, assign) int Lrc_Index;
@property (nonatomic, assign) SCLrcTableViewCell *currentCell;
@property (nonatomic, assign) SCLrcTableViewCell *lrcOldCell;

//用来显示锁屏歌词
@property (nonatomic, strong) UITableView * lockScreenTableView;
@property (nonatomic, assign) SCLrcTableViewCell *lockCurrentCell;
@property (nonatomic, assign) SCLrcTableViewCell *loackLrcOldCell;
@property (nonatomic,assign)  NSInteger currentRow;
@property (nonatomic, assign) BOOL isDragging;

@property (nonatomic, assign) int old_Index;
@property (nonatomic, assign) int mLineNumber;
@property (nonatomic, assign) BOOL mIsLRCPrepared;

-(instancetype)initWithStyle:(UITableViewStyle)style;
-(void) SC_SetUpLrcTableViewFrame: (CGRect)frame;
-(void) setLrc_Index: (int)lrc_index;
-(void) AnalysisLRC: (NSString *)lrcPath;
-(UIImage *)getBlurredImage:(UIImage *)image;

@end

SCLrcTableView.m

#import "SCLrcTableView.h"

@implementation SCLrcTableView

extern OMSongInfo *songInfo;

-(void) setLrc_Index: (int)lrc_index {
    if (_Lrc_Index == lrc_index || lrc_index > songInfo.mLRCDictinary.count - 1) {
        return;
    }

    // 滚动到制定的位置
    // 新的indexPath
    id indexPath = [NSIndexPath indexPathForRow:lrc_index inSection:0];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow: lrc_index inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
//    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:true];

    UITableViewCell *currentCell = [self.tableView cellForRowAtIndexPath:indexPath];
    _currentCell = (SCLrcTableViewCell *)currentCell;
    [_currentCell.textLabel setTextColor:[UIColor redColor]];

    id oldIndexPath = [NSIndexPath indexPathForRow:_Lrc_Index inSection:0];
    UITableViewCell *oldCell = [self.tableView cellForRowAtIndexPath:oldIndexPath];
    _lrcOldCell = (SCLrcTableViewCell *)oldCell;
    [_lrcOldCell.textLabel setTextColor:[UIColor whiteColor]];


    [_currentCell addAnimation:scaleAlways];

//    [self.tableView reloadData];

    // 锁屏歌词更新
//    [_lockScreenTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:true];
    [_lockScreenTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow: lrc_index inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

    UITableViewCell *lockCurrentCell = [_lockScreenTableView cellForRowAtIndexPath:indexPath];
    _currentCell = (SCLrcTableViewCell *)lockCurrentCell;
    [_currentCell.textLabel setTextColor:[UIColor redColor]];

    id lockOldIndexPath = [NSIndexPath indexPathForRow:_Lrc_Index inSection:0];
    UITableViewCell *lockOldCell = [_lockScreenTableView cellForRowAtIndexPath:lockOldIndexPath];
    _lrcOldCell = (SCLrcTableViewCell *)lockOldCell;
    [_lrcOldCell.textLabel setTextColor:[UIColor whiteColor]];
//    [_lockScreenTableView reloadData];

    // 更新歌词index
    _Lrc_Index = lrc_index;
}

-(instancetype)initWithStyle:(UITableViewStyle)style {
    self = [super initWithStyle:style];
    if (self) {
        songInfo.mLRCDictinary = [[NSMutableDictionary alloc] init];
        songInfo.mTimeArray = [[NSMutableArray alloc] init];

        if (!_lockScreenTableView) {
            _lockScreenTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 800 - 44 * 7 + 20, 480, 44 * 3) style:UITableViewStyleGrouped];
            _lockScreenTableView.dataSource = self;
            _lockScreenTableView.delegate = self;
            _lockScreenTableView.separatorStyle = NO;
            _lockScreenTableView.backgroundColor = [UIColor clearColor];
            [_lockScreenTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"lrccellID"];
        }
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {

    }
    return self;
}

-(void) SC_SetUpLrcTableViewFrame: (CGRect)frame {
    self.view.frame = frame;
}


-(void) AnalysisLRC: (NSString *)lrcStr {

    if (songInfo.isLrcExistFlg) {
        NSString* contentStr = lrcStr;

        NSArray *lrcArray = [contentStr componentsSeparatedByString:@"\n"];

        [songInfo.mLRCDictinary removeAllObjects];
        [songInfo.mTimeArray removeAllObjects];

        for (NSString *line in lrcArray) {

            // 首先处理歌词中无用的东西
            // [ti:][ar:][al:]这类的直接跳过
            if ([line containsString:@"[0"] || [line containsString:@"[1"] || [line containsString:@"[2"] || [line containsString:@"[3"]) {
                NSArray *lineArr = [line componentsSeparatedByString:@"]"];
                NSString *str1 = [line substringWithRange:NSMakeRange(3, 1)];
                NSString *str2 = [line substringWithRange:NSMakeRange(6, 1)];

                if ([str1 isEqualToString:@":"] && [str2 isEqualToString:@"."]) {
                    NSString *lrcStr = lineArr[1];
                    NSString *timeStr = [lineArr[0] substringWithRange:NSMakeRange(1, 5)];
                    [songInfo.mLRCDictinary setObject:lrcStr forKey:timeStr];
                    [songInfo.mTimeArray addObject:timeStr];
                }
            } else {
                continue;
            }
        }

        _mIsLRCPrepared = true;
        [self.tableView reloadData];
    } else {
        [songInfo.mLRCDictinary removeAllObjects];
        [songInfo.mTimeArray removeAllObjects];

        [songInfo.mLRCDictinary setObject:@"没有找到该歌词" forKey:@"0:0"];
        [songInfo.mTimeArray addObject:@"0:0"];
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
        [self.tableView reloadData];
    }


}

-(UIImage *)getBlurredImage:(UIImage *)image{
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *ciImage=[CIImage imageWithCGImage:image.CGImage];
    CIFilter *filter=[CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@5.0f forKey:@"inputRadius"];
    CIImage *result=[filter valueForKey:kCIOutputImageKey];
    CGImageRef ref=[context createCGImage:result fromRect:[result extent]];
    return [UIImage imageWithCGImage:ref];
}


#pragma - mark tableView
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return songInfo.mLRCDictinary.count;

}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    SCLrcTableViewCell *cell = [SCLrcTableViewCell SC_CellForRowWithTableVieW:tableView];

    cell.textLabel.text = songInfo.mLRCDictinary[songInfo.mTimeArray[indexPath.row]];
    [cell.textLabel setFont:[UIFont systemFontOfSize:16.0]];
    cell.textLabel.textAlignment = NSTextAlignmentCenter;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
    [cell setBackgroundColor:[UIColor clearColor]];
    cell.textLabel.backgroundColor = [UIColor clearColor];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    if (_currentRow == indexPath.row) {
        cell.textLabel.textColor = [UIColor redColor];
        //cell.textLabel.alpha = 1.0;
    }else{
        cell.textLabel.textColor = [UIColor whiteColor];
        //cell.textLabel.alpha = 1.0 - (float)(labs(indexPath.row - _currentRow)) / 6;
    }

    return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    _isDragging = YES;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    _isDragging = NO;
}

@end

SCLrcTableViewCell.h

#import <UIKit/UIKit.h>

@interface SCLrcTableViewCell : UITableViewCell

typedef enum SC_AnimationType {
    translation,
    scale,
    rotation,
    scaleAlways,
    scaleNormal,
}AnimationType;


+(SCLrcTableViewCell *) SC_CellForRowWithTableVieW: (UITableView *) tableView;
-(void)addAnimation: (AnimationType)animationType;

@end

SCLrcTableViewCell.m

#import "SCLrcTableViewCell.h"

@implementation SCLrcTableViewCell


AnimationType *animationType = translation;

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

+(SCLrcTableViewCell *) SC_CellForRowWithTableVieW: (UITableView *) tableView {

    NSString *cellID = @"lrccellID";
    SCLrcTableViewCell *cell = (SCLrcTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellID];

    if (cell == nil) {
        cell = [[SCLrcTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
        [cell setBackgroundColor:[UIColor clearColor]];
    }

    return cell;
}

-(void)addAnimation: (AnimationType)animationType {
    switch (animationType) {
        case translation:
        {
            [self.layer removeAnimationForKey:@"translation"];
            CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
            animation.values = [NSArray arrayWithObjects:[NSNumber numberWithDouble:50], [NSNumber numberWithDouble:0], [NSNumber numberWithDouble:50], [NSNumber numberWithDouble:0], nil];
            animation.duration = 0.7;
            animation.repeatCount = 1;
            [self.layer addAnimation:animation forKey:@"translation"];
            break;
        }
        case scale:
        {
            [self.layer removeAnimationForKey:@"scale"];
            CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];

            animation.values = [NSArray arrayWithObjects:[NSNumber numberWithDouble:0.5], [NSNumber numberWithDouble:1.0], nil];
            animation.duration = 0.7;
            animation.repeatCount = 1;
            animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

            [self.layer addAnimation:animation forKey:@"scale"];
            break;
        }
        case rotation:
        {
            [self.layer removeAnimationForKey:@"rotation"];
            CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
            animation.values = [NSArray arrayWithObjects:[NSNumber numberWithDouble:(-1 / 6 * M_PI)], [NSNumber numberWithDouble:0], [NSNumber numberWithDouble:(1 / 6 * M_PI)], [NSNumber numberWithDouble:0], nil];
            animation.duration = 0.7;
            animation.repeatCount = 1;
            [self.layer addAnimation:animation forKey:@"rotation"];
            break;
        }
        case scaleAlways:
        {
//            [self.layer removeAnimationForKey:@"scale"];
            CABasicAnimation *animatio1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

            animatio1.repeatCount = 1;
            animatio1.duration = 0.6;
//            animatio1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//            animatio1.removedOnCompletion = false;
//            animatio1.fillMode = kCAFillModeForwards;

            animatio1.autoreverses = YES; // 动画结束时执行逆动画

            // 缩放倍数
            animatio1.fromValue = [NSNumber numberWithFloat:1.0]; // 开始时的倍率
            animatio1.toValue = [NSNumber numberWithFloat:1.2]; // 结束时的倍率
            [self.layer addAnimation:animatio1 forKey:@"scale-layer"];

//            NSLog(@"scaleAlways");
//            CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
//            animation.values = [NSArray arrayWithObjects:[NSNumber numberWithDouble:(-1 / 6 * M_PI)], [NSNumber numberWithDouble:0], [NSNumber numberWithDouble:(1 / 6 * M_PI)], [NSNumber numberWithDouble:0], nil];
//        
//            animation.duration = 0.7;
//            animation.repeatCount = 1;
//            animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//            animation.removedOnCompletion = false;
//            animation.fillMode = kCAFillModeForwards;
//            [self.layer addAnimation:animation forKey:@"scale"];

            break;
        }
        case scaleNormal:
        {
//             [self.layer removeAnimationForKey:@"scale"];
//            CAPropertyAnimation *animation =[CAKeyframeAnimation animationWithKeyPath:@"transform.scale.x"];
//    
//            animation.autoreverses = true;
//            animation.duration = 0.7;
//            animation.repeatCount = 1;
//            animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//            [self.layer addAnimation:animation forKey:@"scale"];

            break;
        }
        default: break;

    }
}

@end

SCIconView.m

#import "SCIconView.h"


@implementation SCIconView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    return self;
}

-(void) setAlbumImage: (UIImage *)image {
    _imageView = [[SCImageView alloc] initWithFrame:CGRectMake(self.frame.size.width * 0.1, self.frame.size.height / 2 - self.frame.size.width * 0.4 , self.frame.size.width * 0.8, self.frame.size.width * 0.8)];
    _imageView.image = image;
    _imageView.clipsToBounds = true;
    _imageView.layer.cornerRadius = self.frame.size.width * 0.4;
    [self addSubview:_imageView];
}

@end

SCIconView.h

#import <UIKit/UIKit.h>
#import "SCImageView.h"

@interface SCIconView : UIView

@property(nonatomic, strong) SCImageView *imageView;

- (instancetype)initWithFrame:(CGRect)frame;
-(void) setAlbumImage: (UIImage *)image;

@end

BottomView.h

#import <UIKit/UIKit.h>


@interface BottomView : UIView

@property (nonatomic, strong) UIButton *preSongButtton;
@property (nonatomic, strong) UIButton *nextSongButton;
@property (nonatomic, strong) UIButton *playOrPauseButton;
@property (nonatomic, strong) UIButton *playModeButton;
@property (nonatomic, strong) UIButton *songListButton;
@property (nonatomic, strong) UISlider *songSlider;
@property (nonatomic, strong) UILabel *currentTimeLabel;
@property (nonatomic, strong) UILabel *durationTimeLabel;

@end

BottomView.m

#import "BottomView.h"

@implementation BottomView


-(instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];

    // 上一曲按键设置
    _preSongButtton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width / 5, frame.size.height / 2.3, frame.size.width * 0.2, frame.size.width * 0.2)];
    [_preSongButtton setImage:[UIImage imageNamed:@"cm2_fm_btn_pre"] forState:UIControlStateNormal];
    [_preSongButtton setImage:[UIImage imageNamed:@"cm2_fm_btn_pre_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_preSongButtton];

    // 播放或暂停按键设置
    _playOrPauseButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width / 2 - frame.size.width * 0.1, frame.size.height / 2.3, frame.size.width * 0.2, frame.size.width * 0.2)];
    [_playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause"] forState:UIControlStateNormal];
    [_playOrPauseButton setImage:[UIImage imageNamed:@"cm2_fm_btn_pause_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_playOrPauseButton];

    // 下一曲按键设置
    _nextSongButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width / 5 * 4 - frame.size.width * 0.2, frame.size.height / 2.3, frame.size.width * 0.2, frame.size.width * 0.2)];
    [_nextSongButton setImage:[UIImage imageNamed:@"cm2_fm_btn_next"] forState:UIControlStateNormal];
    [_nextSongButton setImage:[UIImage imageNamed:@"cm2_fm_btn_next_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_nextSongButton];

    // 播放模式按键设置
    _playModeButton = [[UIButton alloc] initWithFrame:CGRectMake(0, frame.size.height / 2.3, frame.size.width * 0.2, frame.size.width * 0.2)];
    [_playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
    [_playModeButton setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_playModeButton];

    // 歌曲列表按键设置
    _songListButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width * 4 / 5, frame.size.height / 2.3, frame.size.width * 0.2, frame.size.width * 0.2)];
    [_songListButton setImage:[UIImage imageNamed:@"cm2_icn_list"] forState:UIControlStateNormal];
    [_songListButton setImage:[UIImage imageNamed:@"cm2_icn_list_prs"] forState:UIControlStateHighlighted];
    [self addSubview:_songListButton];

    // 播放进度条
    _songSlider = [[UISlider alloc] initWithFrame:CGRectMake(frame.size.width / 6, frame.size.height / 4, frame.size.width * 2 / 3 , frame.size.height* 0.2)];
    [_songSlider setThumbImage:[UIImage imageNamed:@"cm2_detail_knob_nomal"] forState:UIControlStateNormal];
    [_songSlider setThumbImage:[UIImage imageNamed:@"cm2_detail_knob_prs"] forState:UIControlStateHighlighted];
    _songSlider.tintColor = [UIColor whiteColor];
    [self addSubview:_songSlider];


    // 当前播放时间
    _currentTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, frame.size.height / 4,  frame.size.width / 6 - 10, frame.size.height* 0.2)];
    [_currentTimeLabel setTextColor:[UIColor whiteColor]];
    [_currentTimeLabel setText:@"00:00"];
    [_currentTimeLabel setFont:[UIFont systemFontOfSize:15.0]];
    _currentTimeLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview:_currentTimeLabel];

    // 整歌时间
    _durationTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(frame.size.width * 5 / 6 + 5, frame.size.height / 4,  frame.size.width / 6 - 10, frame.size.height* 0.2)];
    [_durationTimeLabel setTextColor:[UIColor whiteColor]];
    [_durationTimeLabel setText:@"00:00"];
    [_durationTimeLabel setFont:[UIFont systemFontOfSize:15.0]];
    _durationTimeLabel.textAlignment = NSTextAlignmentCenter;
    [self addSubview:_durationTimeLabel];


    return self;
}


@end

SongListTableView.h

#import <UIKit/UIKit.h>

@interface SongListTableView : UITableView <UITableViewDelegate, UITableViewDataSource>

@end

SongListTableView.m

#import "SongListTableView.h"
#import "SongListTableViewCell.h"
#import "MusicPlayerManager.h"
#import "OMSongInfo.h"
#import "OMHotSongInfo.h"

static NSString *CellIdentifier = @"SCTableViewCell";
static NSString *PlaceholderCellIdentifier = @"PlaceholderCell";

extern MusicPlayerManager *musicPlayer;
extern OMSongInfo *songInfo;

@implementation SongListTableView


-(instancetype) initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

        // musicPlayer和songInfo初始化
        musicPlayer = MusicPlayerManager.sharedManager;
        songInfo = OMSongInfo.sharedManager;

        // tableView初始化
        self.delegate = self;
        self.dataSource = self;
        self.sectionHeaderHeight = 0.1;
        self.separatorStyle = UITableViewCellSeparatorStyleNone;
        self.scrollIndicatorInsets = UIEdgeInsetsMake(104, 0, 0, 0);
        [self reloadData];
    }
    return self;
}




#pragma mark - UITableViewDataSource

// -------------------------------------------------------------------------------
//  numberOfSectionsInTableView
//  height of tableView.
// -------------------------------------------------------------------------------
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}


// -------------------------------------------------------------------------------
//  tableView:heightForRowAtIndexPath:
//  height of tableView.
// -------------------------------------------------------------------------------
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 70;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return songInfo.OMSongs.count;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    OMHotSongInfo *info = songInfo.OMSongs[indexPath.row];

    SongListTableViewCell *cell = (SongListTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[SongListTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:CellIdentifier];
    }

    cell.songNumber.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];
    cell.songName.text = info.title;
    cell.singerName.text = info.author;


    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    OMHotSongInfo *info = songInfo.OMSongs[indexPath.row];
    NSLog(@"你选择了《%@》这首歌", info.title);
    [songInfo setSongInfo:info];
    [songInfo getSelectedSong:info.song_id index:indexPath.row];

}



@end

SongListTableViewCell.h

#import <UIKit/UIKit.h>
#import "Masonry.h"

@interface SongListTableViewCell : UITableViewCell

@property (nonatomic, strong) UILabel *songNumber;
@property (nonatomic, strong) UILabel *songName;
@property (nonatomic, strong) UILabel *singerName;
@property (nonatomic, strong) UIButton *playOrPauseBtn;
@property (nonatomic, strong) UIButton *nextBtn;
@property (nonatomic, strong) UIButton *detailControllerBtn;

@end

SongListTableViewCell.m

#import "SongListTableViewCell.h"

@implementation SongListTableViewCell

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

        self.backgroundColor = [UIColor clearColor];

        //创建imageView添加到cell中
        _songNumber = [[UILabel alloc] init];
        _songNumber.font = [UIFont systemFontOfSize:20.0];
        _songNumber.textColor = [UIColor blackColor];
        _songNumber.textAlignment = NSTextAlignmentCenter;
        [self addSubview:_songNumber];

        [_songNumber mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(self.mas_left).with.offset(5);
            make.width.mas_equalTo(60);
            make.height.mas_equalTo(60);
            make.bottom.equalTo(self.mas_bottom).with.offset(-5);
        }];

        // 创建歌名label添加到cell中
        _songName = [[UILabel alloc] init];
        _songName.font = [UIFont systemFontOfSize:18.0];
        _songName.textColor = [UIColor blackColor];
        [self addSubview:_songName];

        [_songName mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.mas_top).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(_songNumber.mas_right).with.offset(5);
            make.width.mas_equalTo(150);
            make.height.mas_equalTo(35);
            make.bottom.equalTo(self.mas_bottom).with.offset(-30);
        }];

        // 创建歌手名label添加到cell中
        _singerName = [[UILabel alloc] init];
        _singerName.font = [UIFont systemFontOfSize:12.0];
        _singerName.textColor = [UIColor blackColor];
        [self addSubview:_singerName];

        [_singerName mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(_songName.mas_bottom).with.offset(5); //with is an optional semantic filler
            make.left.equalTo(_songNumber.mas_right).with.offset(5);
            make.width.mas_equalTo(150);
            make.height.mas_equalTo(20);
            make.bottom.equalTo(self.mas_bottom).with.offset(-5);
        }];

    }

    return self;
}

@end

SongListTopView.h

#import <UIKit/UIKit.h>

@interface SongListTopView : UIView

@property (nonatomic, strong) UIButton *playMode;

@end

SongListTopView.m

#import "SongListTopView.h"

@implementation SongListTopView

-(instancetype) initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

        // 播放模式按键初始化
        _playMode = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width / 2.5, self.frame.size.height)];
        [self addSubview:_playMode];

    }
    return self;
}

@end

SongListView.h

#import <UIKit/UIKit.h>
#import "OMSongInfo.h"
#import "MusicPlayerManager.h"
#import "SongListTopView.h"
#import "SongListTableView.h"
#import "Const.h"
#import "MBProgressHUD.h"

@interface SongListView : UIView

@property (nonatomic, strong) SongListTopView *topView;
@property (nonatomic, strong) SongListTableView *tableView;

-(void) setPlayModeButtonState;

@end

SongListView.m

#import "SongListView.h"

@implementation SongListView

extern MusicPlayerManager *musicPlayer;
extern OMSongInfo *songInfo;

-(instancetype) initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

        // musicPlayer和songInfo初始化
        musicPlayer = MusicPlayerManager.sharedManager;
        songInfo = OMSongInfo.sharedManager;

        //topView
        _topView = [[SongListTopView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height / 9)];
        _topView.backgroundColor = UIColorFromRGB(0xaaaaaa);
        [_topView.playMode addTarget:self action:@selector(playModeButtonAction) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_topView];

        //tableView
        _tableView = [[SongListTableView alloc] initWithFrame:CGRectMake(0, self.frame.size.height / 9, self.frame.size.width, self.frame.size.height / 9 * 8)];
       _tableView.backgroundColor = [UIColor whiteColor];
        [self addSubview:_tableView];


    }
    return self;
}


-(void) setPlayModeButtonState {
    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode://顺序播放
        {
            NSString *title = [NSString stringWithFormat:@"顺序播放(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = RepeatPlayMode;
        }
            break;
        case RepeatOnlyOnePlayMode://单曲循环
        {
            NSString *title = [NSString stringWithFormat:@"单曲循环(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_one"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_one_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = RepeatOnlyOnePlayMode;  //单曲循环
        }
            break;
        case ShufflePlayMode://随机播放
        {
            NSString *title = [NSString stringWithFormat:@"随机播放(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_shuffle"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_shuffle_prs"] forState:UIControlStateHighlighted];
            musicPlayer.shuffleAndRepeatState = ShufflePlayMode;
        }
            break;
        default:
            break;
    }
}

-(void) playModeButtonAction {
    switch (musicPlayer.shuffleAndRepeatState)
    {
        case RepeatPlayMode://顺序播放
        {
            NSString *title = [NSString stringWithFormat:@"单曲循环(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_one"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_one_prs"] forState:UIControlStateHighlighted];
            [self showMiddleHint:@"单曲循环"];
            musicPlayer.shuffleAndRepeatState = RepeatOnlyOnePlayMode;  //单曲循环
        }
            break;
        case RepeatOnlyOnePlayMode://单曲循环
        {
            NSString *title = [NSString stringWithFormat:@"随机播放(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_shuffle"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_shuffle_prs"] forState:UIControlStateHighlighted];
            [self showMiddleHint:@"随机播放"];
            musicPlayer.shuffleAndRepeatState = ShufflePlayMode;
        }
            break;
        case ShufflePlayMode://随机播放
        {
            NSString *title = [NSString stringWithFormat:@"顺序播放(%lu)", (unsigned long)songInfo.OMSongs.count];
            [_topView.playMode setTitle:title forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_loop"] forState:UIControlStateNormal];
            [_topView.playMode setImage:[UIImage imageNamed:@"cm2_icn_loop_prs"] forState:UIControlStateHighlighted];
            [self showMiddleHint:@"顺序播放"];
            musicPlayer.shuffleAndRepeatState = RepeatPlayMode;
        }
            break;
        default:
            break;
    }
}

#pragma mark - 播放模式提示框
- (void)showMiddleHint:(NSString *)hint {

    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.superview animated:YES];

    hud.userInteractionEnabled = NO;
    hud.mode = MBProgressHUDModeText;
    hud.label.font = [UIFont systemFontOfSize:15];
    hud.label.text = hint;
    hud.margin = 10.f;
    hud.offset = CGPointMake(0.f, 0.f);
    hud.removeFromSuperViewOnHide = YES;
    [hud hideAnimated:YES afterDelay:2.f];
}

@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值