ANDROID視頻引導滑動黑屏掃雷以及解決方案

首發自: ANDROID視頻引導滑動黑屏掃雷以及解決方案

前一段時間,公司項目需要做一個視頻引導的功能,剛開始以為用個 ViewPager+Fragment+VideoView 不就實現了嗎,很快就弄好了。不過后來測試發現在滑動切換頁面時會出現黑屏,比較影響用戶體驗,然后在網上找了各種“可行”的方案,都未能完全解決,最后嘗試了一種巧妙的方法才解決這個問題。

首先說明下,這里視頻引導用到的技術點是 ViewPager+Fragment+VideoView(當然也使用過 SurfaceView 來實現,不過原理基本一致),產品提供四個單獨的視頻(不是一個視頻)+ 引導的圓點和進入主頁的按鈕(不是直接添加在視頻上的)。另外限制條件是,產品未提供每個視頻的第一幀的圖片

解決滑動切換頁面黑屏的問題

出現黑屏的解釋:videoview加載資源需要一定的耗時,無內容時會繪制黑色背景。

1.用遮罩方式掩蓋黑屏

用第一幀的圖片作為 videoview 的遮罩,當視頻加載好,再隱藏掉這個遮罩。以下例子并不能完全解決黑屏:

2.用PageTransformer設置滑動時切換的動畫

當頁面比較多時,快速滑動切換,ViewPager 會閃一下,可以添加切換動畫作為緩沖。
了解自定義 PageTransformer 動畫可以看下這個庫: GitHub - ToxicBakery/ViewPagerTransforms: Library containing common animations needed for transforming ViewPager scrolling for Android v13+.

3.在每個 page 頁增加一個寬高都為0的 SurfaceView

無效

4.入坑:使用videoView.setZOrderOnTop(true)避免黑屏

在視頻加載前設置一張圖片作為過渡圖片,之后調用videoView.setZOrderOnTop(true),確實可以解決滑動黑屏問題,不過調用了該方法,會使其他控件被 VideoView 覆蓋。前面的幾種方案由于條件限制效果都不是很好,這種方法基本看不到黑屏,但卻出現了另一個問題:如何將圓點和按鈕置于 VideoView 上面?

解決調用videoView.setZOrderOnTop(true),其他控件被覆蓋的問題

由于 VideoView 是繼承 SurfaceView 的,也查了相關解決方案,遇到不少坑

坑1:

解決SurfaceView調用setZOrderOnTop(true)遮擋其他控件的問題

調用setZOrderOnTop(true)之后調用了setZOrderMediaOverlay(true)再設置控件顯示,解決遮擋問題,但是又出現了黑屏問題,也就是說調用setZOrderMediaOverlay(true)會使前面設置的setZOrderOnTop(true)失效

坑2:

解決SurfaceView設置透明造成覆蓋其他組件的替代方案 - jwzhangjie的專欄CSDN.NET
里面提到的兩種在 SurfaceView設置了setZOrderOnTop(true)后,添加其他組件的方法:使用 PopupWindow 作為容器承載其他控件,考慮到setZOrderOnTop(true)能覆蓋其他控件,所以也嘗試了用SurfaceView 繪制圓點和按鈕(在 videoview調用setZOrderOnTop(true) 后調用自身的setZOrderOnTop(true)覆蓋在上面)。在我的實踐中,
a.用 PopupWindow 作為容器,大部分手機可以使圓點和按鈕置于上面,但小米手機第一屏不行,home 鍵后也會圓點也會被覆蓋掉;
b.用 SurfaceView 作為容器小米手機正常了,其他手機異常,圓點和按鈕不能顯示在 VideoView 上面。。。

以上兩種方法部分手機異常都找不到具體原因。

解決方案

最終使用了Dialog 作為圓點和按鈕的容器才解決控件被覆蓋的問題。不過 Dialog 會使 ViewPager 的滑動失效,需要重寫 Dialog 的 onTouch 事件,將 TouchEvent 傳遞給 ViewPager 處理,同時要設置Dialog.setCancelable(false); 避免按返回鍵,對話框消失掉。
不完整代碼如下:

public class ContainerDialog extends Dialog {
    private OnTouchOutsideListener onTouchOutsideListener;

    public ContainerDialog(Context context, int theme) {
        super(context, theme);
    }

    public void setOnTouchOutsideListener(OnTouchOutsideListener onTouchOutsideListener){
        this.onTouchOutsideListener = onTouchOutsideListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(onTouchOutsideListener!=null){
            return onTouchOutsideListener.onTouchOutside(event);
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void show() {
        super.show();
        Window window = this.getWindow();
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        window.setGravity(Gravity.BOTTOM);
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(layoutParams);
        window.setBackgroundDrawableResource(android.R.color.transparent);
    }

    public interface OnTouchOutsideListener{
        boolean onTouchOutside(MotionEvent event);
    }
}

對話框主題

<style name="FeatureDialogTheme" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>

使用方法

        //……
        ContainerDialog mDialog = new ContainerDialog(this, R.style.FeatureDialogTheme);
        mDialog.setContentView(dotsAndBtnView);
        mDialog.setCancelable(false);
        mDialog.setOnTouchOutsideListener(new ContainerDialog.OnTouchOutsideListener() {
            @Override
            public boolean onTouchOutside(MotionEvent event) {
                mViewPager.onTouchEvent(event);
                return true;
            }
        });
        mDialog.show();

在調用 VideoView.start()前加以下兩行代碼避免黑屏

mVideoView.setZOrderOnTop(true);   
mVideoView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

其他代碼略

注:以上是針對公司項目有限的條件下的測試結果,并不保證其他項目也一樣(代碼調用位置和使用方法不同,可能效果不一樣),只是提供一些方案和想法。

另外,未嘗試的方法:
1.只用一個 VideoView,切換 ViewPager 只是變化圓點和 VideoView 的 url,避免切換 VideoView 的黑屏;參照 仿蝦米音樂引導頁面 - Kevin Blog CSDN.NET
2.使用視頻縮略圖解決視頻黑屏,參照 Android之ViewPager+VideoView引導界面 - 博客頻道 - CSDN.NET

獲取視頻縮略圖
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(this, mUri);
mImageView.setImageBitmap(mmr.getFrameAtTime());
添加ViewPager 滑動監聽
ViewPager.addOnPageChangeListener,
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
在這個函數里處理縮略圖的顯示
public void onPageScrollStateChanged(int state) state==0 時視圖準備好了
在這個函數里處理縮略圖的消失

—EOF—


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容