add videoview黑屏一下

本文介绍了一种解决在动态添加SurfaceView时出现短暂黑屏现象的方法。通过调整Activity中窗口和SurfaceView的格式设置,成功避免了黑屏问题的发生。

Add SurfaceView flash a black screen(动态添加SurfaceView导致黑一下屏)


最近工作需要,需要将一个VideoView动态添加到一个View上,但是出现了问题,第一次添加VideoView的时候,总是会全屏闪一下黑屏。搜了所有地方,都没有合适的解答。查看了一下VideoView的源代码,发现这个类从SurfaceView继承而来。为了排除和Video播放有关,我将一个最简单的SurfaceView动态添加到一个View上。发现还是会闪一下黑屏,这下就排除了和video的关系。

为了查这个问题,只好开启WindowManagerService的debug模式,查看log,发现window的格式和SurfaceView的格式不一样,被销毁重建了。于是我在activity onCreate方法里面,设置window和SurfaceView的格式,解决了这个问题,代码如下:

getWindow().setFormat(PixelFormat.TRANSLUCENT);

<think>我们正在解决Android VideoView播放视频前短暂黑屏的问题。根据引用[1][2][3]提供的信息,黑屏的原因是视频加载和渲染需要时间。解决方案主要是通过使用封面图遮挡黑屏,并在视频开始渲染时隐藏封面图。以下是具体步骤: ### 解决方案 #### 方法一:使用封面图(ImageView)覆盖VideoView 1. **布局设置**:在FrameLayout中同时放置VideoView和ImageView,ImageView位于VideoView上方作为封面。 2. **监听视频准备状态**:当视频开始渲染第一帧时,隐藏ImageView。 3. **注意**:确保在视频渲染第一帧时才隐藏封面,避免提前隐藏导致黑屏。 #### 代码实现(Kotlin/Java) 以下是一个完整的示例(使用Kotlin,同时提供Java关键代码): **布局文件(activity_video.xml)**: ```xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/coverImage" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/video_cover" <!-- 设置封面图片 --> android:scaleType="centerCrop"/> </FrameLayout> ``` **Activity代码(Kotlin)**: ```kotlin class VideoActivity : AppCompatActivity() { private lateinit var videoView: VideoView private lateinit var coverImage: ImageView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_video) videoView = findViewById(R.id.videoView) coverImage = findViewById(R.id.coverImage) // 设置视频路径(这里使用本地资源) val videoUri = Uri.parse("android.resource://${packageName}/${R.raw.video_file}") videoView.setVideoURI(videoUri) // 设置准备监听器 videoView.setOnPreparedListener { mp -> mp.setOnInfoListener { _, what, _ -> if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) { // 视频开始渲染第一帧,隐藏封面 coverImage.visibility = View.GONE return@setOnInfoListener true } false } } videoView.start() } } ``` **Java版本关键代码**: ```java videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.setOnInfoListener(new MediaPlayer.OnInfoListener() { @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) { // 隐藏封面 coverImage.setVisibility(View.GONE); return true; } return false; } }); } }); ``` #### 方法二:设置VideoView的背景(简单方案) 如果黑屏时间极短,也可以尝试设置VideoView的背景为一张图片(与封面相同),在视频开始播放后背景会被视频覆盖。但此方法可能不够彻底,因为背景图可能不会立即消失。 ```xml <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/video_cover"/> ``` ```kotlin videoView.setOnPreparedListener { mp -> // 视频准备完成后移除背景(在开始渲染时移除更合适,但这里简单在准备完成就移除) videoView.setBackgroundResource(0) mp.start() } ``` ### 关键点说明 1. **事件监听顺序**: - `setOnPreparedListener`:当媒体文件加载完成,可以播放时触发。 - `setOnInfoListener`:在媒体播放过程中提供信息事件,其中`MEDIA_INFO_VIDEO_RENDERING_START`(3)表示视频开始渲染第一帧[^3]。 2. **封面图隐藏时机**: - 必须在视频渲染第一帧时才隐藏封面图,否则可能仍会看到黑屏。 3. **封面图资源**: - 使用与视频内容相关的图片作为封面,提升用户体验。 ### 相关问题 1. 如何实现视频播放器的缓冲进度显示?[^1] 2. VideoView如何实现全屏播放功能?[^2] 3. 如何处理VideoView播放网络视频时的加载问题?[^3] 4. 如何为VideoView添加自定义控制条?[^2] 5. 如何实现视频播放失败后的重试机制?[^1] 通过以上方法,可以有效解决VideoView播放视频前的短暂黑屏问题。核心思路是使用封面图遮挡,并在视频开始渲染时隐藏封面。</think>### Android VideoView 播放视频前短暂黑屏解决方案 在 Android 中使用 VideoView 播放视频时出现短暂黑屏是常见问题,主要原因是视频加载和渲染需要时间。以下是四种有效的解决方案: --- #### 方法一:封面图遮挡法(推荐⭐️) 这是最常用且效果最好的解决方案,通过 FrameLayout 叠加 ImageView 和 VideoView: 1. **布局文件 (activity_video.xml)**: ```xml <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 视频播放器 --> <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent"/> <!-- 封面图(覆盖在VideoView上方) --> <ImageView android:id="@+id/coverImage" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/video_cover" <!-- 设置封面图片 --> android:scaleType="centerCrop"/> </FrameLayout> ``` 2. **Activity 代码**: ```java public class VideoActivity extends AppCompatActivity { private VideoView mVideoView; private ImageView mCoverImage; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video); mVideoView = findViewById(R.id.videoView); mCoverImage = findViewById(R.id.coverImage); // 设置视频源(本地资源) Uri videoUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.video); mVideoView.setVideoURI(videoUri); // 监听视频准备状态 mVideoView.setOnPreparedListener(mp -> { mp.setOnInfoListener((mp1, what, extra) -> { if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) { // 视频开始渲染第一帧时隐藏封面 mCoverImage.setVisibility(View.GONE); return true; } return false; }); }); mVideoView.start(); } } ``` **关键点**: - 封面图完全覆盖 VideoView - 使用 `MEDIA_INFO_VIDEO_RENDERING_START` 事件判断第一帧渲染完成 - 封面图隐藏后,用户看到的是视频内容而非黑屏[^2] --- #### 方法二:设置透明背景法 通过修改背景色解决黑屏问题: ```java mVideoView.setOnPreparedListener(mp -> { // 设置透明背景 mVideoView.setBackgroundColor(Color.TRANSPARENT); mp.setOnInfoListener((mp1, what, extra) -> { if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) { // 可在此添加其他逻辑 return true; } return false; }); }); ``` **优点**:简单直接,无需额外视图 **局限**:部分设备可能仍有短暂黑屏[^3] --- #### 方法三:预加载缓冲法 提前缓冲视频减少黑屏时间: ```java // 提前初始化VideoView(在onCreate中) mVideoView = findViewById(R.id.videoView); // 在合适的时机预加载(如Activity可见时) @Override protected void onStart() { super.onStart(); Uri videoUri = ...; mVideoView.setVideoURI(videoUri); mVideoView.seekTo(1); // 预加载第一帧(不播放) } ``` **最佳实践**: - 结合方法一使用效果更佳 - 适合网络视频场景 --- #### 方法四:SurfaceView 替代方案 使用 SurfaceView 实现更精细控制: ```java public class VideoActivity extends AppCompatActivity implements SurfaceHolder.Callback { private MediaPlayer mediaPlayer; private SurfaceView surfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video); surfaceView = findViewById(R.id.surfaceView); surfaceView.getHolder().addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { try { mediaPlayer = new MediaPlayer(); mediaPlayer.setDataSource(...); mediaPlayer.setDisplay(holder); // 设置准备监听 mediaPlayer.setOnPreparedListener(mp -> { // 设置透明背景 surfaceView.setBackgroundColor(Color.TRANSPARENT); mp.start(); }); mediaPlayer.prepareAsync(); // 异步准备 } catch (IOException e) { e.printStackTrace(); } } } ``` **优势**:更精细的控制权 **复杂度**:实现相对复杂[^1] --- ### 关键优化技巧 1. **统一封面图与视频比例**: ```xml <ImageView ... android:scaleType="centerCrop" android:adjustViewBounds="true"/> ``` 2. **添加加载动画**: ```java // 显示加载进度 ProgressBar progressBar = findViewById(R.id.progressBar); mVideoView.setOnInfoListener((mp, what, extra) -> { if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { progressBar.setVisibility(View.VISIBLE); } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { progressBar.setVisibility(View.GONE); } return false; }); ``` 3. **错误处理**: ```java mVideoView.setOnErrorListener((mp, what, extra) -> { // 显示错误信息或重试按钮 return true; }); ``` --- ### 相关问题 1. 如何实现 VideoView 的全屏播放功能?[^2] 2. 如何处理 VideoView 播放网络视频时的缓冲问题?[^1] 3. 如何为 VideoView 添加自定义控制面板?[^3] 4. VideoView 和 ExoPlayer 在性能上有哪些差异?[^2] 5. 如何实现视频播放器的画中画(PIP)模式?[^1] 通过以上方法,可以有效解决 Android VideoView 播放视频前的短暂黑屏问题,提升用户体验[^2][^3]。
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值