You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中VideoView播放前出现黑屏闪烁问题求助

引导视频播放前黑屏闪烁问题解决方案

问题场景

应用启动引导页包含视频引导内容,但视频播放前会出现短暂黑屏闪烁,常规方案无法解决,相关代码如下:

Java代码

@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = layoutInflater.inflate(R.layout.slider_layout, container, false);

    ImageView slideImageView = view.findViewById(R.id.imageView);
    VideoView slideVideoView = view.findViewById(R.id.videoView);
    TextView slideHeading = view.findViewById(R.id.textTitle);
    TextView slideDescription = view.findViewById(R.id.textDescription);

    MediaItem item = mediaItems[position];

    if (item.getType() == MediaItem.MediaType.IMAGE) {
        slideImageView.setImageResource(item.getResourceId());
        slideImageView.setVisibility(View.VISIBLE);
        slideVideoView.setVisibility(View.GONE);
    } else if (item.getType() == MediaItem.MediaType.VIDEO) {
        slideImageView.setVisibility(View.GONE);
        slideVideoView.setVisibility(View.VISIBLE);


        // Set the video URI using the resource ID
        Uri videoUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + item.getResourceId());
        slideVideoView.setVideoURI(videoUri);

        // Start video playback when it's ready
        slideVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                slideVideoView.start();
            }
        });
    }

    slideHeading.setText(headings[position]);
    slideDescription.setText(descriptions[position]);

    container.addView(view);
    return view;
}

XML布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/background_color"
android:padding="16dp">

<SurfaceView
    android:layout_width="0px"
    android:layout_height="0px"
    android:visibility="gone" />

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="100dp">

<VideoView
    android:id="@+id/videoView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center_horizontal" />

</FrameLayout>


<ImageView
    android:id="@+id/imageView"
    android:layout_width="wrap_content"
    android:layout_height="210dp"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="100dp"
    android:src="@drawable/baseline_image_24" />

<TextView
    android:id="@+id/textTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:textSize="24sp"
    android:textColor="@android:color/white"
    android:textAlignment="center"
    android:paddingTop="16dp"
    android:text="@string/heading_1" />

<TextView
    android:id="@+id/textDescription"
    android:textAlignment="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:textSize="16sp"
    android:textColor="@android:color/white"
    android:paddingTop="8dp"
    android:text="@string/description_1" />
</LinearLayout>

解决方案

方案1:用视频第一帧做占位图

在视频准备完成前,显示视频第一帧作为临时占位,避免黑屏:

  1. 提前提取视频第一帧保存为drawable资源(如@drawable/video_guide_thumbnail)
  2. 修改视频类型处理代码:
else if (item.getType() == MediaItem.MediaType.VIDEO) {
    // 先显示占位图
    slideImageView.setImageResource(R.drawable.video_guide_thumbnail);
    slideImageView.setVisibility(View.VISIBLE);
    slideVideoView.setVisibility(View.INVISIBLE);

    Uri videoUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + item.getResourceId());
    slideVideoView.setVideoURI(videoUri);

    slideVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            // 视频准备好后切换显示
            slideImageView.setVisibility(View.GONE);
            slideVideoView.setVisibility(View.VISIBLE);
            slideVideoView.start();
            // 开启屏幕常亮,避免渲染延迟
            mp.setScreenOnWhilePlaying(true);
        }
    });

    // 监听视频开始渲染事件,确保完全加载后再显示
    slideVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
                slideVideoView.setVisibility(View.VISIBLE);
                return true;
            }
            return false;
        }
    });
}

方案2:统一布局背景与尺寸

  1. 给VideoView设置和页面一致的背景色,避免加载时显示默认黑色:
<VideoView
    android:id="@+id/videoView"
    android:layout_width="match_parent"
    android:layout_height="210dp"
    android:layout_gravity="center"
    android:background="@color/background_color" />
  1. 调整FrameLayout尺寸和ImageView一致,避免布局重绘闪烁:
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="210dp"
    android:layout_marginTop="100dp"
    android:background="@color/background_color">

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:background="@color/background_color" />
</FrameLayout>

方案3:替换为ExoPlayer

VideoView的底层兼容性问题较多,改用ExoPlayer可更好控制播放流程:

  1. 添加依赖(替换为最新版本号):
implementation "com.google.android.exoplayer:exoplayer-core:2.19.1"
implementation "com.google.android.exoplayer:exoplayer-ui:2.19.1"
  1. 替换布局中的VideoView为PlayerView:
<com.google.android.exoplayer2.ui.PlayerView
    android:id="@+id/playerView"
    android:layout_width="match_parent"
    android:layout_height="210dp"
    android:layout_marginTop="100dp"
    android:background="@color/background_color" />
  1. 修改Java代码实现播放:
else if (item.getType() == MediaItem.MediaType.VIDEO) {
    slideImageView.setVisibility(View.GONE);
    PlayerView playerView = view.findViewById(R.id.playerView);
    playerView.setVisibility(View.VISIBLE);

    // 初始化ExoPlayer
    SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
    playerView.setPlayer(player);

    // 设置视频源
    Uri videoUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + item.getResourceId());
    com.google.android.exoplayer2.MediaItem mediaItem = com.google.android.exoplayer2.MediaItem.fromUri(videoUri);
    player.setMediaItem(mediaItem);

    // 设置占位图
    playerView.setDefaultArtwork(BitmapFactory.decodeResource(context.getResources(), R.drawable.video_guide_thumbnail));

    // 准备并播放
    player.prepare();
    player.setPlayWhenReady(true);

    // 页面销毁时释放资源(需在instantiateItem对应的destroyItem中处理)
    player.addListener(new Player.Listener() {
        @Override
        public void onPlaybackStateChanged(int playbackState) {
            if (playbackState == Player.STATE_ENDED) {
                // 处理播放完成逻辑
            }
        }
    });
}

内容的提问来源于stack exchange,提问作者AKD2022

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 00:27:33