¡Acostúmbrate a escribir juntos! Este es el cuarto día de mi participación en el "Nuevo plan diario de los Nuggets·Desafío de actualización de abril", haz clic para ver los detalles del evento .
Introducción a VideoView
Previamente introduje el uso de MediaPlayer
+ SurfaceView
para realizar la función de reproducción de video. Accidentalmente descubrí que los VideoView
componentes oficiales empaquetados para realizar la función de reproducción de video simple, y el formulario MediaPlayer
+ SurfaceView
también se usa para controlar MediaPlayer
la reproducción de archivos de video. El escenario de uso es relativamente simple y es adecuado para el escenario de solo reproducir el video. Su capacidad limitada no es adecuada para otras funciones, como ajustar el brillo del video.
MediaController
Además del componente de reproducción VideoView
, también hay un MediaController
componente que proporciona una función de barra de operación de reproducción para reproducción de video, que admite reproducción de video, pausa, avance rápido, retroceso rápido y otras funciones. Además, también proporciona una función de barra de progreso que se puede arrastrar a una posición específica para reproducir el video.
usar
VideoView
El paquete MediaPlayer
también proporciona una MediaPlayer
API similar. Por ejemplo start
, el método también tiene la función de reproducir video, pero es mejor configurar el setOnpreparedListener
resultado de la devolución de llamada antes de llamar al método para ejecutar el método, y el método setVideoPath
se ejecutará activamente después de prepareAsync
que se llame al método. Ayuda a los desarrolladores a encapsular e implementar muchas funciones internamente. De VideoView
hecho, también puede aprender de su código fuente interno para crear un reproductor propio más amplio y completo.
API comunes | ilustrar |
---|---|
establecer ruta de video | Configurar recursos de video |
comienzo | jugar |
pausa | pausa |
resumir | repetición |
tratar de | Juega en una ubicación específica |
está jugando | Si el video se está reproduciendo |
obtenerPosiciónActual | Obtener la posición de reproducción actual |
establecerMediaController | Configurar MediaController |
setOnpreparedListener | Escuche el evento de finalización de carga de video |
// 实例化videoView
videoView = new VideoView(this);
Uri uri = Uri.fromFile(new File("sdcard/DCIM","新世纪福音战士24.mp4"));
//加载视频资源
videoView.setVideoURI(uri);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.addView(videoView);
setContentView(linearLayout);
//设置监听
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//回调成功并播放视频
videoView.start();
}
});
//创建操作栏
MediaController mediaController = new MediaController(this);
videoView.setMediaController(mediaController);
mediaController.setMediaPlayer(videoView);
复制代码
Análisis de código fuente
VideoView
Ahora que los dos componentes están encapsulados MediaController
, muchas funciones que se han intentado implementar antes se encuentran en el proceso de uso para ver cómo se implementan.
pantalla de progreso
MediaController
show
Se puede ver un post(mShowProgress);
método dentro del método de llamada cuando se muestra
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
disableUnsupportedButtons();
updateFloatingWindowLayout();
mWindowManager.addView(mDecor, mDecorLayoutParams);
mShowing = true;
}
updatePausePlay();
// cause the progress bar to be updated even if mShowing
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
post(mShowProgress);
if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
removeCallbacks(mFadeOut);
postDelayed(mFadeOut, timeout);
}
}
复制代码
Se puede ver que mShowProgress
es uno Runnable
, y el retardo interno se llamará a sí mismo para actualizar setProgress()
. setProgress()
El método consiste en leer el MediaPlayer
progreso de la reproducción para actualizar la información de reproducción.
private final Runnable mShowProgress = new Runnable() {
@Override
public void run() {
int pos = setProgress();
if (!mDragging && mShowing && mPlayer.isPlaying()) {
postDelayed(mShowProgress, 1000 - (pos % 1000));
}
}
};
复制代码
Adaptación al tamaño del juego
Antes de personalizar la adaptación del tamaño de la reproducción, VideoView
ayuda directamente a los desarrolladores a lograr la adaptación de la reproducción de video internamente. El código detallado se puede reescribir onMeasure
directamente . El algoritmo aproximado del código consiste VideoView
en reescribir el ancho y el alto calculados comparando el ancho y el alto del diseño y el ancho y el alto del video VideoView
.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if ( mVideoWidth * height < width * mVideoHeight ) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if ( mVideoWidth * height > width * mVideoHeight ) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
setMeasuredDimension(width, height);
}
复制代码