網易雲音樂鎖屏界面效果實現


最終效果:

 鎖屏界面

完整的實現思路:

  1. App如果需要在鎖屏界面上顯示相關的信息和按鈕, 必須先開啟遠程控制事件(Remote Control Event), 否則鎖屏界面只顯示滑動解鎖.
  2. 實現鎖屏界面信息, 將歌曲的相關信息更新到鎖屏界面上
  3. 實現鎖屏界面的事件處理, 在鎖屏界面和上拉的快速功能菜單中實現播放控制

遠程控制事件的實現

在iOS7.1之前, 遠程控制事件主要涉及以下三個方法:

  • 開始接收遠程控制事件
  • 結束接收遠程控制事件
  • 觸發遠程控制事件后的捕獲處理

官方文檔對這三個方法的描述如下, 這里做了簡單的翻譯.

開始接收遠程控制事件

Declaration
- (void)beginReceivingRemoteControlEvents

讓App開始接收遠程控制事件, 該方法屬於UIApplication類

Discussion

在iOS7.1之后, 使用MPRemoteCommandCenter的共享對象來注冊遠程控制事件. 當使用shared command center時, 不需要再調用該方法.
該方法會開始使用事件響應鏈來傳遞遠程控制事件. 遠程控制事件是當耳機和外部附件意圖控制App的多媒體表現時發出的命令. 要停止遠程控制事件的接收, 必須調用endReceivingRemoteControlEvents方法

結束接收遠程控制事件

Declaration
- (void)endReceivingRemoteControlEvents 

讓App停止接收遠程控制事件, 該方法屬於UIApplication類

Discussion

在iOS7.1之前, 使用shared MPRemoteCommandCenter對象來注冊遠程控制事件. 當使用shared command center時, 不需要再調用該方法. 該方法會停止通過事件響應鏈來傳遞遠程控制事件. 遠程控制事件是當耳機和外部附件意圖控制App的多媒體表現時發出的命令.

遠程控制事件的捕獲處理

Declaration
- (void)remoteControlReceivedWithEvent:(UIEvent *)event

當遠程控制事件發生時觸發該方法, 該方法屬於UIResponder類

Discussion

遠程控制事件是由外部附件(包括耳機)所發出的命令. 應用需要響應這些命令來控制音頻或視頻媒體的對用戶的表示. 事件響應者通過檢查事件的subtype, 來判斷命令的意圖. 比如UIEventSubtypeRemoteControlPlay為播放操作, 然后做相關處理

要允許遠程控制事件的傳遞, 需要調用UIApplication的beginReceivingRemoteControlEvents方法; 要關閉遠程控制事件的傳遞則調用endReceivingRemoteControlEvents

項目中的代碼實現

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 在App啟動后開啟遠程控制事件, 接收來自鎖屏界面和上拉菜單的控制 [application beginReceivingRemoteControlEvents]; return YES; } - (void)applicationWillTerminate:(UIApplication *)application { // 在App要終止前結束接收遠程控制事件, 也可以在需要終止時調用該方法終止 [application endReceivingRemoteControlEvents]; } // 在具體的控制器或其它類中捕獲處理遠程控制事件 - (void)remoteControlReceivedWithEvent:(UIEvent *)event { // 根據事件的子類型(subtype) 來判斷具體的事件類型, 並做出處理 switch (event.subtype) { case UIEventSubtypeRemoteControlPlay: case UIEventSubtypeRemoteControlPause: { // 執行播放或暫停的相關操作 (鎖屏界面和上拉快捷功能菜單處的播放按鈕) break; } case UIEventSubtypeRemoteControlPreviousTrack: { // 執行上一曲的相關操作 (鎖屏界面和上拉快捷功能菜單處的上一曲按鈕) break; } case UIEventSubtypeRemoteControlNextTrack: { // 執行下一曲的相關操作 (鎖屏界面和上拉快捷功能菜單處的下一曲按鈕) break; } case UIEventSubtypeRemoteControlTogglePlayPause: { // 進行播放/暫停的相關操作 (耳機的播放/暫停按鈕) break; } default: break; } }

iOS7.1后, 更新了遠程控制事件的實現方式

相關方法的描述中, 已經說明, iOS7.1之后使用MPRemoteCommandCenter類來進行遠程控制事件的相關處理, 因此可以不再使用上面所描述的三個方法. 官方文檔對MPRemoteCommandCenter的描述如下:

MPRemoteCommandCenter

MPRemoteCommandCenter類提供了處理遠程控制事件的對象, 包括由外部附件和系統傳輸控制發送的遠程控制事件. 不需要自己創建該類的實例. 而是使用shareCommandCenter方法獲取默認的命令中心(share command center)對象. share command center對象的屬性包含了MPRemoteCommand對象(表示iOS支持的每種遠程控件事件). 如果要對響應的事件特殊處理, 使用適當的MPRemoteCommand對象注冊一個handler即可.

遠程命令中心(remote command center)對象為許多不同類型的事件提供了命令(command)對象. 如果你的App不需要支持某些特定類型的事件, 可以通過設置其enabled屬性為NO來禁用關聯的MPRemoteCommand對象. 使用command對象注冊一個handler, 以便讓系統知道你的App已經做好了接收事件的准備. 只有當你的App是當前正在播放(Now Playing App)時才能接收到事件的傳遞.

項目中的代碼實現 :

// 在需要處理遠程控制事件的具體控制器或其它類中實現 - (void)remoteControlEventHandler { // 直接使用sharedCommandCenter來獲取MPRemoteCommandCenter的shared實例 MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; // 啟用播放命令 (鎖屏界面和上拉快捷功能菜單處的播放按鈕觸發的命令) commandCenter.playCommand.enabled = YES; // 為播放命令添加響應事件, 在點擊后觸發 [commandCenter.playCommand addTarget:self action:@selector(playAction:)]; // 播放, 暫停, 上下曲的命令默認都是啟用狀態, 即enabled默認為YES // 為暫停, 上一曲, 下一曲分別添加對應的響應事件 [commandCenter.pauseCommand addTarget:self action:@selector(pauseAction:)]; [commandCenter.previousTrackCommand addTarget:self action:@selector(previousTrackAction:)]; [commandCenter.nextTrackCommand addTarget:self action:@selector(nextTrackAction:)]; // 啟用耳機的播放/暫停命令 (耳機上的播放按鈕觸發的命令) commandCenter.togglePlayPauseCommand.enabled = YES; // 為耳機的按鈕操作添加相關的響應事件 [commandCenter.togglePlayPauseCommand addTarget:self action:@selector(playOrPauseAction:)]; }
效果如圖:

 鎖屏界面-遠程控制

鎖屏界面相關信息更新

實現了遠程控制事件后, App在進行音樂播放時, 上拉快捷功能菜單都會提供遠程控件按鈕, 鎖屏界面會有改動, 出現遠程控制按鈕, 以及歌曲進度等信息, 接下來需要將歌曲的相關信息更新到鎖屏界面上. 主要通過MPNowPlayingInfoCenter類來實現, 下面是官方文檔的描述:

MPNowPlayingInfoCenter

使用now playing info center來設置App當前正在播放的媒體文件的信息(now-playing information).

系統會在設備的鎖屏界面和上划的快捷控制面板的多媒體控制部分顯示當前播放文件的信息. 如果用戶直接通過AirPlay在Apple TV上播放媒體文件時, now-playing信息會顯示在電視屏幕上. 如果用戶將設備連接到iPad附件, 比如汽車(通過CarPlay連接)上, 附件上可能會顯示now-playing的信息.

你不能直接控制哪些信息要被顯示出來, 以及這些信息顯示的樣式. 只需要設置now playing info center dictionary的相關value, 將這些相關信息提交給系統即可. 系統或已經連接的附件, 會用一致的方式為所有的App處理這些信息的展示.

可以配置的鎖屏界面信息

可以使用的information屬性, 是定義在MPMediaItem類的General Media Item Property Keys屬性中的子集(即其中的某些屬性). 在iOS5.0后, now playing info center支持下列media item屬性的Key: (僅列舉了常用的Key!)

  • MPMediaItemPropertyAlbumTitle 專輯的標題, value是NSString對象
  • MPMediaItemPropertyArtist media item的創作者, value是NSString對象
  • MPMediaItemPropertyArtwork media item的插圖. value是MPMediaItemArtwork類的對象
  • MPMediaItemPropertyPlaybackDuration media item的播放總時長. value是表示包裝了時長秒數(NSTimeInterval)的NSNumber類型
  • MPMediaItemPropertyTitle media item的名字或標題. 該屬性與MPMediaItemPropertyAlbumTitle屬性無關, value是NSString對象

額外添加的一些可以使用的屬性在MPNowPlayingInfoCenter類的描述文檔中的Additional Metadata Properties中作了聲明. (僅列舉了常用的Key!)

  • MPNowPlayingInfoPropertyElapsedPlaybackTime 當前播放的item所消逝的時間(歌曲當前時間), 單位為秒. value是包裝了double值的NSNumber對象. elapsed time是由系統根據之前提供elapsed tiime和playback rate進行自動進行計算的. 請不要頻繁的更新該屬性, 這是沒有必要的.
  • MPNowPlayingInfoPropertyPlaybackRate 當前播放的item的播放速率, value為1.0表示正常的播放速率. value是包裝了double值的NSNumber對象. 默認值是1.0. playback rate的值為2.0表示普通播放速率的2倍; 此時media從播放到結束只需要一半時間.

項目中的代碼實現

- (void)updatelockScreenInfo { // 直接使用defaultCenter來獲取MPNowPlayingInfoCenter的默認唯一實例 MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter]; // MPMediaItemArtwork 用來表示鎖屏界面圖片的類型 MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image]; // 通過配置nowPlayingInfo的值來更新鎖屏界面的信息 infoCenter.nowPlayingInfo = @{ // 歌曲名 MPMediaItemPropertyTitle : music.name, // 藝術家名 MPMediaItemPropertyArtist : music.singer, // 專輯名字 MPMediaItemPropertyAlbumTitle : music.album, // 歌曲總時長 MPMediaItemPropertyPlaybackDuration : @(duration), // 歌曲的當前時間 MPNowPlayingInfoPropertyElapsedPlaybackTime : @(currentTime), // 歌曲的插圖, 類型是MPMeidaItemArtwork對象 MPMediaItemPropertyArtwork : artwork, // 無效的, 歌詞的展示是通過圖片繪制完成的, 即將歌詞繪制到歌曲插圖, 通過更新插圖來實現歌詞的更新的 // MPMediaItemPropertyLyrics : lyric.content, }; }
效果如圖:

 鎖屏界面-信息展示

類似網易新聞的鎖屏控制按鈕實現

通過上述代碼實現后, 鎖屏界面已經可以展示出歌曲信息與控制按鈕, 通過按鈕或耳機的按鍵也可以實現相關的控制效果. 但網易的控制按鈕中最左邊並是上一曲, 而是列表按鈕, 點擊后還能在鎖屏界面彈出一個ActionSheet界面. 該功能其實是通過修改MPRemoteCommandCenter的反饋功能(提供喜歡, 不喜歡, 標記(bookmark)操作)來實現的.

涉及到的反饋功能, 先了解MPFeedbackCommond這個類, 以下是文檔的描述

MPFeedbackCommond

MPFeedbackCommand對象反映了當前App所播放的反饋狀態. MPRemoteCommandCenter對象提供feedback對象用於對媒體文件進行喜歡, 不喜歡, 標記的操作. 使用這些對象為App支持的回饋(feedback)方式進行注冊handler, 並在反饋狀態修改時執行適當的任務(task). 在當前播放的item改變時, 也可以使用該對象為新的item設置反饋狀態.

當item的反饋狀態改變時, 系統傳遞適當的事件到該對象注冊的handler上. handler的代碼必須決定哪一個media item來接收反饋, 然后再為該item執行更新反饋狀態的操作. 你也可以執行與接收到反饋相關的其它任務. 比如, 當用戶喜歡當前播放的歌曲時你可能要在UI上做出適當調整, 並使用該信息來進行相關歌曲的推薦.

MPRemoteCommandCenterr提供了相關屬性(反饋按鈕)

@property (nonatomic, readonly) MPFeedbackCommand *likeCommand; // 喜歡命令 @property (nonatomic, readonly) MPFeedbackCommand *dislikeCommand; // 不喜歡命令 @property (nonatomic, readonly) MPFeedbackCommand *bookmarkCommand; // 標記(書簽)命令

事實上, 系統的鎖屏界面並不支持自定義. 這里邊只需要添加反饋按鈕, 則系統默認的鎖屏界面就是網易雲音樂所展示的樣式. 包括點擊后彈出的ActionSheet都是系統針對反饋按鈕所提供了, 網易雲音樂只是巧妙的將"不喜歡"按鈕的標題修改成"上一曲", 並在該按鈕的響應事件里實現上一曲的代碼, 即完成相關功能.

項目中的代碼實現

// 添加"喜歡"按鈕, 需要啟用, 並且設置了相關Action后才會生效 [MPRemoteCommandCenter sharedCommandCenter].likeCommand.enabled = YES; [[MPRemoteCommandCenter sharedCommandCenter].likeCommand addTarget:self action:@selector(likeItemAction)]; [MPRemoteCommandCenter sharedCommandCenter].likeCommand.localizedTitle = @"喜歡"; // 添加"不喜歡"按鈕 [MPRemoteCommandCenter sharedCommandCenter].dislikeCommand.enabled = YES; // 自定義該按鈕的響應事件, 實現在點擊"不喜歡"時去執行上一首的功能 [[MPRemoteCommandCenter sharedCommandCenter].dislikeCommand addTarget:self action:@selector(previousCommandAction)]; [MPRemoteCommandCenter // 自定義"不喜歡"的標題, 偽裝成"上一首" sharedCommandCenter].dislikeCommand.localizedTitle = @"上一首";

注意: 反饋按鈕默認不啟用, 因此需要將enabled設置為YES, 同時必須添加對應的響應事件, 按鈕才會在鎖屏界面顯示.

完成效果:

 鎖屏界面

 鎖屏界面

 上拉快速功能菜單

 上拉快速功能菜單-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM