I am using the DraggablePanel library (https://github.com/pedrovgs/DraggablePanel) to facilitate a YouTube like video player. If you are not familiar with this feature it basically allows the user to shrink the currently playing video into a small thumbnail that is docked into the corner of the screen.
Unfortunately (and I am not so sure this is an issue with the above library) I have noticed that if I apply an X and Y scale on the parent view of a VideoView, the VideoView itself will not resize its content to match.
See below screenshots, where VideoView is at its natural scale and then with its parent view scaled down to about 0.6:0.6. You should notice that in the scaled screenshot the VideoView has cropped its content instead of resizing to fit.
So I tried to force a width and height on the VideoView as its parent's scale changed. There are a few examples on the internet about overriding the dimensions of a VideoView - but here is my simple version:
public class ScalableVideoView extends VideoView {
private int mVideoWidth;
private int mVideoHeight;
public ScalableVideoView(Context context) {
super(context);
}
public ScalableVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalableVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mVideoWidth = 0;
mVideoHeight = 0;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mVideoWidth > 0 && mVideoHeight > 0) {
// If a custom dimension is specified, force it as the measured dimension
setMeasuredDimension(mVideoWidth, mVideoHeight);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void changeVideoSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
getHolder().setFixedSize(width, height);
requestLayout();
invalidate();
}
}
The fragment that contains the VideoView is responsible for calling changeVideoSize on it when it receives a notification from the DraggablePanel library about a change in scale. At which point I calculate a new pair of width and height based on the provided scale values. (scale is from 0f to 1f)
public void setVideoViewScale(float scaleX, float scaleY) {
if (mMaxVideoWidth == 0) {
mMaxVideoWidth = mVideoView.getWidth();
}
if (mMaxVideoHeight == 0) {
mMaxVideoHeight = mVideoView.getHeight();
}
if (mMaxVideoWidth > 0) {
mVideoView.changeVideoSize((int) (scaleX * mMaxVideoWidth),
(int) (scaleY * mMaxVideoHeight));
}
}
Unfortunately this causes some really interesting results. It seems that the Video portion of the VideoView is scaling appropriately - but the bounds of the VideoView seem to be scaling too fast (causing the video to both shrink and crop).
For further demonstration here are two videos:
I have also uploaded this sample project to GitHub so that you can see the complete code: https://github.com/npike/so_scalevideoview
I was having the same problem with my app, so I took your example that is much simpler, and tried to fix it.
This is the code that fixes the problem. Edit your changeVideoSize(int width, int height) method to:
public void changeVideoSize(int width, int height){
mVideoWidth = width;
mVideoHeight = height;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(width, height);
lp.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
lp.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
setLayoutParams(lp);
requestLayout();
invalidate();
}
With the invalidation of the view you force the VideoView to redraw the whole View with the new layout parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With