如何动画更改VideoView的大小?

时间:2016-08-20 01:02:45

标签: android animation transition android-videoview

我有一个VideoView,我想在我的应用中动态更改大小。通过扩展VideoView类,我成功地获得了视频和videoView以正确地改变大小。但是,我希望能够逐渐在两种尺寸之间进行转换。我怎样才能做到这一点?我尝试过缩放动画,但是虽然这会改变VideoView布局的大小,但视频本身并没有缩放。想法?

这是我的视频课程:

public class MyVideoView extends VideoView {

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


    public MyVideoView(Context context) {
        super(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;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (mForceHeight != 0)
            setMeasuredDimension(mForceWidth, mForceHeight);
        else
            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);
    }


    /* RESIZES THE VIEW */
    public void setNewViewSize(int width, int height) {
        mForceWidth = width;
        mForceHeight = height;
        setDimensions(width, height);
        getHolder().setFixedSize(width, height);
    }
}

这是我尝试过的缩放代码:

Animation scaling = new ScaleAnimation(1.0f, 0.2f, 1.0f, 0.2f);
scaling.setDuration(2000);
startAnimation(scaling);

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

我找到的一个解决方案是使用ValueAnimator更改大小应该是的比率,然后使用更新侦听器强制视频实际更改大小。然而,它非常紧张:

ValueAnimator scaleDown = ValueAnimator.ofFloat(1, 0.25f);
    scaleDown.setDuration(1000);

    scaleDown.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            Float value = (Float) animation.getAnimatedValue();
            setNewViewSize(mOrigWidth*value, mOrigHeight*value);
        }
    });

    scaleDown.start();

答案 1 :(得分:0)

最佳答案是简单地使用 TextureView 而不是SurfaceView(默认情况下VideoView继承自SurfaceView)。为此,请使用以下代码:

activity_main.xml中定义TextureView:

<TextureView
    android:id="@+id/videoTexture"
    android:layout_width="match_parent"
    android:layout_height="match_parent />

MainActivity.java中,声明以下变量:

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

然后在onCreate()方法中,按如下方式初始化它们:

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

mMediaPlayer = new MediaPlayer();
loadNewMovie();

要将影片加载到MediaPlayer,请使用以下代码:

private void loadNewMovie() {

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

    try {

        // Set source

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

        /*
        // 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();
        display.getSize(size);

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

        // Play movie

        if (currState == State.PLAYING)
            mMediaPlayer.start();

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

    mMediaPlayer.seekTo(DEFAULT_VIDEO_INIT_POSITION);
}

最后,您可以使用以下代码即时调整视频:

private void updateTextureViewSize(int viewWidth, int viewHeight) {

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

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

    mVideoTextureView.setLayoutParams(params);
}

或者你可以像这样对变化进行动画处理:

private void animateTextureViewScaling(final float startScaleX, final float startScaleY, 
                                       final float endScaleX, final float endScaleY, 
                                       int duration) {

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

    mVideoTextureView.animate().setDuration(duration)
        .setUpdateListener(new AnimatorUpdateListener() {

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

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

                scalingX = (float) (startScaleX - changeXScale*value);
                scalingY = (float) (startScaleX - changeYScale*value);

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

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

                mVideoTextureView.setLayoutParams(params);
            }

        }).start();
}

在上面的代码中,我使用mDisplayWidth(在loadNewVideo()中设置)作为我视频的原始尺寸。你可以随心所欲地使用它。

的好处是可以对TextureView进行动画制作,转换和缩放(SurfaceView不能)。

缺点是TextureView只能在硬件加速窗口中使用,并且比SurfaceView使用更多的内存(约30%)。它也可能会出现1到3帧延迟。