Skip to content

Instantly share code, notes, and snippets.

@JoaquimLey
Created April 12, 2017 16:02
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save JoaquimLey/3fda0c4492081a24d5610e6ab13569cc to your computer and use it in GitHub Desktop.
Save JoaquimLey/3fda0c4492081a24d5610e6ab13569cc to your computer and use it in GitHub Desktop.
A simple VideoView subclass that displays in full screen while keeping the aspect ration
/**
* Subclass of VideoView to enable video scaling
* CustomAttribute: "scaleType": "normal", "centerCrop", "fill"
* <p>
* Add this stylable:
* <declare-styleable name="IntroVideoView">
* <attr name="scaleType" format="integer">
* <flag name="normal" value="0" />
* <flag name="centerCrop" value="1" />
* <flag name="fill" value="2" />
* </attr>
* </declare-styleable>
* <p>
* Created by joaquimley on 13/01/2017.
*/
public class IntroVideoView extends VideoView {
private static final int SCALE_TYPE_NORMAL = 0;
private static final int SCALE_TYPE_CENTER_CROP = 1;
private static final int SCALE_TYPE_FILL = 2;
private int mScaleType;
private int mHorizontalAspectRatioThreshold;
private int mVerticalAspectRatioThreshold;
public IntroVideoView(Context context) {
this(context, null, 0);
}
public IntroVideoView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IntroVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.IntroVideoView, 0, 0);
mScaleType = attributes.getInt(R.styleable.IntroVideoView_scaleType, SCALE_TYPE_NORMAL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mScaleType == SCALE_TYPE_CENTER_CROP) {
applyCenterCropMeasure(widthMeasureSpec, heightMeasureSpec);
} else if (mScaleType == SCALE_TYPE_FILL) {
applyFillMeasure(widthMeasureSpec, heightMeasureSpec);
} // else default/no-op
}
@Override
public void layout(int l, int t, int r, int b) {
if (mScaleType == SCALE_TYPE_CENTER_CROP) {
applyCenterCropLayout(l, t, r, b);
} else {
super.layout(l, t, r, b);
}
}
private void applyCenterCropLayout(int left, int top, int right, int bottom) {
super.layout(left + mHorizontalAspectRatioThreshold, top + mVerticalAspectRatioThreshold, right
+ mHorizontalAspectRatioThreshold, bottom + mVerticalAspectRatioThreshold);
}
private void applyCenterCropMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int videoWidth = getMeasuredWidth();
int videoHeight = getMeasuredHeight();
int viewWidth = getDefaultSize(0, widthMeasureSpec);
int viewHeight = getDefaultSize(0, heightMeasureSpec);
mHorizontalAspectRatioThreshold = 0;
mVerticalAspectRatioThreshold = 0;
if (videoWidth == viewWidth) {
int newWidth = (int) ((float) videoWidth / videoHeight * viewHeight);
setMeasuredDimension(newWidth, viewHeight);
mHorizontalAspectRatioThreshold = -(newWidth - viewWidth) / 2;
} else {
int newHeight = (int) ((float) videoHeight / videoWidth * viewWidth);
setMeasuredDimension(viewWidth, newHeight);
mVerticalAspectRatioThreshold = -(newHeight - viewHeight) / 2;
}
}
private void applyFillMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getDefaultSize(0, widthMeasureSpec);
int height = getDefaultSize(0, heightMeasureSpec);
setMeasuredDimension(width, height);
}
}
@JoaquimLey
Copy link
Author

JoaquimLey commented Apr 12, 2017

And the stylable for the custom attributes:

<resources>
    <declare-styleable name="IntroVideoView">
        <attr name="scaleType" format="integer">
            <flag name="normal" value="0" />
            <flag name="centerCrop" value="1" />
            <flag name="fill" value="2" />
        </attr>
    </declare-styleable>
</resources>

@tsmrecki
Copy link

I came across an issue when using this in ViewPager.
I've set the scaleType to "centerCrop", the video behaves OK on one card, but when i swipe to second one, there still a part of video showing on the other card.
Aspect ratio of the video is wider than the card itself, so it looks like it just continues rendering on the next available surface.

Any fix for this?

9045523642352492674

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment