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阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容