随笔博文

Android-任意屏幕永不变形的背景视频播放View

2023-03-03 09:44:30 michael007js 162

前言:

播放视频TextureView要比SurfaceView更加合适,尤其是视频是以背景的形式。

技术点:

背景视频就是一张动态的图片,图片的ScaleType可以支持centerCrop,视频咱们可以自己造

centerCrop原理解析:用Video最大的一条边(一般指Height)与容器View最大边计算比例,进行等比缩放。


系统api解析:

android.graphics.Matrix

setScale(float sx,float sy,float px,float py):设置Matrix以px,py为轴心进行缩放,sx,sy控制X,Y方向上的缩放比例;


完整源码:


public class BgVideoView extends TextureView implements TextureView.SurfaceTextureListener, MediaPlayer.OnVideoSizeChangedListener {

 protected MediaPlayer mMediaPlayer;

 public BgVideoView(Context context) {
     this(context, null);
 }

 public BgVideoView(Context context, AttributeSet attrs) {
     this(context, attrs, 0);
 }

 public BgVideoView(Context context, AttributeSet attrs, int defStyle) {
     super(context, attrs, defStyle);
 }

 @Override
 public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
     Surface surface = new Surface(surfaceTexture);
     if (mMediaPlayer != null) {
         mMediaPlayer.setSurface(surface);
     }
 }

 @Override
 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
 }

 @Override
 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
     return false;
 }

 @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;
     }
     Size viewSize = new Size(getWidth(), getHeight());
     Size videoSize = new Size(videoWidth, videoHeight);
     Matrix matrix = getScaleMatrix(viewSize, videoSize);
     if (matrix != null) {
         setTransform(matrix);
     }
 }

 private Matrix getScaleMatrix(Size mViewSize, Size mVideoSize) {
     float sx = (float) mViewSize.getWidth() / mVideoSize.getWidth();
     float sy = (float) mViewSize.getHeight() / mVideoSize.getHeight();
     float maxScale = Math.max(sx, sy);
     sx = maxScale / sx;
     sy = maxScale / sy;

     Matrix matrix = new Matrix();
     matrix.setScale(sx, sy, mViewSize.getWidth() / 2f, mViewSize.getHeight() / 2f);
     return matrix;
 }

 private void initializeMediaPlayer() {
     if (mMediaPlayer == null) {
         mMediaPlayer = new MediaPlayer();
         mMediaPlayer.setOnVideoSizeChangedListener(this);
         setSurfaceTextureListener(this);
     } else {
         reset();
     }
 }

 public void setRawData(@RawRes int id) throws IOException {
     AssetFileDescriptor afd = getResources().openRawResourceFd(id);
     setDataSource(afd);
 }

 private void setDataSource(@NonNull AssetFileDescriptor afd) throws IOException {
     setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
     afd.close();
 }

 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 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 boolean isPlaying() {
     return mMediaPlayer.isPlaying();
 }

 public void pause() {
     mMediaPlayer.pause();
 }

 public void setLooping(boolean looping) {
     mMediaPlayer.setLooping(looping);
 }

 public void setVolume(float leftVolume, float rightVolume) {
     mMediaPlayer.setVolume(leftVolume, rightVolume);
 }

 public void start() {
     mMediaPlayer.start();
 }

 public void stop() {
     mMediaPlayer.stop();
 }

 public void reset() {
     mMediaPlayer.reset();
 }

 public void release() {
     reset();
     mMediaPlayer.release();
     mMediaPlayer = null;
 }
}




首页
关于博主
我的博客
搜索