How to fit video in Live wallpaper, by center-crop and by fitting to width/height?

后端 未结 5 1287
伪装坚强ぢ
伪装坚强ぢ 2020-12-08 09:42

Background

I\'m making a live wallpaper that can show a video. In the beginning I thought this is going to be very hard, so some people suggested using OpenGL solu

5条回答
  •  死守一世寂寞
    2020-12-08 09:57

    You can achieve this with a TextureView. (surfaceView won't work either).I have found some code which will help you for achieving this.
    in this demo you can crop the video in three type center, top & bottom.

    TextureVideoView.java

    public class TextureVideoView extends TextureView implements TextureView.SurfaceTextureListener {
    
        // Indicate if logging is on
        public static final boolean LOG_ON = true;
    
        // Log tag
        private static final String TAG = TextureVideoView.class.getName();
    
        private MediaPlayer mMediaPlayer;
    
        private float mVideoHeight;
        private float mVideoWidth;
    
        private boolean mIsDataSourceSet;
        private boolean mIsViewAvailable;
        private boolean mIsVideoPrepared;
        private boolean mIsPlayCalled;
    
        private ScaleType mScaleType;
        private State mState;
    
        public enum ScaleType {
            CENTER_CROP, TOP, BOTTOM
        }
    
        public enum State {
            UNINITIALIZED, PLAY, STOP, PAUSE, END
        }
    
        public TextureVideoView(Context context) {
            super(context);
            initView();
        }
    
        public TextureVideoView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
    
        public TextureVideoView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initView();
        }
    
        private void initView() {
            initPlayer();
            setScaleType(ScaleType.CENTER_CROP);
            setSurfaceTextureListener(this);
        }
    
        public void setScaleType(ScaleType scaleType) {
            mScaleType = scaleType;
        }
    
        private void updateTextureViewSize() {
            float viewWidth = getWidth();
            float viewHeight = getHeight();
    
            float scaleX = 1.0f;
            float scaleY = 1.0f;
    
            if (mVideoWidth > viewWidth && mVideoHeight > viewHeight) {
                scaleX = mVideoWidth / viewWidth;
                scaleY = mVideoHeight / viewHeight;
            } else if (mVideoWidth < viewWidth && mVideoHeight < viewHeight) {
                scaleY = viewWidth / mVideoWidth;
                scaleX = viewHeight / mVideoHeight;
            } else if (viewWidth > mVideoWidth) {
                scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight);
            } else if (viewHeight > mVideoHeight) {
                scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth);
            }
    
            // Calculate pivot points, in our case crop from center
            int pivotPointX;
            int pivotPointY;
    
            switch (mScaleType) {
                case TOP:
                    pivotPointX = 0;
                    pivotPointY = 0;
                    break;
                case BOTTOM:
                    pivotPointX = (int) (viewWidth);
                    pivotPointY = (int) (viewHeight);
                    break;
                case CENTER_CROP:
                    pivotPointX = (int) (viewWidth / 2);
                    pivotPointY = (int) (viewHeight / 2);
                    break;
                default:
                    pivotPointX = (int) (viewWidth / 2);
                    pivotPointY = (int) (viewHeight / 2);
                    break;
            }
    
            Matrix matrix = new Matrix();
            matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY);
    
            setTransform(matrix);
        }
    
        private void initPlayer() {
            if (mMediaPlayer == null) {
                mMediaPlayer = new MediaPlayer();
            } else {
                mMediaPlayer.reset();
            }
            mIsVideoPrepared = false;
            mIsPlayCalled = false;
            mState = State.UNINITIALIZED;
        }
    
        /**
         * @see MediaPlayer#setDataSource(String)
         */
        public void setDataSource(String path) {
            initPlayer();
    
            try {
                mMediaPlayer.setDataSource(path);
                mIsDataSourceSet = true;
                prepare();
            } catch (IOException e) {
                Log.d(TAG, e.getMessage());
            }
        }
    
        /**
         * @see MediaPlayer#setDataSource(Context, Uri)
         */
        public void setDataSource(Context context, Uri uri) {
            initPlayer();
    
            try {
                mMediaPlayer.setDataSource(context, uri);
                mIsDataSourceSet = true;
                prepare();
            } catch (IOException e) {
                Log.d(TAG, e.getMessage());
            }
        }
    
        /**
         * @see MediaPlayer#setDataSource(java.io.FileDescriptor)
         */
        public void setDataSource(AssetFileDescriptor afd) {
            initPlayer();
    
            try {
                long startOffset = afd.getStartOffset();
                long length = afd.getLength();
                mMediaPlayer.setDataSource(afd.getFileDescriptor(), startOffset, length);
                mIsDataSourceSet = true;
                prepare();
            } catch (IOException e) {
                Log.d(TAG, e.getMessage());
            }
        }
    
        private void prepare() {
            try {
                mMediaPlayer.setOnVideoSizeChangedListener(
                        new MediaPlayer.OnVideoSizeChangedListener() {
                            @Override
                            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                                mVideoWidth = width;
                                mVideoHeight = height;
                                updateTextureViewSize();
                            }
                        }
                );
                mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mState = State.END;
                        log("Video has ended.");
    
                        if (mListener != null) {
                            mListener.onVideoEnd();
                        }
                    }
                });
    
                // don't forget to call MediaPlayer.prepareAsync() method when you use constructor for
                // creating MediaPlayer
                mMediaPlayer.prepareAsync();
    
                // Play video when the media source is ready for playback.
                mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mediaPlayer) {
                        mIsVideoPrepared = true;
                        if (mIsPlayCalled && mIsViewAvailable) {
                            log("Player is prepared and play() was called.");
                            play();
                        }
    
                        if (mListener != null) {
                            mListener.onVideoPrepared();
                        }
                    }
                });
    
            } catch (IllegalArgumentException e) {
                Log.d(TAG, e.getMessage());
            } catch (SecurityException e) {
                Log.d(TAG, e.getMessage());
            } catch (IllegalStateException e) {
                Log.d(TAG, e.toString());
            }
        }
    
        /**
         * Play or resume video. Video will be played as soon as view is available and media player is
         * prepared.
         *
         * If video is stopped or ended and play() method was called, video will start over.
         */
        public void play() {
            if (!mIsDataSourceSet) {
                log("play() was called but data source was not set.");
                return;
            }
    
            mIsPlayCalled = true;
    
            if (!mIsVideoPrepared) {
                log("play() was called but video is not prepared yet, waiting.");
                return;
            }
    
            if (!mIsViewAvailable) {
                log("play() was called but view is not available yet, waiting.");
                return;
            }
    
            if (mState == State.PLAY) {
                log("play() was called but video is already playing.");
                return;
            }
    
            if (mState == State.PAUSE) {
                log("play() was called but video is paused, resuming.");
                mState = State.PLAY;
                mMediaPlayer.start();
                return;
            }
    
            if (mState == State.END || mState == State.STOP) {
                log("play() was called but video already ended, starting over.");
                mState = State.PLAY;
                mMediaPlayer.seekTo(0);
                mMediaPlayer.start();
                return;
            }
    
            mState = State.PLAY;
            mMediaPlayer.start();
        }
    
        /**
         * Pause video. If video is already paused, stopped or ended nothing will happen.
         */
        public void pause() {
            if (mState == State.PAUSE) {
                log("pause() was called but video already paused.");
                return;
            }
    
            if (mState == State.STOP) {
                log("pause() was called but video already stopped.");
                return;
            }
    
            if (mState == State.END) {
                log("pause() was called but video already ended.");
                return;
            }
    
            mState = State.PAUSE;
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
            }
        }
    
        /**
         * Stop video (pause and seek to beginning). If video is already stopped or ended nothing will
         * happen.
         */
        public void stop() {
            if (mState == State.STOP) {
                log("stop() was called but video already stopped.");
                return;
            }
    
            if (mState == State.END) {
                log("stop() was called but video already ended.");
                return;
            }
    
            mState = State.STOP;
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.pause();
                mMediaPlayer.seekTo(0);
            }
        }
    
        /**
         * @see MediaPlayer#setLooping(boolean)
         */
        public void setLooping(boolean looping) {
            mMediaPlayer.setLooping(looping);
        }
    
        /**
         * @see MediaPlayer#seekTo(int)
         */
        public void seekTo(int milliseconds) {
            mMediaPlayer.seekTo(milliseconds);
        }
    
        /**
         * @see MediaPlayer#getDuration()
         */
        public int getDuration() {
            return mMediaPlayer.getDuration();
        }
    
        static void log(String message) {
            if (LOG_ON) {
                Log.d(TAG, message);
            }
        }
    
        private MediaPlayerListener mListener;
    
        /**
         * Listener trigger 'onVideoPrepared' and `onVideoEnd` events
         */
        public void setListener(MediaPlayerListener listener) {
            mListener = listener;
        }
    
        public interface MediaPlayerListener {
    
            public void onVideoPrepared();
    
            public void onVideoEnd();
        }
    
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
            Surface surface = new Surface(surfaceTexture);
            mMediaPlayer.setSurface(surface);
            mIsViewAvailable = true;
            if (mIsDataSourceSet && mIsPlayCalled && mIsVideoPrepared) {
                log("View is available and play() was called.");
                play();
            }
        }
    
        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    
        }
    
        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            return false;
        }
    
        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    
        }
    }
    

    After that use this class like the below code in MainActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener,
            ActionBar.OnNavigationListener {
    
        // Video file url
        private static final String FILE_URL = "http://techslides.com/demos/sample-videos/small.mp4";
        private TextureVideoView mTextureVideoView;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initView();
            initActionBar();
    
            if (!isWIFIOn(getBaseContext())) {
                Toast.makeText(getBaseContext(), "You need internet connection to stream video",
                        Toast.LENGTH_LONG).show();
            }
        }
    
        private void initActionBar() {
            ActionBar actionBar = getSupportActionBar();
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
            actionBar.setDisplayShowTitleEnabled(false);
    
            SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
                    android.R.layout.simple_spinner_dropdown_item);
            actionBar.setListNavigationCallbacks(mSpinnerAdapter, this);
        }
    
        private void initView() {
            mTextureVideoView = (TextureVideoView) findViewById(R.id.cropTextureView);
    
            findViewById(R.id.btnPlay).setOnClickListener(this);
            findViewById(R.id.btnPause).setOnClickListener(this);
            findViewById(R.id.btnStop).setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btnPlay:
                    mTextureVideoView.play();
                    break;
                case R.id.btnPause:
                    mTextureVideoView.pause();
                    break;
                case R.id.btnStop:
                    mTextureVideoView.stop();
                    break;
            }
        }
    
        final int indexCropCenter = 0;
        final int indexCropTop = 1;
        final int indexCropBottom = 2;
    
        @Override
        public boolean onNavigationItemSelected(int itemPosition, long itemId) {
            switch (itemPosition) {
                case indexCropCenter:
                    mTextureVideoView.stop();
                    mTextureVideoView.setScaleType(TextureVideoView.ScaleType.CENTER_CROP);
                    mTextureVideoView.setDataSource(FILE_URL);
                    mTextureVideoView.play();
                    break;
                case indexCropTop:
                    mTextureVideoView.stop();
                    mTextureVideoView.setScaleType(TextureVideoView.ScaleType.TOP);
                    mTextureVideoView.setDataSource(FILE_URL);
                    mTextureVideoView.play();
                    break;
                case indexCropBottom:
                    mTextureVideoView.stop();
                    mTextureVideoView.setScaleType(TextureVideoView.ScaleType.BOTTOM);
                    mTextureVideoView.setDataSource(FILE_URL);
                    mTextureVideoView.play();
                    break;
            }
            return true;
        }
    
        public static boolean isWIFIOn(Context context) {
            ConnectivityManager connMgr =
                    (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    
            return (networkInfo != null && networkInfo.isConnected());
        }
    }
    

    and layout activity_main.xml file for that is below

    
    
        
    
        
    
            

    Output of the code for center crop look like

提交回复
热议问题