Cropping video in different shapes in Android
Just before I start, I want you to check following shapes.
Many times in your app you deal with images, you might be showing in a list or on a profile page or any where else. Normally the image is in rectangular shape only.
But what if you apply these shapes to a profile picture. That will definitely make your view look good. For examples check following picture.
There are many libraries available to give shapes to your images. For example the above pic is taken from the library CustomShapeImageView.
But what if I have to take it one step further & apply these shapes on a video. Wouldn?t that be more exciting? ???
To crop a video in any shape can be done in many ways for e.g. you can mask a VideoView with shape(.xml) resource. You can create shapes & apply over your VideoView.
But in my approach I am not using any default VideoView, instead I want to create a custom view that can be used to play a video on it.
So let?s start with my approach. As mentioned I will be creating a custom view, for that I am extending SurfaceView class.
Here is the code.
VideoSurfaceView.java
As you can see I have extended the class SurfaceView class with all the required constructors. Now we have created a surface, now it?s time to draw on it, for that I am overriding dispatchDraw() method of SurfaceView.
@Override protected void dispatchDraw(Canvas canvas) { if (this.inOtherShape) canvas.clipPath(shapePath); super.dispatchDraw(canvas); }
If you see that method I have used a flag inOtherShape for checking whether we need a different shape or not. If set it uses clipPath() method which uses a Path object shapePath, which actually clips the canvas to give a specified shape.
Now let?s move to other methods cropCircle(), cropOval(), cropRect() & setOtherShape(). You can see the crop methods actually initializing the shapePath object & adding shapes like circle, oval & rectangle to the path. These methods take coordinates, radius or width & height parameters for positioning & size of the shape.
The last method setOtherShape() actually updates the flag & uses invalidate(), which actually means redraw the view & in result calls dispatchDraw() method. The dispatchDraw() again checks the flag & clips the canvas in set path.
Now we are done with our surface. Now it?s time to use it & play our video on it. Following is the layout file, which uses the VideoSurfaceView & some buttons for different shapes. You can find the full source code from here.
activity_crop_video.xml
Now let?s create an activity CropVideoActivity.
In above activity you can see I have inflated all the required views & initialized the MediaPlayer object player, which is created by video file placed under raw resource. You can see from VideoSurfaceView object I am getting a SurfaceHolder & adding a callback on that, which makes me implement following three methods.
Whenever the surfaceCreated() callback method is called, I take that surfaceHolder object set on player object as display & then starts the player by start() method.
By doing this much only you will be able to play the video on your custom VideoSurfaceView & also you can use methods cropCircle(), cropOval(), cropRect() & setOtherShape() to give shapes to video.
Although you have done enough to crop a video in specified shape. But there may be one issue in that, the videos full or cropped may not maintain the aspect ratio of your video. The video may look creepy ?, which of course you don?t want. To solve that issue other parameters are used.
private int fullLayoutWidth;private int fullLayoutHeight;private int screenWidth;private int screenHeight;
fullLayoutWidth & fullLayoutHeight, these will be the dimensions of the video in full size, which will maintain the aspect ratio of the video. To maintain the aspect ratio on device of any size, I first get the width & height of the device?s screen, which are screenWidth & screenHeight respectively. I am using following method to calculate the width & height which will maintain the aspect ratio of video.
In this method I pass the MediaPlayer object, width & height for which you want to calculate the dimensions which will maintain the aspect ratio.
Initially, I used this method for full screen & calculates the fullLayoutWidth & fullLayoutHeight. Once calculated, I call setVideoLayout() method, by passing values FULL, fullLayoutWidth & fullLayoutHeight. The method resets the LayoutParams of VideoSurfaceView object along with the shape parameters.
It checks Shape enum, calls the crop shape method accordingly & setOtherShape() to draw view in specified shape.
The following methods calls the setVideoLayout() method but with different shapes & parameters. Here I am using screenWidth & screenHeight for creating shapes, you can pass your own values there.
You can change any parameters like center coordinates & radius for circle shape or left, top positions for other shapes.
In my case the results looks like below images.
You can also update the VideoSurfaceView class to create more shapes. You can find the full source code at VideoInShape.
I hope you like this & you learned something useful from here.
? Happy Coding ?