Elliptica Elliptica - 1 year ago 168
Android Question

How Can I Animate Changing the Size of a VideoView?

I have a VideoView that I want to change the size of dynamically in my app. By extending the VideoView class, I have successfully gotten both the video and videoView to change size correctly. However, I'd like to be able to transition between the two sizes more gradually. How can I do that? I've tried a scaling animation, but while that changes the VideoView layout's size, the video itself does not scale. Thoughts?

Here is my video class:

public class MyVideoView extends VideoView {

private int mForceHeight,mForceWidth;
private int mOrigWidth, mOrigHeight, mMinWidth, mMinHeight;

public MyVideoView(Context context) {

/* Will cause inflator errors if not present */
public MyVideoView(Context context, AttributeSet attrs){
super(context, attrs);

public void setDimensions(int w, int h) {
this.mForceHeight = h;
this.mForceWidth = w;

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (mForceHeight != 0)
setMeasuredDimension(mForceWidth, mForceHeight);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

public void setOrigDimens(int width, int height) {
mOrigWidth = width;
mOrigHeight = height;

mMinWidth = width/4; // My own decision for the small size
mMinHeight = height/4;

public void setSmallView() {
setNewViewSize(mMinWidth, mMinHeight);

public void setNormalView() {
setNewViewSize(mOrigWidth, mOrigHeight);

public void setNewViewSize(int width, int height) {
mForceWidth = width;
mForceHeight = height;
setDimensions(width, height);
getHolder().setFixedSize(width, height);

Here is the scaling code I tried:

Animation scaling = new ScaleAnimation(1.0f, 0.2f, 1.0f, 0.2f);

Any help is much appreciated!

Answer Source

The best answer is to simply use a TextureView instead of a SurfaceView (a VideoView inherits from a SurfaceView by default). To do this, use code as follows:

Define your TextureView in activity_main.xml:

    android:layout_height="match_parent />

In your MainActivity.java, declare the following variables:

private MediaPlayer mMediaPlayer;
private TextureView mVideoTextureView;
private float mDisplayWidth;
private float mDisplayHeight;

Then in your onCreate() method, initialize them as follows:

mVideoTextureView =(TextureView) rootview.findViewById(R.id.videoTexture);

mMediaPlayer = new MediaPlayer();

To load a movie into the MediaPlayer, use the following code:

private void loadNewMovie() {

    AssetFileDescriptor afd = this.getResources().openRawResourceFd(ID_OF_YOUR_MOVIE);

    try {

        // Set source

        mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());

        // Gets the Height/Width of the video but does NOT include space
        // taken up by black bars if the dimensions don't exactly fit the screen.

        MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
        metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
        String height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
        String width = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
        mVideoHeight = Float.parseFloat(height);
        mVideoWidth = Float.parseFloat(width);

        // Gets the size of the display in pixels (used for scaling)

        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();

        mDisplayWidth = size.x;
        mDisplayHeight = size.y;

        // Play movie

        if (currState == State.PLAYING)

    catch (Exception e) {
        Log.e("ERROR", "loadNewMovie: " + e.getMessage(), e);


Finally, your video can be adjusted instantaneously using the following code:

private void updateTextureViewSize(int viewWidth, int viewHeight) {

    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(viewWidth,viewHeight);

    // params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);


Or you can animate the change like this:

private void animateTextureViewScaling(final float endScaleX, final float endScaleY, int duration, final boolean scaleDown) {

    // Note: Can't just use .scaleX and .scaleY directly because it will only scale the video, not it's holder

        .setUpdateListener(new AnimatorUpdateListener() {

            float value, scalingX, scalingY;
            float changeXScale = 1 - endScaleX;
            float changeYScale = 1 - endScaleY;

            public void onAnimationUpdate(ValueAnimator animation) {
                value = (Float) animation.getAnimatedValue();

                if (scaleDown) {
                    scalingX = (float) (1 - changeXScale*value);
                    scalingY = (float) (1 - changeYScale*value);
                else {
                    scalingX = (float) (changeXScale*value);
                    scalingY = (float) (changeYScale*value);

                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                        (int) (mDisplayWidth*scalingX), (int) (mDisplayHeight*scalingY));

                // ANY OTHER RULES...EXAMPLE:
                // params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);



In the above code, I use mDisplayWidth (set in loadNewVideo()) as my video's original size. You can use whatever you want.

The benefits of this are that a TextureView can be animated, transformed, and scaled (a SurfaceView can't).

The cons are that a TextureView can only be used in a hardware accelerated window and will use much more memory (about 30%) more than a SurfaceView. It may also experience a 1 to 3 frame latency.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download