來張簡單的效果圖:
scale.gif
問題引出
半年前開始接觸Android清單播放短視訊開發是從 VideoPlayerManager 這裡開始的。
該庫核心思路:
1.使用TextureView嵌套在Item View裡面作為視訊渲染
2.将視訊的生命周期全部在子線程隊列執行,然後post到主線程,避免ANR以及周期混亂
對此在Medium上作者做出了解釋
但存在一個棘手的問題:
由于TextureView是在ItemView中,所有壓根就不能無痕全屏切換播放
但是對于國内的視訊播放app來說,敢問哪家不要求全屏播放?
于是想出了一個方案就是在ListView或者RecyclerView布局同等層級中加入視訊播放的布局,将播放布局依附在itemView的顯示區域,然後監聽ListView或RecyclerView的滾動,通過滾動的位置來動态移動視訊播放布局的位置,這樣在全屏隻需要将出了ListView或RecyclerView外的其他布局全部隐藏,将視訊播放的播放Resize到螢幕的寬高。大緻的代碼可以在
ListViewFragment這裡看到.
BTW:就我所看到的,敢打賭目前市面上大部分的所謂的清單播放視訊思路大緻如此
上述雖然能實作功能,但是在維護上存在極大的問題,無論是ListView或RecyclerView各種詭異滾動問題以及ViewPager相關的滾動問題, 還是每次建立一個頁面都要将視訊所有的布局寫死在xml檔案中。完全無任何擴充性可言。并且當需要在點選視訊時進入詳情頁? 落地頁 ?做無痕,不斷播的互動簡直是天方夜譚。
既然思路沒問題,那就着手優化重構了。其實隻要找到問題的關鍵點:
視訊布局真的就必須固定在某個頁面布局中?
2.視訊布局每次滾動都會有一個可依附的View(粘在上面,看着就像内嵌在清單裡面一樣),必須要監聽ListView,ViewPager的滾動?
3.視訊布局無論是橫豎屏或者進入詳情頁的視訊布局應該都必須是同一個才能保證無痕播放
橫豎屏保證是同一個尚好處理,但是當需要切換界面的時怎樣保證是同一個?
解決方案
一個Activity擁有一個頂層的View 即:
(ViewGroup) mContext.getWindow().getDecorView()
該decorView能保證随時随地都能附在activity的最頂層,将視訊播放相關的所有布局都置于其中就能解決問題1和3 存在的問題
但當将布局Add到DecorView後,會導緻任何時候視訊布局都會在頂層,會遮擋StatusBar,ActionBar或者其他滾動清單之外的布局,此時就需要将視訊的播放布局嵌套在一個FrameLayout 中,如 VideoLayerView.java#L47,當視訊整體的布局是在滾動此FrameLayout , 當在非合理範圍内就滾動真正的視訊布局,
這樣就完美的将視訊播放的布局 Attach在了清單item上跟随滾動了
Android在ViewTreeObserver中添加了每個View,改View的相關變化都會在ViewTreeObserver回調,比如說: mTrackView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
//View滾動時會回調
}
});
mTrackView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//重新layout會被回調
}
});複制代碼
在此隻需要關心ViewTreeObserver.OnScrollChangedListener即可,這樣就根本不用關心ListView,RecyclerView,ViewPager的滾動距離來改變視訊布局的位置了,具體代碼可在ViewTracker.java#L202 檢視到
是以根據上述思路簡單設計出了 一個View 粘附到 另一個View上 且跟随滾動的架構
詳情見 ViewTracker
放張效果圖:
bullheadN4F26Tbrucetoo04112017181910.gif
隻要将跟随滾動的邏輯處理ok,視訊播放相關的可以将播放布局參照demo來進行整合就能實作無縫播放 like below:
bullheadN4F26Tbrucetoo04112017181817.gif