How to transform a videoview into a circular shape

2019-08-21 20:06发布

问题:

I want to play a video in full screen in a videoview and after some time I want to crop to a circular view?

How can I achieve that ?

回答1:

Another way is put this type of image overlay on your videoview Relative or FrameLayout (Circuler is transprent so videoview will visible only in circle)

By default make visibility GONE this imageView and Change VISIBLE it runtime when you want.

MAY BE HELPFUL TO YOU



回答2:

There is a better way.

You can create a custom SurfaceView. Which actually clips the view in circular shape. And from this custom view you can set display to MediaPlayer object.

public class VideoSurfaceView extends SurfaceView {

    private final static String TAG = "VideoSurfaceView";
    private Path clipPath;
    private boolean isCircular;

    public VideoSurfaceView(Context context) {
        super(context);
        init();
    }

    public VideoSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        clipPath = new Path();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (this.isCircular)
            canvas.clipPath(clipPath);
        super.dispatchDraw(canvas);
    }

    /**
     * Crops the view in circular shape
     * @param centerX
     * @param centerY
     * @param radius
     */
    public void cropCircle(float centerX, float centerY, int radius) {
        Log.i(TAG, "cropCircle: x=" + centerX + " ,y= " + centerY + ", radius=" + radius);
        clipPath.addCircle(centerX, centerY, radius, Path.Direction.CW);
    }

    /**
     * Sets the flag for cropping the view in circular shape
     * @param isCircular
     */
    public void setCircular(boolean isCircular) {
        this.isCircular = isCircular;
        invalidate();
    }
}

In your activity you can implement SurfaceHolder.Callback & set MediaPlayer's display in overridden method.

public class MainActivity extends AppCompatActivity implements MediaPlayer.OnCompletionListener, SurfaceHolder.Callback {
    private final static String TAG = "MainActivity";

    @BindView(R.id.activity_main_video_surface_view)
    protected VideoSurfaceView videoView;


    private Handler handler;
    private boolean inCircleMode;

    private final static int CIRCULAR_INTERVAL = 5000;
    private final static int MINIMUM_CARD_HEIGHT = 300;
    private final static int MAXIMUM_CARD_HEIGHT = 500;

    //Parameters for video view.
    private int cropCenterX;
    private int cropCenterY;
    private int cropRadius;
    private int croppedLayoutWidth;
    private int croppedLayoutHeight;
    private int fullLayoutWidth;
    private int fullLayoutHeight;

    private MediaPlayer player;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        initParameters();
    }

    /**
     * Initialise the parameters used.
     */
    private void initParameters() {

        SurfaceHolder holder = videoView.getHolder();
        holder.addCallback(this);

        player = MediaPlayer.create(this, R.raw.bird_s);
        player.setOnCompletionListener(this);

        //Setting the video with proper aspect ratio.
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int height = displayMetrics.heightPixels;
        int width = displayMetrics.widthPixels;
        int dimenFull[] = Utility.getVideoDimensions(player, width, height);
        fullLayoutWidth = dimenFull[0];
        fullLayoutHeight = dimenFull[1];

        setVideoLayout();
    }

    //Runnable for switching the views from circular video to full screen video.
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            inCircleMode = !inCircleMode;

            setVideoLayout();
            handler.postDelayed(runnable, CIRCULAR_INTERVAL);
        }
    };

    /**
     * Calculates the dimensions required for cropped video view.
     */
    private void calculateCroppedParams() {
        int dimen[] = Utility.getVideoDimensions(player, 100, 100); 
        croppedLayoutWidth = dimen[0];
        croppedLayoutHeight = dimen[1];

        cropRadius = croppedLayoutWidth / 2;
        cropCenterX = cropRadius;
        cropCenterY = cropRadius;
    }

    /**
     * Change the layout dimensions for video view.
     */
    private void setVideoLayout() {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) videoView.getLayoutParams();

        //Changing the margin, width & height of videoView.
        layoutParams.setMargins(0, inCircleMode ? cardView.getVideoMargin() : 0, 0, 0);
        layoutParams.width = inCircleMode ? croppedLayoutWidth : fullLayoutWidth;
        layoutParams.height = inCircleMode ? croppedLayoutHeight : fullLayoutHeight;
        layoutParams.addRule(inCircleMode ? RelativeLayout.CENTER_HORIZONTAL : RelativeLayout.CENTER_IN_PARENT);

        videoView.cropCircle(cropCenterX, cropCenterY, cropRadius);
        videoView.setCircular(inCircleMode);
        videoView.setLayoutParams(layoutParams);
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {

    }

    @Override
    public void onLayout() {
        Log.i(TAG, "onLayout: starting runnable");
        calculateCroppedParams();
        player.start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        player.setDisplay(surfaceHolder);
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    }

    @Override
    protected void onStop() {
        Log.i(TAG, "onStop");
        super.onStop();
     }

    @Override
    protected void onRestart() {
        super.onRestart();

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (player != null && player.isPlaying())
            player.pause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (player != null && !player.isPlaying())
            player.start();
    }
}

For more details on how to crop the video in different shapes, please check this blog post VideoInShapes.

Hope this helps.