android - studio - VideoView onPrepared no se llama si VideoView es invisible
videos para android studio (4)
Lo resolvió haciendo su diseño invisible en lugar de videoView. Gracias a @ J.Kowalski.
Diseño:
<FrameLayout
android:id="@+id/layout_video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<VideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:scrollbars="none"/>
</FrameLayout>
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
/>
Establecer OnPreparedListener:
videoView.setOnPreparedListener(this);
Mostrar barra de progreso antes de estar listo:
@Override
public void showProgress() {
progress.setVisibility(View.VISIBLE);
layoutVideoView.setVisibility(View.INVISIBLE);
}
Cargar video URI:
@Override
public void loadVideo(Uri uri) {
videoView.setVideoURI(uri);
}
Cuando está listo, onPrepared se llama:
@Override
public void onPrepared(MediaPlayer mp) {
Log.d("debug", "onPrepared");
iStepPreviewPresenter.onVideoViewReady();
}
Finalmente mostrar el diseño y comenzar el video:
@Override
public void hideProgress() {
progress.setVisibility(View.INVISIBLE);
layoutVideoView.setVisibility(View.VISIBLE);
}
@Override
public void startVideo() {
videoView.start();
}
¡Dado en el clavo!
Estoy ocultando el VideoView
inicialmente y cuando el video está cargado, estoy mostrando el VideoView
. Pero onPrepared
nunca se llama si el VideoView
es inicialmente invisible
. Sin embargo, se llama correctamente a VideoView
si VideoView
es visible. ¿Hay alguna manera de ocultar el videoView
hasta que se cargue el video. Cualquier ayuda sería apreciada. ¡Gracias!
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<VideoView
android:id="@+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:visibility="invisible" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VideoView videoView = (VideoView) findViewById(R.id.video);
Uri videoUri = Uri.parse(url);
videoView.setVideoURI(videoUri);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Toast.makeText(mActivity, "on prepared", Toast.LENGTH_SHORT).show();
videoView.setVisibility(View.VISIBLE);
}
});
}
Puede intentar configurar el canal alfa de la vista de video en 0 o cerca de 0.
Se puede lograr mediante uno de estos trucos.
Puede configurar el alto y el ancho de
VideoView
a1px
hasta que el video esté preparado y luego cambiar a pantalla completa cambiando las propiedades para quematch parent
Como @FDIM dijo en su respuesta, podemos establecer el valor alfa de la vista en 0 hasta que el video esté preparado. Pero funciona solo si usamos TextureView para cargar el video. No funciona con
VideoView
normal. Aquí hay un VideoView personalizado que amplíaTextureView
que imita la implementación predeterminada deVideoVideo
. Esta clase se puede usar directamente en un archivo xml y puede configurar el alfa en 0 para ocultar el video.public class TextureVideoView extends TextureView implements SurfaceTextureListener { private MediaPlayer mMediaPlayer; public TextureVideoView(Context context) { super(context); init(); } public TextureVideoView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mMediaPlayer = new MediaPlayer(); this.setSurfaceTextureListener(this); } public void seekTo(int msec) { mMediaPlayer.seekTo(msec); } public void setVideoPath(final String path) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(path); mMediaPlayer.prepare(); } public void setVideoPath(FileDescriptor fd, long offset, long length) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(fd, offset, length); mMediaPlayer.prepare(); } public void setVideoURI(Context context, Uri uri) throws IOException { mMediaPlayer.reset(); mMediaPlayer.setDataSource(context, uri); } public void setOnPreparedListener(OnPreparedListener onPreparedListener) { mMediaPlayer.setOnPreparedListener(onPreparedListener); } public void setOnCompletionListener(OnCompletionListener onCompletionListener) { mMediaPlayer.setOnCompletionListener(onCompletionListener); } public void setOnErrorListener(OnErrorListener onErrorListener) { mMediaPlayer.setOnErrorListener(onErrorListener); } public void start() { mMediaPlayer.start(); } public void pause() { mMediaPlayer.pause(); } public void setVolume(float leftVolume, float rightVolume ) { mMediaPlayer.setVolume(leftVolume, rightVolume); } public boolean isPlaying() { return mMediaPlayer.isPlaying(); } public void stopPlayback() { mMediaPlayer.stop(); } public void reset() { mMediaPlayer.reset(); } public void release() { mMediaPlayer.release(); } @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { mMediaPlayer.setSurface(new Surface(surface)); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { }
Una solución más fácil:
Solo agregue una vista parentview
ficticia para la parentview
de parentview
y configure la visiblity
para esa vista parentview
lugar de cambiar la visibility
de la vista de videoview
sí.