我一直在寻找一种方法来摆脱VideoView在运行
start()
方法之前出现的令人讨厌的黑色初始屏幕。
我试着在小组件上添加背景图片,但是根本没有达到预期的效果。
我也试过把视频中第一帧的图像放在VideoView的顶部,并在
start()
方法后将其隐藏。
添加一个onPrepared监听器来启动视频,然后隐藏图像。这很有效,但在过渡过程中出现了可怕的闪烁,我不知道如何摆脱它。
添加MediaController完全没有效果。问题仍然存在(我仍然看到黑色的闪烁),我根本不想让视频控件可见。
我的代码看起来像这样。
VideoView vSurface= (VideoView) findViewById(R.id.surfaceView1);
vSurface.setVideoURI(Uri.parse("android.resource://com.mypackage/" + R.raw.video1));
vSurface.setVisibility(View.VISIBLE);
vSurface.setOnPreparedListener(this);
vSurface.setDrawingCacheEnabled(true);
vSurface.setOnErrorListener(this);
24 个回答
0 人赞同
我遇到了同样的问题,用上面接受的解决方案加上这个来解决。
@Override
public void onPrepared(MediaPlayer mp) {
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onInfo, what = " + what);
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
// video started; hide the placeholder.
placeholder.setVisibility(View.GONE);
return true;
return false;
我认为onPrepared只是意味着视频准备好了,但不意味着视频开始播放。如果在onPrepared中隐藏占位符,屏幕仍然显示黑屏。
在我的Note3和Nexus上,这个解决方案运作良好。
0 人赞同
我在Galaxy tab 2上有同样的问题,Android 4.1.1。
Do videoView.setZOrderOnTop(true);
and next videoView.start()
It works fine for me.
0 人赞同
我也遇到了同样的问题,我找到了一个解决方案。虽然有点麻烦,但还是有效果的。
所以基本上你需要把你的VideoView放到一个FrameLayout中。
在视频视图上,你需要添加另一个带有视频背景的FrameLayout,当你的视频被加载并准备好播放时,你要隐藏这个占位符。
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="@+id/geoloc_anim"
android:layout_width="fill_parent"
android:layout_height="172dip" android:layout_gravity="top|center" android:visibility="visible"/>
<FrameLayout
android:id="@+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="@drawable/fondvert_anim">
</FrameLayout>
public void onPrepared(MediaPlayer mp) {
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
因此,当视频准备好后,我们隐藏我们的占位符,这一招避免了黑色闪烁的屏幕。
Hope this help someone.
0 人赞同
我也有同样的问题,这个方法对我有用。
当你想显示视频时,让videoView.setZOrderOnTop(false);而当你想隐藏视频时,只要让videoView.setZOrderOnTop(true)。
0 人赞同
我也有同样的问题,我只是用videov.setBackgroundColor(Color.WHITE),然后在prepare时用Color.TRANSPARENT),对我来说白色还是比黑色好。
0 人赞同
通过扩展TextureView,我在开始和结束时都没有黑屏。这是如果你想避免使用ZOrderOnTop(true)
。
public class MyVideoView extends TextureView implements TextureView.SurfaceTextureListener {
private MediaPlayer mMediaPlayer;
private Uri mSource;
private MediaPlayer.OnCompletionListener mCompletionListener;
private boolean isLooping = false;
public MyVideoView(Context context) {
this(context, null, 0);
public MyVideoView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setSurfaceTextureListener(this);
public void setSource(Uri source) {
mSource = source;
public void setOnCompletionListener(MediaPlayer.OnCompletionListener listener) {
mCompletionListener = listener;
public void setLooping(boolean looping) {
isLooping = looping;
@Override
protected void onDetachedFromWindow() {
// release resources on detach
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
super.onDetachedFromWindow();
* TextureView.SurfaceTextureListener
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Surface surface = new Surface(surfaceTexture);
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setLooping(isLooping);
mMediaPlayer.setDataSource(getContext(), mSource);
mMediaPlayer.setSurface(surface);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
mMediaPlayer.reset();
} catch (IOException e) {
e.printStackTrace();
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
surface.release();
return true;
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
0 人赞同
上述方法对我都不起作用。
在我的例子中,onPrepared
是在黑框消失之前被调用的,所以我还是会看到黑框。
我需要一个解决方案,视频在第一帧后不久出现。
所以我所做的是在xml中把VideoView的alpha设置为0。
android:alpha="0"
然后在我开始视频之前,我把阿尔法动画化为1。
videoView.animate().alpha(1);
videoView.seekTo(0);
videoView.start();
或者,你可以直接发布一个延迟的Runnable,将alpha设置为1,而不是将其做成动画。
0 人赞同
This worked for me:
videoView.setBackgroundColor(Color.WHITE); // Your color.
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
videoView.setBackgroundColor(Color.TRANSPARENT);
至少两年后,但我希望这对你有帮助。
0 人赞同
这绝对是黑客行为,但比叠加图像要好(IMO)。
boolean mRestored = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRestored = savedInstanceState != null;
@Override
public void onPrepared(MediaPlayer mp) {
if (!mRestored) vSurface.seekTo(1);
假设你把东西放进savedInstanceState
中的onSaveInstanceState
。
0 人赞同
只需从视频中显示一帧作为预览。
vSurface.SeekTo(100);
0 人赞同
我想,只要使用VideoView#setBackgroundDrawable()就可以了。
初始设置。
VideoView.setBackgroundDrawable(yourdrawableid);
VideoView.start();
VideoView.setBackgroundDrawable(0);
0 人赞同
对于仍在寻找答案的人来说,在onPrepared
中连续调用VideoView.start()
和VideoView.pause()
对我来说是有效的。我知道这可能不是实现这一目标的理想方法,但它可能是代码中需要的最小的变通方法。希望这对你也有用。
@Override
public void onPrepared(MediaPlayer mp) {
mVideoView.start();
mVideoView.pause();
0 人赞同
This one works for me :
在XML中:VideoView隐藏在一个具有白色背景的相对布局后面
<VideoView
android:id="@+id/myVideo"
android:layout_below="@+id/logo_top"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
<RelativeLayout
android:id="@+id/mask"
android:background="#FFFFFF"
android:layout_below="@+id/logo_top"
android:layout_centerHorizontal="true"
android:layout_width="200dp" android:layout_height="200dp"
</RelativeLayout>
并在活动中:onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.acceuil);
myVideo = (VideoView) findViewById(R.id.myVideo);
mask = (RelativeLayout) findViewById(R.id.mask);
String path = "android.resource://"
+ getPackageName() + "/" + R.raw.anim_normal;
myVideo.setVideoURI(Uri.parse(path));
myVideo.start();
onStart :
public void onStart() {
final long time = System.currentTimeMillis();
super.onStart();
new CountDownTimer(5000, 100) {
@Override
public void onTick(long l) {
long time2 = System.currentTimeMillis();
if((time2 - time) > 500) {
mask.setVisibility(View.GONE);
}.start();
Hope this helps.
0 人赞同
对我来说,设置setZOrderOnTop
并没有完全消除播放mp4视频时的初始黑框。然而,它确实减少了黑框出现的时间。我想完全消除最初的黑框,所以我玩了一下,发现将视频向前推进100ms就可以了。
注意,我正在循环使用该视频,所以如果你不想循环使用该视频,只需删除
mp.isLooping = true
Following is the snippet which I used to fix the issue:
val path = "android.resource://" + packageName + "/" + R.raw.my_video
videoView.setVideoURI(Uri.parse(path))
videoView.setZOrderOnTop(true)
videoView.seekTo(100)
videoView.start()
videoView.setOnPreparedListener { mp ->
videoView.setZOrderOnTop(false)
mp.isLooping = true // Loops the video
如果我得到一个确切的解释,说明上述工作的原因,如果有人觉得有帮助,那还是很好的。
0 人赞同
Use svVideoView.seekTo(position).
Give Position within 5 (ms).
onPause():
position=svVideoView.getCurrentPosition()
onResume():
svVideoView.seekTo(position);
0 人赞同
它对我来说在活动和片段上都有效。
VideoView mVideo = (VideoView) findViewById(R.id.yourViewViewId);
mVideo.setVideoURI(mUri);
mVideo.setZOrderOnTop(false);
SurfaceHolder surfaceholder = mVideo.getHolder();
surfaceholder.setFormat(PixelFormat.TRANSPARENT);
0 人赞同
这个答案有点晚了,但也许其他用户有同样的问题并发现这个问题。
我已经处理了这个问题,最初设置了一个BackgroundResource,然后在启动视频时,我将背景设置为不可见的颜色。
VideoView myView = findViewById(R.id.my_view);
myView.setBackgroundResource(R.drawable.some_resource);
// some stuff
// this is when starting the video
myView.setVideoUri(someUri);
// also set MediaController somewhere...
//...
// now set the backgroundcolor to be not visible (first val of Color.argb(..) is the alpha)
myView.setBackGroundColor(Color.argb(0, 0, 0, 0));
//...
myView.start();
0 人赞同
这是一个不错的解决方案。
package com.example.videoviewpractice;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;
public class MainActivity extends Activity {
VideoView myVideoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initVideo();
private void initVideo() {
myVideoView = (VideoView) findViewById(R.id.videoView1);
String url = "http://mtc.cdn.vine.co/r/videos/3DF00EB7001110633055418310656_1e50d6d9a65.3.2.mp4?" +
"versionId=KVMUFFGqe6rYRrGKgl8hxL6eakVAErPy";
myVideoView.setVideoURI(Uri.parse(url));
myVideoView.setMediaController(new MediaController(this));
myVideoView.requestFocus();
public void gone(View v){
myVideoView.setZOrderOnTop(true);
View placeholder = (View) findViewById(R.id.placeholder);
placeholder.setVisibility(View.GONE);
myVideoView.start();
activity_main.xml。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<FrameLayout
android:id="@+id/frameLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_marginTop="50dip" >
<VideoView
android:id="@+id/videoView1"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:visibility="visible" />
<FrameLayout
android:id="@+id/placeholder"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="top|center"
android:background="@drawable/ic_launcher"
android:onClick="gone" >
</FrameLayout>
</FrameLayout>
</LinearLayout>
0 人赞同
为了避免恼人的闪烁和黑屏问题,我写道帧视频视图.
它从 "占位符解决方案 "和(如果你的设备运行API级别14或更高)TextureView
中获取好处,这比VideoView
更有效。
I wrote 文章在我们的博客上,涵盖了它的实际作用。
It's simple to use:
Add FrameVideoView
to layout:
<mateuszklimek.framevideoview.FrameVideoView
android:id="@+id/frame_video_view"
android:layout_width="@dimen/video_width"
android:layout_height="@dimen/video_height"
在Activity
中找到其实例,并在onResume
和onPause
中调用相应的方法。
public class SampleActivity extends Activity {
private FrameVideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple);
String uriString = "android.resource://" + getPackageName() + "/" + R.raw.movie;
videoView = (FrameVideoView) findViewById(R.id.frame_video_view);
videoView.setup(Uri.parse(uriString), Color.GREEN);
@Override
protected void onResume() {
super.onResume();
videoView.onResume();
@Override
protected void onPause() {
videoView.onPause();
super.onPause();
0 人赞同
我也有同样的问题。我发现,主要原因是使用FrameLayout
作为父布局。使用RelativeLayout
作为VideoView
的父布局
0 人赞同
修改@emmgfx的答案对我有用。
videoView.setBackgroundColor(Color.WHITE)
videoView.start()
Timer().schedule(100){
videoView?.setBackgroundColor(Color.TRANSPARENT)
技巧是在视频加载前延迟视频浏览。
PS : 这是kotlin。
0 人赞同
我发现了一个解决这个问题的好办法。( 在Kotlin中 )
Create an imageview over top of your videoview.
Create a function with a handler, and check if ( videoview.duration > 0 )
如果持续时间大于0,则将imageview.visibility设置为INVISABLE,并立即用handler.removeCallbacks(this)进行跟踪。
在调用videoview.start后再调用上述函数。
Code below:
fun showVideoView() {
val handler = Handler()
handler.postDelayed(object : Runnable {
override fun run() {
try {
if (videoplayer_topthree.currentPosition > 0) {
videoview_topthreeloadingimage.visibility = View.INVISIBLE
videoview_topthreeprogressbar.visibility = View.VISIBLE
videoview_topthreefullname.visibility = View.VISIBLE
videoview_topthreeviews.visibility = View.VISIBLE
videoview_topthreedate.visibility = View.VISIBLE
videoview_topthreedescription.visibility = View.VISIBLE
videoview_topthreedimview.visibility = View.VISIBLE
handler.removeCallbacks(this)
handler.postDelayed(this, 250)
} catch (e: Exception) {
println("SHOW VIDEOVIEW CATCH WAS CAUGHT")
}, 0)
这就是我调用这个函数的地方。
videoplayer_topthree.setOnPreparedListener {
prepareSizing(it)
initializeProgressBar()
showVideoView()
0 人赞同
试图在一个大部分为白色的布局上播放一个大部分为白色的视频时,这些故障会以一种非常明显和恼人的方式显示出来,特别是在活动过渡期间。我设法完全摆脱这些故障的唯一方法是把这个主题的几个不同的答案和elprl的答案混在一起,即https://stackoverflow.com/a/9089245/3997253.
创建一个覆盖VideoView的纯色视图。
android:id="@+id/coverView"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在onCreate中
coverView = findViewById(R.id.coverView)
videoView = findViewById(R.id.videoView)
videoView.setZOrderOnTop(false)
val surfaceHolder = videoView.holder
surfaceHolder.setFormat(PixelFormat.TRANSPARENT)
在onStart
videoView.setOnPreparedListener { mp ->
// Fade out cover View to show VideoView once rendering has started
mp.setOnInfoListener { _, what, _ ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
coverView.animate().alpha(0F)
return@setOnInfoListener true
return@setOnInfoListener false
mp.isLooping = true
videoView.start()
videoView.requestFocus()
When done with the VideoView
// Fade in cover View to hide the VideoView
coverView.animate().alpha(1F)
0 人赞同
see this
VideoView videoView = (VideoView) findViewById(R.id.VideoView);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
Uri video = Uri.parse("android.resource://your_package_name/"+R.raw.monkeysonthebed_video);