iOS畫中畫Picture in Picture:你需要知道的9個知識點

      iOS9最後給我們帶來了每個人期待已久的”多任務”,Slider Over、Split View 和畫中畫(PiP),已經使iPad成爲一個比之前更強大、更便利的工具。使你在工作中需要在屏幕上同時做多個事情的時候增加工作效率,這在商務辦公中將會備受歡迎。相比於轉換爲後臺或者四指切換APP,用戶能夠更加集中注意力於更加重要的事情上。並且現在由於蘋果對視頻app更加優雅的處理方式,當你需要回復朋友的email或者瀏覽其他模塊的時候,你不必暫停你喜愛的電視劇。同樣,在iOS9上,當我們用Facebook上與其他人談話的時候,還可以在網上搜索其他東西。
     所有的這些多任務特性都是非常棒的,並且畫中畫功能使iPad在蘋果的其他產品中更加突出。比如在Mac上,我們把視頻縮小放到一個屏幕的邊角,而當我們有一些其他的窗口打開的時候,我們同樣會擔心視頻是否會被其他的窗口覆蓋,並且不得不重新調整窗口的層級。在我看來,Pipe如果加到了OSX上回更加nice,但是我們不得不把這個留給蘋果去決定。

     如果你問自己是否真的需要把畫中畫功能添加到你的iOSapp中的話,回答是絕對的要假如。這個特性對於每一個媒體app將會是必須的。並且沒有它你將會流失你的客戶。並且將他假如到你的app中,並不會造成太多的影響,繼續往下看你將會發現


 Picture in Picture Q & A

(官方demo)


1.怎麼使其起作用

首先畫中畫(Picture in Picture)功能只有在iPad中才能使用。一旦你點擊你的app中的工具欄中的PiP按鈕,將會進入畫中畫模式,視頻將會展示在一個漂浮在其他所有你打開的app的上方的窗口中。

PiP的窗口能被調整大小並且能夠拖拽到屏幕的四個角,他同樣能夠被從屏幕上移除,點擊PiP的窗口,將會展示控制面板,你可以暫停或開始視頻,或者離開畫中畫模式或者你可以將畫中畫窗口捲起來。


2.如果我的app正在畫中畫模式中播放,而用戶播放了其他的視頻/音頻,將會發生什麼

這個不需要擔心,你的畫中畫將會自動暫停,同樣,如果用戶想要重複播放你的視頻,其他的視頻或音頻也會被暫停


3.用戶可以禁止掉畫中畫功能嗎?

當然,可以在設置>>通用>>多任務>>持續視頻層疊 中將其關閉。所以當你測試畫中畫的時候,也要確定這個功能沒有被關閉


4.我怎麼能夠在我的app實現畫中畫功能

如果你播放你的視頻用AVPlayerViewController類,將會非常的簡單。畫中畫按鈕已經被放置好並且系統能夠自動的處理好畫中畫模式和全屏模式。同樣你的視頻內容播放在WKWebView同樣可以展示在畫中畫模式中。然而如果你想實現你自己定製的播放器中,你可能就要多做些工作了,你需要在庫AVKit中實例化一個 AVPictureInPictureController類,你能夠關聯上 AVPlayerLayer實例。在任何情況下,你都需要爲你的APP後臺畫中畫模式做一些合理的配置

1.在工程中的Build settings 中,設置Base SDK爲“Latest iOS.”


2.到工程的Target,在Capabilities中選擇  Background Modes 爲  Audio and AirPlay.



3.你的app播放任務需要設置爲AVAudioSessionCategoryPlayback 或者AVAudioSessionCategoryPlayAndRecord
舉個例子:

在蘋果開發文檔中的demo中在AppDelegate.swift 中


let audioSession = AVAudioSession.sharedInstance()

		do {
			try audioSession.setCategory(AVAudioSessionCategoryPlayback)
		}
		catch {
			print("Audio session setCategory failed")
		}


5.當我在用一個自定義的播放器的時候,怎麼處理到畫中畫模式的過渡?

第一步就是確保你的app能夠支持畫中畫模式(看上文),並且視頻內容能夠全屏播放
由於你沒有用AVPlayerViewController,所以你需要創建一個button去選擇到畫中畫模式。然而你還要去檢查這種模式在用戶的iPad上是否支持。AVPictureInPictureController類提供這種檢測,所以你只能在AVPictureInPictureController.isPictureInPictureSupported()這個方法返回值是true的時候才能在app中用畫中畫模式。
事實上,AVPictureInPictureController纔是真正能夠初始化和退出畫中畫模式的類

通過的方法:

stopPictureInPicture()
startPictureInPicture()



它能夠給你提供一些當前畫中畫的狀態,例如:
pictureInPicturePossible——告訴你畫中畫窗口是可用的。如果其他的app再使用PiP模式,他將會返回false。這個實行也能夠通過KVO來觀察,同樣通過觀察這種狀態的改變,你也能夠很好地額處理PiP按鈕的的隱藏於展示。
pictureInPictureActive——表示PiP窗口當前時間是否在屏幕上
pictureInPictureSuspended——如果你的app因爲其他的app在使用PiP而導致你的視頻後臺播放播放狀態爲暫停並且不可見,將會返回true。當其他的app離開了PiP時,你的視頻會被重新播放

AVPictureInPictureController的初始化通過將要展示視頻的視圖的view的 AVPlayerLayer來初始化。爲了達到這種目的視頻播放的視圖的layer返回應該是AVPlayerLayer。


var player: AVPlayer? {
		get {
			return playerLayer.player
		}
		
		set {
			playerLayer.player = newValue
		}
	}
	
	var playerLayer: AVPlayerLayer {
		return layer as! AVPlayerLayer
	}
	
	override class func layerClass() -> AnyClass {
		return AVPlayerLayer.self
	}

 

 下面是當你的視頻內容已經準備好展示的時候PiP是如何設置的:

private func setupPictureInPicturePlayback() {
 
		if AVPictureInPictureController.isPictureInPictureSupported() {
 
			pictureInPictureController = AVPictureInPictureController(playerLayer: playerView.playerLayer)
			pictureInPictureController.delegate = self
			
			addObserver(self, forKeyPath: "pictureInPictureController.pictureInPicturePossible", options: [.New, .Initial], context: &playerViewControllerKVOContext)
		}
		else {
			pictureInPictureButton.enabled = false
		}
}


注意在這個例子中,包含了視頻播放器的視圖控制器遵守AVPictureInPictureControllerDelegate協議。這個協議裏面定義了你可以響應PiP播放事件的方法,包含了:
pictureInPictureController(_:restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:)
pictureInPictureControllerDidStartPictureInPicture(_:)
pictureInPictureControllerDidStopPictureInPicture(_:)
pictureInPictureControllerWillStartPictureInPicture(_:)
pictureInPictureControllerWillStopPictureInPicture(_:)
pictureInPictureControllerFailedToStartPictureInPicture(_:withError:)


下面的這些代碼是根據pictureInPicturePossible這個屬性來控制PiP按鈕的狀態(可用於不可用):
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [NSObject : AnyObject]?, context: UnsafeMutablePointer<Void>) {
 
…
 
            if keyPath == "pictureInPictureController.pictureInPicturePossible" {
			let newValue = change?[NSKeyValueChangeNewKey] as! NSNumber
			let isPictureInPicturePossible: Bool = newValue.boolValue
			pictureInPictureButton.enabled = isPictureInPicturePossible
		}
}



最後,如果用戶點擊了PiP按鈕,AVPictureInPictureController將會重新初始化或者停止PIP模式
@IBAction func togglePictureInPictureMode(sender: UIButton) {
		if pictureInPictureController.pictureInPictureActive {
			pictureInPictureController.stopPictureInPicture()
		}
		else {
			pictureInPictureController.startPictureInPicture()
		}
}


6.我可以關閉掉PiP功能嗎?

當然!你所需要做的就是設置實例AVPlayerViewController 或者 WKWebView的屬性  allowsPictureInPictureMediaPlayback爲NO就行了。


7.我可以寫AVPictureInPictureController的子類嗎?

儘管寫一個子類將會是很大的誘惑,但是確實不建議的。Apple警告道: “overriding this class’s methods is unsupported and results in undefined behavior.” 重寫這個類的方法是不支持的,並且會造成意想不到的後果。同樣,也可能會造成在你的app會被審覈部門拒絕。


8.有什麼方法可以在PiP窗口中設置主題嗎或者改變扁標準的控制,或者添加更多的控制?

就現在來說,官方的AVKit框架文檔並沒有談到任何的對於開發者來說的接口。所以有點輕微的失望,我們希望在下一個iOS版本中Apple將會給我們更多的自由設計。


9.關於使用畫中畫有更好的建議嗎?

基本上同樣的建議就是當你的app使用了畫中畫模式之後,你要及時的釋放一些後臺的資源,因爲這可能會造成你的app被系統殺掉,所以當你的app轉換到PIP模式的時候需要釋放掉不用的資源

序:如有需要 iOS demo的可以聯繫



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章