首先,原生的VideoView是继承SurfaceView加上媒体控制器,不能直接处理。而对TextureView centerCrop的原理很简单,如下:
在onVideoSizeChanged方法
if (videoWidth == 0 || videoHeight == 0) {
return;
}
float sx = (float) getWidth() / (float) videoWidth;
float sy = (float) getHeight() / (float) videoHeight;
float maxScale = Math.max(sx, sy);
sx = maxScale / sx;
sy = maxScale / sy;
Matrix matrix = new Matrix();
matrix.setScale(sx, sy, getWidth() / 2f, getHeight() / 2f);
if (matrix != null) {
setTransform(matrix);
}
更多的类型可以参考
https://github.com/codeguyFred/Android-ScalableVideoView
在自定义View的入口加上setSurfaceTextureListener监听
但是有些手机onSurfaceTextureAvailable回调会不够及时。
如果mMediaPlayer.setSurface(mSurface);中的mSurface是null的你会出现黑屏的情况。
完整代码如下
/**
* https://github.com/codeguyFred/Android-ScalableVideoView
* Created by leida on 2019/09/25.
* centerCrop视频,单纯展示
* 正确使用方法
* vBgVideo.post(() -> **);
*/
public class ScaleVideoView extends TextureView implements TextureView.SurfaceTextureListener,
MediaPlayer.OnVideoSizeChangedListener {
protected MediaPlayer mMediaPlayer;
private Surface mSurface = null;
public ScaleVideoView(Context context) {
this(context, null);
}
public ScaleVideoView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScaleVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setSurfaceTextureListener(this);
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
mSurface = new Surface(surfaceTexture);
if (mMediaPlayer != null) {
mMediaPlayer.setSurface(mSurface);
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mMediaPlayer == null) {
return;
}
if (isPlaying()) {
stop();
}
release();
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
scaleVideoSize(width, height);
}
private void scaleVideoSize(int videoWidth, int videoHeight) {
if (videoWidth == 0 || videoHeight == 0) {
return;
}
float sx = (float) getWidth() / (float) videoWidth;
float sy = (float) getHeight() / (float) videoHeight;
float maxScale = Math.max(sx, sy);
sx = maxScale / sx;
sy = maxScale / sy;
Matrix matrix = new Matrix();
matrix.setScale(sx, sy, getWidth() / 2f, getHeight() / 2f);
if (matrix != null) {
setTransform(matrix);
}
}
private void initializeMediaPlayer() {
if (mMediaPlayer == null) {
mMediaPlayer = new MediaPlayer();
} else {
reset();
}
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.setSurface(mSurface);
}
public void setRawData(@RawRes int id) throws IOException {
AssetFileDescriptor afd = getResources().openRawResourceFd(id);
setDataSource(afd);
}
public void setAssetData(@NonNull String assetName) throws IOException {
AssetManager manager = getContext().getAssets();
AssetFileDescriptor afd = manager.openFd(assetName);
setDataSource(afd);
}
private void setDataSource(@NonNull AssetFileDescriptor afd) throws IOException {
setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
}
public void setDataSource(@NonNull String path) throws IOException {
initializeMediaPlayer();
mMediaPlayer.setDataSource(path);
}
public void setDataSource(@NonNull Context context, @NonNull Uri uri,
@Nullable Map<String, String> headers) throws IOException {
initializeMediaPlayer();
mMediaPlayer.setDataSource(context, uri, headers);
}
public void setDataSource(@NonNull Context context, @NonNull Uri uri) throws IOException {
initializeMediaPlayer();
mMediaPlayer.setDataSource(context, uri);
}
public void setDataSource(@NonNull FileDescriptor fd, long offset, long length)
throws IOException {
initializeMediaPlayer();
mMediaPlayer.setDataSource(fd, offset, length);
}
public void setDataSource(@NonNull FileDescriptor fd) throws IOException {
initializeMediaPlayer();
mMediaPlayer.setDataSource(fd);
}
public void prepare(@Nullable MediaPlayer.OnPreparedListener listener)
throws IOException, IllegalStateException {
mMediaPlayer.setOnPreparedListener(listener);
mMediaPlayer.prepare();
}
public void prepareAsync(@Nullable MediaPlayer.OnPreparedListener listener)
throws IllegalStateException {
mMediaPlayer.setOnPreparedListener(listener);
mMediaPlayer.prepareAsync();
}
public void prepare() throws IOException, IllegalStateException {
prepare(null);
}
public void prepareAsync() throws IllegalStateException {
prepareAsync(null);
}
public void setOnErrorListener(@Nullable MediaPlayer.OnErrorListener listener) {
mMediaPlayer.setOnErrorListener(listener);
}
public void setOnCompletionListener(@Nullable MediaPlayer.OnCompletionListener listener) {
mMediaPlayer.setOnCompletionListener(listener);
}
public void setOnInfoListener(@Nullable MediaPlayer.OnInfoListener listener) {
mMediaPlayer.setOnInfoListener(listener);
}
public int getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
public int getDuration() {
return mMediaPlayer.getDuration();
}
public int getVideoHeight() {
return mMediaPlayer.getVideoHeight();
}
public int getVideoWidth() {
return mMediaPlayer.getVideoWidth();
}
public boolean isLooping() {
return mMediaPlayer.isLooping();
}
public void setLooping(boolean looping) {
mMediaPlayer.setLooping(looping);
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void pause() {
mMediaPlayer.pause();
}
public void seekTo(int msec) {
mMediaPlayer.seekTo(msec);
}
public void setVolume(float leftVolume, float rightVolume) {
mMediaPlayer.setVolume(leftVolume, rightVolume);
}
public void start() {
if (mMediaPlayer != null) {
mMediaPlayer.start();
}
}
public void stop() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
}
}
public void reset() {
if (mMediaPlayer != null) {
mMediaPlayer.reset();
}
}
public void release() {
if (mMediaPlayer != null) {
reset();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
使用方法
vBgVideo.post(() -> playBgVideo());
private void playBgVideo() {
try {
vBgVideo.setRawData(R.raw.login_bg_video);
vBgVideo.setVolume(0, 0);
vBgVideo.setLooping(true);
vBgVideo.prepare(mp -> vBgVideo.start()
);
} catch (IOException e) {
//忽略
}
}